Level 3#
Level 3 represents the highest level of user control and customization in Aviary’s user interface. At this level, users have full access to Python and OpenMDAO methods that Aviary calls. They can use the complete set of Aviary’s methods, functionalities, and classes to construct and fine-tune their aircraft models. Level 3 enables users to have supreme control over every aspect of the model, including subsystems, connections, and advanced optimization techniques.
Level 3 is the most complex but specific methods defined at this level are used in levels 1 and 2, hopefully reducing user activation energy when learning more about Aviary. This progressive approach helps users gradually enhance their analysis capabilities and adapt to more complex modeling requirements as they gain proficiency and experience.
We will show two approaches of level 3 development using two examples: The first one will implement all methods differently from what are available in aviary/interface/methods_for_level2.py but will follow the same steps. It will show that you don’t have to have a .csv input file and you don’t have to have a phase_info dictionary. The second is a solved_2DOF mission approach that is embedded into all the methods of aviary/interface/methods_for_level2.py.
Note
For each of these examples we have set max_iter = 0, which means that the optimization will not run. This is done to reduce the computational time for the examples. If you want to run the optimization, you can set max_iter = 100 or some similar value.
A level 3 example: N3CC#
In level 2, we have shown how to follow the standard steps to build an Aviary model, but sometimes you may find that the model you have in mind does not match that predefined structure. If you start a new model that cannot been embedded in those methods, we can write special methods ourselves. This example will show you how to do that.
In aviary/validation_cases/benchmark_tests folder, there is an N3CC aircraft full mission benchmark test test_FLOPS_based_sizing_N3CC.py. Now, we will show how to create an N3CC example in level3. The key is that we follow the same steps:
__init__()load_inputs()check_and_preprocess_inputs()build_model()add_pre_mission_systems()add_phases()add_post_mission_systems()link_phases()add_driver()add_design_variables()(optional)add_objective()setup()run_aviary_problem()
Examining an N3CC design case#
"""
NOTES:
Includes:
Takeoff, Climb, Cruise, Descent, Landing
Computed Aero
advanced_single_aisle data
"""
import dymos as dm
import openmdao.api as om
import scipy.constants as _units
import aviary.api as av
from aviary.validation_cases.validation_tests import get_flops_inputs
from aviary.variable_info.functions import setup_model_options
prob = om.Problem(model=om.Group())
driver = prob.driver = om.pyOptSparseDriver()
driver.options['optimizer'] = 'IPOPT'
driver.opt_settings['max_iter'] = 100
driver.opt_settings['tol'] = 1e-3
driver.opt_settings['print_level'] = 4
########################################
# Aircraft Input Variables and Options #
########################################
aviary_inputs = get_flops_inputs('AdvancedSingleAisle')
aviary_inputs.set_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX, 2.4, units='unitless')
aviary_inputs.set_val(av.Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, units='unitless')
aviary_inputs.set_val(av.Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=0.0175, units='unitless')
takeoff_fuel_burned = 577 # lbm
takeoff_thrust_per_eng = 24555.5 # lbf
takeoff_L_over_D = 17.35
aviary_inputs.set_val(av.Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm')
aviary_inputs.set_val(av.Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless')
aviary_inputs.set_val(av.Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf')
alt_airport = 0 # ft
cruise_mach = 0.79
alt_i_climb = 0 * _units.foot # m
alt_f_climb = 35000.0 * _units.foot # m
mass_i_climb = 131000 * _units.lb # kg
mass_f_climb = 126000 * _units.lb # kg
# initial mach set to lower value so it can intersect with takeoff end mach
# mach_i_climb = 0.3
mach_i_climb = 0.2
mach_f_climb = cruise_mach
range_i_climb = 0 * _units.nautical_mile # m
range_f_climb = 160.3 * _units.nautical_mile # m
t_i_climb = 2 * _units.minute # sec
t_f_climb = 26.20 * _units.minute # sec
t_duration_climb = t_f_climb - t_i_climb
alt_i_cruise = 35000 * _units.foot # m
alt_f_cruise = 35000 * _units.foot # m
alt_min_cruise = 35000 * _units.foot # m
alt_max_cruise = 35000 * _units.foot # m
mass_i_cruise = 126000 * _units.lb # kg
mass_f_cruise = 102000 * _units.lb # kg
cruise_mach = cruise_mach
range_i_cruise = 160.3 * _units.nautical_mile # m
range_f_cruise = 3243.9 * _units.nautical_mile # m
t_i_cruise = 26.20 * _units.minute # sec
t_f_cruise = 432.38 * _units.minute # sec
t_duration_cruise = t_f_cruise - t_i_cruise
alt_i_descent = 35000 * _units.foot
# final altitude set to 35 to ensure landing is feasible point
# alt_f_descent = 0*_units.foot
alt_f_descent = 35 * _units.foot
mach_i_descent = 0.79
mach_f_descent = 0.3
mass_i_descent = 102000 * _units.pound
mass_f_descent = 101000 * _units.pound
distance_i_descent = 3243.9 * _units.nautical_mile
distance_f_descent = 3378.7 * _units.nautical_mile
t_i_descent = 432.38 * _units.minute
t_f_descent = 461.62 * _units.minute
t_duration_descent = t_f_descent - t_i_descent
engines = [av.build_engine_deck(aviary_inputs)]
av.preprocess_options(aviary_inputs, engine_models=engines)
# define subsystems
aero = av.CoreAerodynamicsBuilder(code_origin=av.LegacyCode('FLOPS'))
geom = av.CoreGeometryBuilder(code_origin=av.LegacyCode('FLOPS'))
mass = av.CoreMassBuilder(code_origin=av.LegacyCode('FLOPS'))
prop = av.CorePropulsionBuilder(engine_models=engines)
premission_subsystems = [prop, geom, aero, mass]
mission_subsystems = [aero, prop]
####################
# Design Variables #
####################
# Nudge it a bit off the correct answer to verify that the optimize takes us there.
aviary_inputs.set_val(av.Mission.Design.GROSS_MASS, 135000.0, units='lbm')
aviary_inputs.set_val(av.Mission.Summary.GROSS_MASS, 135000.0, units='lbm')
prob.model.add_design_var(
av.Mission.Design.GROSS_MASS, units='lbm', lower=100000.0, upper=200000.0, ref=135000
)
prob.model.add_design_var(
av.Mission.Summary.GROSS_MASS, units='lbm', lower=100000.0, upper=200000.0, ref=135000
)
takeoff_options = av.HeightEnergyTakeoffPhaseBuilder(
airport_altitude=alt_airport, # ft
# no units
num_engines=aviary_inputs.get_val(av.Aircraft.Engine.NUM_ENGINES),
)
#################
# Define Phases #
#################
num_segments_climb = 6
num_segments_cruise = 1
num_segments_descent = 5
climb_seg_ends, _ = dm.utils.lgl.lgl(num_segments_climb + 1)
descent_seg_ends, _ = dm.utils.lgl.lgl(num_segments_descent + 1)
transcription_climb = dm.Radau(
num_segments=num_segments_climb, order=3, compressed=True, segment_ends=climb_seg_ends
)
transcription_cruise = dm.Radau(num_segments=num_segments_cruise, order=3, compressed=True)
transcription_descent = dm.Radau(
num_segments=num_segments_descent, order=3, compressed=True, segment_ends=descent_seg_ends
)
climb_options = av.HeightEnergyPhaseBuilder(
'test_climb',
user_options={
'altitude_optimize': (False, 'unitless'),
'altitude_initial': (alt_i_climb, 'm'),
'altitude_final': (alt_f_climb, 'm'),
'mach_optimize': (False, 'unitless'),
'mach_initial': (mach_i_climb, 'unitless'),
'mach_final': (mach_f_climb, 'unitless'),
},
subsystems=mission_subsystems,
subsystem_options={'aerodynamics': {'method': 'computed'}},
transcription=transcription_climb,
)
cruise_options = av.HeightEnergyPhaseBuilder(
'test_cruise',
user_options={
'altitude_optimize': (False, 'unitless'),
'altitude_polynomial_order': 3,
'altitude_initial': (alt_min_cruise, 'm'),
'altitude_final': (alt_max_cruise, 'm'),
'mach_optimize': (False, 'unitless'),
'mach_polynomial_order': 3,
'mach_initial': (cruise_mach, 'unitless'),
'mach_final': (cruise_mach, 'unitless'),
'required_available_climb_rate': (300, 'ft/min'),
},
subsystems=mission_subsystems,
subsystem_options={'aerodynamics': {'method': 'computed'}},
transcription=transcription_cruise,
)
descent_options = av.HeightEnergyPhaseBuilder(
'test_descent',
user_options={
'altitude_optimize': (False, 'unitless'),
'altitude_final': (alt_f_descent, 'm'),
'altitude_initial': (alt_i_descent, 'm'),
'mach_optimize': (False, 'unitless'),
'mach_initial': (mach_i_descent, 'unitless'),
'mach_final': (mach_f_descent, 'unitless'),
},
subsystems=mission_subsystems,
subsystem_options={'aerodynamics': {'method': 'computed'}},
transcription=transcription_descent,
)
landing_options = av.HeightEnergyLandingPhaseBuilder(
ref_wing_area=aviary_inputs.get_val(av.Aircraft.Wing.AREA, units='ft**2'),
Cl_max_ldg=aviary_inputs.get_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX), # no units
)
# Upstream pre-mission analysis for aero
prob.model.add_subsystem(
'pre_mission',
av.CorePreMission(aviary_options=aviary_inputs, subsystems=premission_subsystems),
promotes_inputs=['aircraft:*', 'mission:*'],
promotes_outputs=['aircraft:*', 'mission:*'],
)
# directly connect phases (strong_couple = True), or use linkage constraints (weak
# coupling / strong_couple=False)
strong_couple = False
takeoff = takeoff_options.build_phase(False)
climb = climb_options.build_phase(aviary_options=aviary_inputs)
climb.set_state_options('mass', fix_initial=False, input_initial=True)
climb.set_state_options('distance', fix_initial=False, input_initial=True)
climb.set_control_options('altitude', fix_initial=False)
climb.set_control_options('mach', fix_initial=False)
cruise = cruise_options.build_phase(aviary_options=aviary_inputs)
cruise.set_state_options('mass', fix_initial=False, input_initial=False)
cruise.set_state_options('distance', fix_initial=False, input_initial=False)
cruise.set_control_options('mach', fix_initial=False)
descent = descent_options.build_phase(aviary_options=aviary_inputs)
descent.set_state_options('mass', fix_initial=False, input_initial=False)
descent.set_state_options('distance', fix_initial=False, input_initial=False)
descent.set_control_options('mach', fix_initial=False)
landing = landing_options.build_phase(False)
prob.model.add_subsystem(
'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=['mission:*']
)
traj = prob.model.add_subsystem('traj', dm.Trajectory())
# if fix_initial is false, can we always set input_initial to be true for
# necessary states, and then ignore if we use a linkage?
climb.set_time_options(
fix_initial=True,
fix_duration=False,
units='s',
duration_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),
duration_ref=t_duration_climb,
)
cruise.set_time_options(
fix_initial=False,
fix_duration=False,
units='s',
duration_bounds=(t_duration_cruise * 0.5, t_duration_cruise * 2),
duration_ref=t_duration_cruise,
initial_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),
)
descent.set_time_options(
fix_initial=False,
fix_duration=False,
units='s',
duration_bounds=(t_duration_descent * 0.5, t_duration_descent * 2),
duration_ref=t_duration_descent,
initial_bounds=(
(t_duration_cruise + t_duration_climb) * 0.5,
(t_duration_cruise + t_duration_climb) * 2,
),
)
traj.add_phase('climb', climb)
traj.add_phase('cruise', cruise)
traj.add_phase('descent', descent)
prob.model.add_subsystem(
'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=['mission:*']
)
###############
# link phases #
###############
phases = ['climb', 'cruise', 'descent']
traj.link_phases(
phases, ['time', av.Dynamic.Vehicle.MASS, av.Dynamic.Mission.DISTANCE], connected=strong_couple
)
# loop through phases and get all subsystem parameters
external_parameters = {}
for phase_name in phases:
external_parameters[phase_name] = {}
for subsystem in mission_subsystems:
parameter_dict = subsystem.get_parameters(phase_info={}, aviary_inputs=aviary_inputs)
for parameter in parameter_dict:
external_parameters[phase_name][parameter] = parameter_dict[parameter]
traj = av.setup_trajectory_params(
prob.model, traj, aviary_inputs, phases, external_parameters=external_parameters
)
##################################
# Connect in Takeoff and Landing #
##################################
prob.model.connect(av.Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass')
prob.model.connect(av.Mission.Takeoff.GROUND_DISTANCE, 'traj.climb.initial_states:distance')
prob.model.connect('traj.descent.states:mass', av.Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])
prob.model.connect(
'traj.descent.control_values:altitude', av.Mission.Landing.INITIAL_ALTITUDE, src_indices=[-1]
)
###############
# Constraints #
###############
ecomp = om.ExecComp(
'fuel_burned = initial_mass - descent_mass_final',
initial_mass={'units': 'lbm', 'shape': 1},
descent_mass_final={'units': 'lbm', 'shape': 1},
fuel_burned={'units': 'lbm', 'shape': 1},
)
prob.model.add_subsystem(
'fuel_burn',
ecomp,
promotes_inputs=[('initial_mass', av.Mission.Design.GROSS_MASS)],
promotes_outputs=['fuel_burned'],
)
prob.model.connect('traj.descent.states:mass', 'fuel_burn.descent_mass_final', src_indices=[-1])
ecomp = om.ExecComp(
'overall_fuel = fuel_burned + fuel_reserve',
fuel_burned={'units': 'lbm', 'shape': 1},
fuel_reserve={'units': 'lbm', 'val': 2173.0},
overall_fuel={'units': 'lbm'},
)
prob.model.add_subsystem(
'fuel_calc', ecomp, promotes_inputs=['fuel_burned'], promotes_outputs=['overall_fuel']
)
ecomp = om.ExecComp(
'mass_resid = operating_empty_mass + overall_fuel + payload_mass - initial_mass',
operating_empty_mass={'units': 'lbm'},
overall_fuel={'units': 'lbm'},
payload_mass={'units': 'lbm'},
initial_mass={'units': 'lbm'},
mass_resid={'units': 'lbm'},
)
prob.model.add_subsystem(
'mass_constraint',
ecomp,
promotes_inputs=[
('operating_empty_mass', av.Mission.Summary.OPERATING_MASS),
'overall_fuel',
('payload_mass', av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS),
('initial_mass', av.Mission.Design.GROSS_MASS),
],
promotes_outputs=['mass_resid'],
)
prob.model.add_constraint('mass_resid', equals=0.0, ref=1.0)
prob.model.add_subsystem(
'gtow_constraint',
om.EQConstraintComp(
'GTOW',
eq_units='lbm',
normalize=True,
add_constraint=True,
),
promotes_inputs=[
('lhs:GTOW', av.Mission.Design.GROSS_MASS),
('rhs:GTOW', av.Mission.Summary.GROSS_MASS),
],
)
##########################
# Add Objective Function #
##########################
# This is an example of a overall mission objective
# create a compound objective that minimizes climb time and maximizes final mass
# we are maxing final mass b/c we don't have an independent value for fuel_mass yet
# we are going to normalize these (making each of the sub-objectives approx = 1 )
prob.model.add_subsystem(
'regularization',
om.ExecComp(
'reg_objective = fuel_mass/1500',
reg_objective=0.0,
fuel_mass={'units': 'lbm', 'shape': 1},
),
promotes_outputs=['reg_objective'],
)
# connect the final mass from cruise into the objective
prob.model.connect(av.Mission.Summary.FUEL_MASS, 'regularization.fuel_mass')
prob.model.add_objective('reg_objective', ref=1)
# Set initial default values for all LEAPS aircraft variables.
varnames = [
av.Aircraft.Engine.SCALE_FACTOR,
av.Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN,
av.Aircraft.Wing.SWEEP,
av.Aircraft.Wing.TAPER_RATIO,
av.Aircraft.Wing.THICKNESS_TO_CHORD,
av.Mission.Design.GROSS_MASS,
av.Mission.Summary.GROSS_MASS,
]
av.set_aviary_input_defaults(prob.model, varnames, aviary_inputs)
av.setup_model_options(prob, aviary_inputs)
prob.setup()
phase = prob.model.traj.phases.cruise
phase.nonlinear_solver = om.NonlinearRunOnce()
phase.linear_solver = om.LinearRunOnce()
if isinstance(phase.indep_states, om.ImplicitComponent):
phase.indep_states.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)
phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True)
phase = prob.model.traj.phases.descent
phase.nonlinear_solver = om.NonlinearRunOnce()
phase.linear_solver = om.LinearRunOnce()
if isinstance(phase.indep_states, om.ImplicitComponent):
phase.indep_states.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)
phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True)
av.set_aviary_initial_values(prob, aviary_inputs)
############################################
# Initial Settings for States and Controls #
############################################
prob.set_val('traj.climb.t_initial', t_i_climb, units='s')
prob.set_val('traj.climb.t_duration', t_duration_climb, units='s')
prob.set_val(
'traj.climb.controls:altitude',
climb.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]),
units='m',
)
prob.set_val(
'traj.climb.controls:mach',
climb.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_climb, mach_f_climb]),
units='unitless',
)
prob.set_val(
'traj.climb.states:mass',
climb.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_climb, mass_f_climb]),
units='kg',
)
prob.set_val(
'traj.climb.states:distance',
climb.interp(av.Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]),
units='m',
)
prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')
prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')
prob.set_val(
'traj.cruise.controls:altitude',
cruise.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]),
units='m',
)
prob.set_val(
'traj.cruise.controls:mach',
cruise.interp(av.Dynamic.Atmosphere.MACH, ys=[cruise_mach, cruise_mach]),
units='unitless',
)
prob.set_val(
'traj.cruise.states:mass',
cruise.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_cruise, mass_f_cruise]),
units='kg',
)
prob.set_val(
'traj.cruise.states:distance',
cruise.interp(av.Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]),
units='m',
)
prob.set_val('traj.descent.t_initial', t_i_descent, units='s')
prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')
prob.set_val(
'traj.descent.controls:altitude',
descent.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]),
units='m',
)
prob.set_val(
'traj.descent.controls:mach',
descent.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_descent, mach_f_descent]),
units='unitless',
)
prob.set_val(
'traj.descent.states:mass',
descent.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_descent, mass_f_descent]),
units='kg',
)
prob.set_val(
'traj.descent.states:distance',
descent.interp(av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]),
units='m',
)
# Turn off solver printing so that the optimizer output is readable.
prob.set_solver_print(level=0)
dm.run_problem(
prob,
simulate=False,
make_plots=False,
solution_record_file='N3CC_sizing.db',
)
prob.record('final')
prob.cleanup()
times_climb = prob.get_val('traj.climb.timeseries.time', units='s')
altitudes_climb = prob.get_val('traj.climb.timeseries.altitude', units='m')
masses_climb = prob.get_val('traj.climb.timeseries.mass', units='kg')
ranges_climb = prob.get_val('traj.climb.timeseries.distance', units='m')
velocities_climb = prob.get_val('traj.climb.timeseries.velocity', units='m/s')
thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')
times_cruise = prob.get_val('traj.cruise.timeseries.time', units='s')
altitudes_cruise = prob.get_val('traj.cruise.timeseries.altitude', units='m')
masses_cruise = prob.get_val('traj.cruise.timeseries.mass', units='kg')
ranges_cruise = prob.get_val('traj.cruise.timeseries.distance', units='m')
velocities_cruise = prob.get_val('traj.cruise.timeseries.velocity', units='m/s')
thrusts_cruise = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N')
times_descent = prob.get_val('traj.descent.timeseries.time', units='s')
altitudes_descent = prob.get_val('traj.descent.timeseries.altitude', units='m')
masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg')
ranges_descent = prob.get_val('traj.descent.timeseries.distance', units='m')
velocities_descent = prob.get_val('traj.descent.timeseries.velocity', units='m/s')
thrusts_descent = prob.get_val('traj.descent.timeseries.thrust_net_total', units='N')
print('-------------------------------')
print(f'times_climb: {times_climb[-1]} (s)')
print(f'altitudes_climb: {altitudes_climb[-1]} (m)')
print(f'masses_climb: {masses_climb[-1]} (kg)')
print(f'ranges_climb: {ranges_climb[-1]} (m)')
print(f'velocities_climb: {velocities_climb[-1]} (m/s)')
print(f'thrusts_climb: {thrusts_climb[-1]} (N)')
print(f'times_cruise: {times_cruise[-1]} (s)')
print(f'altitudes_cruise: {altitudes_cruise[-1]} (m)')
print(f'masses_cruise: {masses_cruise[-1]} (kg)')
print(f'ranges_cruise: {ranges_cruise[-1]} (m)')
print(f'velocities_cruise: {velocities_cruise[-1]} (m/s)')
print(f'thrusts_cruise: {thrusts_cruise[-1]} (N)')
print(f'times_descent: {times_descent[-1]} (s)')
print(f'altitudes_descent: {altitudes_descent[-1]} (m)')
print(f'masses_descent: {masses_descent[-1]} (kg)')
print(f'ranges_descent: {ranges_descent[-1]} (m)')
print(f'velocities_descent: {velocities_descent[-1]} (m/s)')
print(f'thrusts_descent: {thrusts_descent[-1]} (N)')
print('-------------------------------')
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:4656: OpenMDAOWarning:Calling `list_inputs` before `final_setup` will only display the default values of variables and will not show the result of any `set_val` calls.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.propulsion.turbofan_22k' <class SizeEngine>: input variable 'aircraft:engine:scale_factor', promoted using 'aircraft:engine:scale_factor', was already promoted using 'aircraft:engine:scale_factor'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.canard' <class Canard>: input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.canard' <class Canard>: input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.canard' <class Canard>: input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fus_ratios' <class _FuselageRatios>: input variable 'aircraft:fuselage:ref_diameter', promoted using 'aircraft:fuselage:ref_diameter', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fus_ratios' <class _FuselageRatios>: input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fus_ratios' <class _FuselageRatios>: input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fus_ratios' <class _FuselageRatios>: input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fus_ratios' <class _FuselageRatios>: input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:fuselage:ref_diameter', promoted using 'aircraft:fuselage:ref_diameter', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.fuselage' <class _Fuselage>: input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.nacelle_characteristic_lengths' <class NacelleCharacteristicLength>: input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.nacelle_characteristic_lengths' <class NacelleCharacteristicLength>: input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.nacelles' <class Nacelles>: input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.nacelles' <class Nacelles>: input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.nacelles' <class Nacelles>: input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.tail' <class _Tail>: input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.tail' <class _Tail>: input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.tail' <class _Tail>: input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.tail' <class _Tail>: input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.tail' <class _Tail>: input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing' <class _Wing>: input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing' <class _Wing>: input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing_characteristic_lengths' <class WingCharacteristicLength>: input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing_characteristic_lengths' <class WingCharacteristicLength>: input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing_characteristic_lengths' <class WingCharacteristicLength>: input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing_characteristic_lengths' <class WingCharacteristicLength>: input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/core/system.py:2769: PromotionWarning:'pre_mission.geometry.wing_characteristic_lengths' <class WingCharacteristicLength>: input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/dymos/transcriptions/transcription_base.py:449: OpenMDAOWarning:'traj.phases.climb' <class Phase>
Non-default solvers are required
implicit parameters: False
solved segments: False
input initial: True
Setting `traj.phases.climb.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`
Explicitly set traj.phases.climb.nonlinear_solver to override.
Setting `traj.phases.climb.linear_solver = om.DirectSolver(iprint=2)`
Explicitly set traj.phases.climb.linear_solver to override.
Set `traj.phases.climb.options["auto_solvers"] = False` to disable this behavior.
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/utils/relevance.py:1295: OpenMDAOWarning:The following groups have a nonlinear solver that computes gradients and will be treated as atomic for the purposes of determining which systems are included in the optimization iteration:
traj.phases.climb
traj.phases.cruise.rhs_all.solver_sub
traj.phases.descent.rhs_all.solver_sub
List of user-set options:
Name Value used
file_print_level = 5 yes
hessian_approximation = limited-memory yes
linear_solver = mumps yes
max_iter = 100 yes
nlp_scaling_method = user-scaling yes
output_file = /home/runner/work/Aviary/Aviary/aviary/docs/getting_started/problem_out/IPOPT.out yes
print_level = 4 yes
print_user_options = yes yes
sb = yes yes
tol = 0.001 yes
Number of Iterations....: 0
Number of objective function evaluations = 0
Number of objective gradient evaluations = 0
Number of equality constraint evaluations = 0
Number of inequality constraint evaluations = 1
Number of equality constraint Jacobian evaluations = 0
Number of inequality constraint Jacobian evaluations = 0
Number of Lagrangian Hessian evaluations = 0
Total seconds in IPOPT = 0.213
EXIT: Invalid number in NLP function or derivative detected.
Optimization Problem -- Optimization using pyOpt_sparse
================================================================================
Objective Function: _objfunc
Solution:
--------------------------------------------------------------------------------
Total Time: 0.2147
User Objective Time : 0.2125
User Sensitivity Time : 0.0000
Interface Time : 0.0003
Opt Solver Time: 0.0019
Calls to Objective Function : 1
Calls to Sens Function : 0
Objectives
Index Name Value
0 reg_objective 0.000000E+00
Variables (c - continuous, i - integer, d - discrete)
Index Name Type Lower Bound Value Upper Bound Status
0 mission:design:gross_mass_0 c 7.407407E-01 1.000000E+00 1.481481E+00
1 mission:summary:gross_mass_0 c 7.407407E-01 1.000000E+00 1.481481E+00
2 traj.climb.t_duration_0 c 5.000000E-01 1.000000E+00 2.000000E+00
3 traj.climb.states:mass_0 c 0.000000E+00 5.935225E+00 1.000000E+17
4 traj.climb.states:mass_1 c 0.000000E+00 5.925793E+00 1.000000E+17
5 traj.climb.states:mass_2 c 0.000000E+00 5.922808E+00 1.000000E+17
6 traj.climb.states:mass_3 c 0.000000E+00 5.908258E+00 1.000000E+17
7 traj.climb.states:mass_4 c 0.000000E+00 5.888182E+00 1.000000E+17
8 traj.climb.states:mass_5 c 0.000000E+00 5.881829E+00 1.000000E+17
9 traj.climb.states:mass_6 c 0.000000E+00 5.862952E+00 1.000000E+17
10 traj.climb.states:mass_7 c 0.000000E+00 5.836905E+00 1.000000E+17
11 traj.climb.states:mass_8 c 0.000000E+00 5.828662E+00 1.000000E+17
12 traj.climb.states:mass_9 c 0.000000E+00 5.809785E+00 1.000000E+17
13 traj.climb.states:mass_10 c 0.000000E+00 5.783739E+00 1.000000E+17
14 traj.climb.states:mass_11 c 0.000000E+00 5.775495E+00 1.000000E+17
15 traj.climb.states:mass_12 c 0.000000E+00 5.760946E+00 1.000000E+17
16 traj.climb.states:mass_13 c 0.000000E+00 5.740870E+00 1.000000E+17
17 traj.climb.states:mass_14 c 0.000000E+00 5.734516E+00 1.000000E+17
18 traj.climb.states:mass_15 c 0.000000E+00 5.727681E+00 1.000000E+17
19 traj.climb.states:mass_16 c 0.000000E+00 5.718249E+00 1.000000E+17
20 traj.climb.states:mass_17 c 0.000000E+00 5.715264E+00 1.000000E+17
21 traj.climb.states:distance_0 c 0.000000E+00 8.947709E-03 1.000000E+15
22 traj.climb.states:distance_1 c 0.000000E+00 2.129372E-02 1.000000E+15
23 traj.climb.states:distance_2 c 0.000000E+00 2.520119E-02 1.000000E+15
24 traj.climb.states:distance_3 c 0.000000E+00 4.424674E-02 1.000000E+15
25 traj.climb.states:distance_4 c 0.000000E+00 7.052571E-02 1.000000E+15
26 traj.climb.states:distance_5 c 0.000000E+00 7.884292E-02 1.000000E+15
27 traj.climb.states:distance_6 c 0.000000E+00 1.035527E-01 1.000000E+15
28 traj.climb.states:distance_7 c 0.000000E+00 1.376470E-01 1.000000E+15
29 traj.climb.states:distance_8 c 0.000000E+00 1.484378E-01 1.000000E+15
30 traj.climb.states:distance_9 c 0.000000E+00 1.731475E-01 1.000000E+15
31 traj.climb.states:distance_10 c 0.000000E+00 2.072419E-01 1.000000E+15
32 traj.climb.states:distance_11 c 0.000000E+00 2.180327E-01 1.000000E+15
33 traj.climb.states:distance_12 c 0.000000E+00 2.370782E-01 1.000000E+15
34 traj.climb.states:distance_13 c 0.000000E+00 2.633572E-01 1.000000E+15
35 traj.climb.states:distance_14 c 0.000000E+00 2.716744E-01 1.000000E+15
36 traj.climb.states:distance_15 c 0.000000E+00 2.806221E-01 1.000000E+15
37 traj.climb.states:distance_16 c 0.000000E+00 2.929681E-01 1.000000E+15
38 traj.climb.states:distance_17 c 0.000000E+00 2.968756E-01 1.000000E+15
39 traj.cruise.t_initial_0 c 7.260000E+02 1.572000E+03 2.904000E+03
40 traj.cruise.t_duration_0 c 5.000000E-01 1.000000E+00 2.000000E+00
41 traj.cruise.states:mass_0 c 0.000000E+00 5.715264E+00 1.000000E+17
42 traj.cruise.states:mass_1 c 0.000000E+00 5.328748E+00 1.000000E+17
43 traj.cruise.states:mass_2 c 0.000000E+00 4.795434E+00 1.000000E+17
44 traj.cruise.states:mass_3 c 0.000000E+00 4.626642E+00 1.000000E+17
45 traj.cruise.states:distance_0 c 0.000000E+00 2.968756E-01 1.000000E+15
46 traj.cruise.states:distance_1 c 0.000000E+00 2.324511E+00 1.000000E+15
47 traj.cruise.states:distance_2 c 0.000000E+00 5.122233E+00 1.000000E+15
48 traj.cruise.states:distance_3 c 0.000000E+00 6.007703E+00 1.000000E+15
49 traj.descent.t_initial_0 c 1.291140E+04 2.594280E+04 5.164560E+04
50 traj.descent.t_duration_0 c 5.000000E-01 1.000000E+00 2.000000E+00
51 traj.descent.states:mass_0 c 0.000000E+00 4.626642E+00 1.000000E+17
52 traj.descent.states:mass_1 c 0.000000E+00 4.624750E+00 1.000000E+17
53 traj.descent.states:mass_2 c 0.000000E+00 4.622140E+00 1.000000E+17
54 traj.descent.states:mass_3 c 0.000000E+00 4.621314E+00 1.000000E+17
55 traj.descent.states:mass_4 c 0.000000E+00 4.617450E+00 1.000000E+17
56 traj.descent.states:mass_5 c 0.000000E+00 4.612119E+00 1.000000E+17
57 traj.descent.states:mass_6 c 0.000000E+00 4.610431E+00 1.000000E+17
58 traj.descent.states:mass_7 c 0.000000E+00 4.605838E+00 1.000000E+17
59 traj.descent.states:mass_8 c 0.000000E+00 4.599500E+00 1.000000E+17
60 traj.descent.states:mass_9 c 0.000000E+00 4.597494E+00 1.000000E+17
61 traj.descent.states:mass_10 c 0.000000E+00 4.593630E+00 1.000000E+17
62 traj.descent.states:mass_11 c 0.000000E+00 4.588299E+00 1.000000E+17
63 traj.descent.states:mass_12 c 0.000000E+00 4.586611E+00 1.000000E+17
64 traj.descent.states:mass_13 c 0.000000E+00 4.584720E+00 1.000000E+17
65 traj.descent.states:mass_14 c 0.000000E+00 4.582109E+00 1.000000E+17
66 traj.descent.states:mass_15 c 0.000000E+00 4.581283E+00 1.000000E+17
67 traj.descent.states:distance_0 c 0.000000E+00 6.007703E+00 1.000000E+15
68 traj.descent.states:distance_1 c 0.000000E+00 6.018115E+00 1.000000E+15
69 traj.descent.states:distance_2 c 0.000000E+00 6.032483E+00 1.000000E+15
70 traj.descent.states:distance_3 c 0.000000E+00 6.037030E+00 1.000000E+15
71 traj.descent.states:distance_4 c 0.000000E+00 6.058295E+00 1.000000E+15
72 traj.descent.states:distance_5 c 0.000000E+00 6.087637E+00 1.000000E+15
73 traj.descent.states:distance_6 c 0.000000E+00 6.096924E+00 1.000000E+15
74 traj.descent.states:distance_7 c 0.000000E+00 6.122206E+00 1.000000E+15
75 traj.descent.states:distance_8 c 0.000000E+00 6.157091E+00 1.000000E+15
76 traj.descent.states:distance_9 c 0.000000E+00 6.168132E+00 1.000000E+15
77 traj.descent.states:distance_10 c 0.000000E+00 6.189397E+00 1.000000E+15
78 traj.descent.states:distance_11 c 0.000000E+00 6.218739E+00 1.000000E+15
79 traj.descent.states:distance_12 c 0.000000E+00 6.228025E+00 1.000000E+15
80 traj.descent.states:distance_13 c 0.000000E+00 6.238438E+00 1.000000E+15
81 traj.descent.states:distance_14 c 0.000000E+00 6.252805E+00 1.000000E+15
82 traj.descent.states:distance_15 c 0.000000E+00 6.257352E+00 1.000000E+15
Constraints (i - inequality, e - equality)
Index Name Type Lower Value Upper Status Lagrange Multiplier
0 mass_resid e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
1 gtow_constraint.GTOW e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
2 traj.linkages.climb:time_final|cruise:time_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
3 traj.linkages.climb:mass_final|cruise:mass_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
4 traj.linkages.climb:distance_final|cruise:distance_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
5 traj.linkages.cruise:time_final|descent:time_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
6 traj.linkages.cruise:mass_final|descent:mass_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
7 traj.linkages.cruise:distance_final|descent:distance_initial e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
8 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
9 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
10 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
11 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
12 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
13 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
14 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
15 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
16 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
17 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
18 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
19 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
20 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
21 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
22 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
23 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
24 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
25 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
26 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
27 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
28 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
29 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
30 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
31 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
32 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
33 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
34 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
35 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
36 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
37 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
38 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
39 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
40 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
41 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
42 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
43 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
44 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
45 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
46 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
47 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
48 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
49 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
50 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
51 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
52 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
53 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
54 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
55 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
56 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
57 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
58 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
59 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
60 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
61 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
62 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
63 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
64 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
65 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
66 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
67 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
68 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
69 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
70 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
71 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
72 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
73 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
74 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
75 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
76 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
77 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
78 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
79 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 NAN 0.000000E+00 0.00000E+00
80 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
81 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
82 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
83 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
84 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
85 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
86 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
87 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
88 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
89 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
90 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
91 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
92 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
93 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
94 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
95 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
96 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
97 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
98 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
99 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
100 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
101 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
102 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
103 traj.climb.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
104 traj.cruise.altitude_rate_max[path] i 5.000000E+00 NAN 1.000000E+30 lu 0.00000E+00
105 traj.cruise.altitude_rate_max[path] i 5.000000E+00 NAN 1.000000E+30 lu 0.00000E+00
106 traj.cruise.altitude_rate_max[path] i 5.000000E+00 NAN 1.000000E+30 lu 0.00000E+00
107 traj.cruise.altitude_rate_max[path] i 5.000000E+00 NAN 1.000000E+30 lu 0.00000E+00
108 traj.cruise.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
109 traj.cruise.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
110 traj.cruise.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
111 traj.cruise.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
112 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
113 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
114 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
115 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
116 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
117 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
118 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
119 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
120 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
121 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
122 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
123 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
124 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
125 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
126 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
127 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
128 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
129 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
130 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
131 traj.descent.throttle[path] i 0.000000E+00 NAN 1.000000E+00 lu 0.00000E+00
Exit Status
Inform Description
-13 Invalid Number Detected
--------------------------------------------------------------------------------
/home/runner/work/Aviary/Aviary/aviary/mission/height_energy/ode/required_thrust.py:58: RuntimeWarning: divide by zero encountered in divide
thrust_required = drag + (altitude_rate * gravity / velocity + velocity_rate) * mass
/home/runner/work/Aviary/Aviary/aviary/mission/height_energy/ode/required_thrust.py:58: RuntimeWarning: invalid value encountered in divide
thrust_required = drag + (altitude_rate * gravity / velocity + velocity_rate) * mass
/usr/share/miniconda/envs/test/lib/python3.12/site-packages/openmdao/vectors/default_vector.py:421: RuntimeWarning: invalid value encountered in add
data[idxs] += val
-------------------------------
times_climb: [1572.] (s)
altitudes_climb: [10668.] (m)
masses_climb: [57152.63862] (kg)
ranges_climb: [296875.6] (m)
velocities_climb: [234.30259077] (m/s)
thrusts_climb: [53436.1467367] (N)
times_cruise: [1.] (s)
altitudes_cruise: [0.3048] (m)
masses_cruise: [1.] (kg)
ranges_cruise: [1.] (m)
velocities_cruise: [1.] (m/s)
thrusts_cruise: [4.44822162] (N)
times_descent: [1.] (s)
altitudes_descent: [0.3048] (m)
masses_descent: [1.] (kg)
ranges_descent: [1.] (m)
velocities_descent: [1.] (m/s)
thrusts_descent: [4.44822162] (N)
-------------------------------
This model demonstrates the flexibility of level 3. For example, we do not load the aircraft model from a .csv file but from a Python file using the get_flops_inputs() method.
This function not only reads Aviary and mission variables but also builds the engine. More information can be found in models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py.
Note that we can read large single aisle aircraft inputs this way as well:
aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS')
aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS')
aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPSdw')
aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPSalt')
The data files are at:
aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py
aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py
aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py
aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py
respectively.
Discussing this example in more detail#
We move all the code blocks on taxi to add_pre_mission_systems() function because it is how it is done in aviary/interface/methods_for_level2.py. Similarly, all the code blocks on landing are moved to add_post_mission_systems() function. Be careful! Generally speaking, not all components can be moved around due to the expected order of execution.
In aviary/validation_cases/benchmark_tests folder, there is another N3CC model test_FLOPS_based_sizing_N3CC.py. If we had started from that model, you would need to have an add_design_variables() function.
Summary#
We have shown in an example that users have total control over every aspect of the model in level 3. There is one big feature that hasn’t been covered: adding external subsystems. We will move on to discuss how to run Aviary External Subsystem next.