From 7c46f49513b7838a927dacd4a554f95b5de4b174 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 5 Jan 2024 12:18:26 -0500 Subject: [PATCH 001/111] Split Aircraft.Design.RESERVES to two variables --- .../getting_started/input_csv_phase_info.md | 23 +++++++ aviary/interface/methods_for_level2.py | 68 +++++++++++-------- aviary/interface/test/test_reserve_support.py | 8 +-- .../large_single_aisle_1_GwGm.csv | 4 +- .../large_single_aisle_1_GwGm.dat | 2 + .../small_single_aisle_GwGm.csv | 4 +- .../small_single_aisle_GwGm.dat | 4 +- .../test_aircraft/aircraft_for_bench_FwFm.csv | 3 +- .../test_aircraft/aircraft_for_bench_FwGm.csv | 3 +- .../test_aircraft/aircraft_for_bench_GwFm.csv | 3 +- .../test_aircraft/aircraft_for_bench_GwGm.csv | 3 +- ...converter_configuration_test_data_GwGm.csv | 4 +- ...converter_configuration_test_data_GwGm.dat | 4 +- .../legacy_code_data/gasp_default_values.dat | 4 +- aviary/utils/process_input_decks.py | 57 ++++++++++++++-- aviary/variable_info/variable_meta_data.py | 30 +++++++- aviary/variable_info/variables.py | 2 + 17 files changed, 175 insertions(+), 51 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index 08fc04076..447c43733 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -6,6 +6,29 @@ This section is under development. ``` +`initial_guesses` is a dictionary that contains values used to initialize the trajectory. It contains the following keys along with default values: + +- actual_takeoff_mass: 0, +- rotation_mass: .99, +- operating_empty_mass: 0, +- fuel_burn_per_passenger_mile: 0.1, +- cruise_mass_final: 0, +- flight_duration: 0, +- time_to_climb: 0, +- climb_range: 0, +- reserves: 0 + +The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than 10 or anything between -1 and 0. There are three variables to control the reserve fuel in the model file (`.csv`): +- Aircraft.Design.RESERVES: the required fuel reserves: directly in lbm, +- Aircraft.Design.RESERVES_FRACTION: the required fuel reserves: given as a proportion of mission fuel, +- Aircraft.Design.RESERVES_OPTION: if 1, use Aircraft.Design.RESERVES; if 2, use Aircraft.Design.RESERVES_FRACTION + +If the value of parameter `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: +- if `reserves > 10.0`, we set `Aircraft.Design.RESERVES = reserves` and `Aircraft.Design.RESERVES_OPTION = 1`, +- if `-1.0 <= reserves <= 0`, we set `Aircraft.Design.RESERVES_FRACTION = reserves` and `Aircraft.Design.RESERVES_OPTION = 2`. + +The initial guess of `reserves` is always converted to the actual design reserves (instead of reserve factor) and is used to update the initial guesses of `fuel_burn_per_passenger_mile` and `cruise_mass_final`. + ## Phase Info Dictionary `phase_info` is a nested dictionary that Aviary uses for users to define their mission phases - how they are built, the design variables, constraints, connections, etc. diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 06f038472..26d89e116 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2436,31 +2436,45 @@ def _add_gasp_landing_systems(self): ) def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL): - reserves_val = self.aviary_inputs.get_val(Aircraft.Design.RESERVES) - if reserves_val <= 0: - reserves_val = -reserves_val - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_val}*(takeoff_mass - final_mass)", - takeoff_mass={"units": "lbm"}, - final_mass={"units": "lbm"}, - reserve_fuel={"units": "lbm"} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Summary.GROSS_MASS), - ("final_mass", Mission.Landing.TOUCHDOWN_MASS), - ], - promotes_outputs=[("reserve_fuel", reserves_name)], - ) - elif reserves_val > 10: - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_val}", - reserve_fuel={"val": reserves_val, "units": "lbm"} - ), - promotes_outputs=[("reserve_fuel", reserves_name)], - ) + reserves_val = self.aviary_inputs.get_val(Aircraft.Design.RESERVES, units='lbm') + reserves_fac = self.aviary_inputs.get_val( + Aircraft.Design.RESERVES_FRACTION, units='unitless') + reserves_opt = self.aviary_inputs.get_val( + Aircraft.Design.RESERVES_OPTION, units='unitless') + if reserves_opt == 1: + if reserves_val > 10: + self.model.add_subsystem( + "reserves_calc", + om.ExecComp( + f"reserve_fuel = {reserves_val}", + reserve_fuel={"val": reserves_val, "units": "lbm"} + ), + promotes_outputs=[("reserve_fuel", reserves_name)], + ) + else: + raise ValueError('"aircraft:design:reserves" is not valid below 10.') + elif reserves_opt == 2: + if reserves_fac <= 0 and reserves_fac >= -1: + reserves_fac = -reserves_fac + self.model.add_subsystem( + "reserves_calc", + om.ExecComp( + f"reserve_fuel = {reserves_fac}*(takeoff_mass - final_mass)", + takeoff_mass={"units": "lbm"}, + final_mass={"units": "lbm"}, + reserve_fuel={"units": "lbm"} + ), + promotes_inputs=[ + ("takeoff_mass", Mission.Summary.GROSS_MASS), + ("final_mass", Mission.Landing.TOUCHDOWN_MASS), + ], + promotes_outputs=[("reserve_fuel", reserves_name)], + ) + elif reserves_fac > 0 and reserves_fac <= 1: + raise ValueError( + '"aircraft:design:reserves_fraction" between 0 and 1 is not implemented.') + else: + raise ValueError( + '"aircraft:design:reserves_fraction" is not valid if less than -1 or larger than 1.') else: - raise ValueError('"aircraft:design:reserves" is not valid between 0 and 10.') + raise ValueError('"aircraft:design:reserves_option" must be 1 or 2.') diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index b0b3982d8..7fed83a67 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -25,10 +25,7 @@ def test_post_mission_promotion(self): prob.load_inputs(csv_path) prob.check_inputs() - # TODO: This needs to be converted into a reserve and a scaler so that it can - # be given proper units. - # The units here are lbm. - prob.aviary_inputs.set_val(Aircraft.Design.RESERVES, 10000.0, units='unitless') + prob.aviary_inputs.set_val(Aircraft.Design.RESERVES, 10000.0, units='lbm') prob.add_pre_mission_systems() prob.add_phases() @@ -75,7 +72,8 @@ def test_gasp_relative_reserve(self): prob.run_model() - res_frac = prob.aviary_inputs.get_val(Aircraft.Design.RESERVES, units='unitless') + res_frac = prob.aviary_inputs.get_val( + Aircraft.Design.RESERVES_FRACTION, units='unitless') td_mass = prob.model.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm') reserve = prob.model.get_val(Mission.Design.RESERVE_FUEL, units='lbm') assert_near_equal(reserve, -res_frac * (140000.0 - td_mass), 1e-3) diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index 7a69a9942..2092a85fb 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -14,7 +14,9 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,4998,unitless +aircraft:design:reserves,4998,lbm +aircraft:design:reserves_fraction,0,unitless +aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat index f23fff285..b8a4d51f3 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat @@ -195,6 +195,8 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) FRESF=4998, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) + FRESF2=0, ! Reserve fuel fraction of mission fuel (negative sign trigger) + FRESF3=1, ! Use Reserve Fuel RF(1)=.05, ! Reserve Fuel Input: Time for Missed Approach RF(2)=125., ! Reserve Fuel Input: Range to alternate RF(3)=20000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index e395cf439..c444f9a8e 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -14,7 +14,9 @@ aircraft:design:drag_increment,0.0018,unitless aircraft:design:equipment_mass_coefficients,778,0.06,0.112,0.14,1349,1.65,397,9071,7.6,3,50,6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,-0.125,unitless +aircraft:design:reserves,0,lbm +aircraft:design:reserves_fraction,-0.125,unitless +aircraft:design:reserves_option,2,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat index 143b405d4..d6736b834 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat @@ -205,7 +205,9 @@ OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=-.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) + FRESF=0, ! Reserve Fuel + FRESF2=-.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) + FRESF3=2, ! Use Reserve Fuel RF(1)=2.0, ! Reserve Fuel Input: Time for Missed Approach (min) RF(2)=100., ! Reserve Fuel Input: Range to alternate RF(3)=25000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index 0c2985b9e..a3b66e387 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -25,7 +25,8 @@ aircraft:design:base_area,0.0,ft**2 aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:reserves,3000.,unitless +aircraft:design:reserves,3000.,lbm +aircraft:design:reserves_option,1,unitless aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index d8128ce1e..316c73a5c 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -12,7 +12,8 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,3000.,unitless +aircraft:design:reserves,3000.,lbm +aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 58caba631..4881c183b 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -39,7 +39,8 @@ aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,5000.,unitless +aircraft:design:reserves,5000.,lbm +aircraft:design:reserves_option,1,unitless aircraft:design:smooth_mass_discontinuities,False,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index 70c78f420..17f76a7c0 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -13,7 +13,8 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,4998,unitless +aircraft:design:reserves,4998,lbm +aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index a52b15fb7..4367304b9 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -14,7 +14,9 @@ aircraft:design:drag_increment,0.0014,unitless aircraft:design:equipment_mass_coefficients,1014,0.0736,0.085,0.105,1504,1.65,126,9114,5,3,0,10,12,unitless aircraft:design:max_structural_speed,440,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,-0.15,unitless +aircraft:design:reserves,0,lbm +aircraft:design:reserves_fraction,-0.15,unitless +aircraft:design:reserves_option,2,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat index 1ee358869..e6ed8dbee 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat @@ -209,7 +209,9 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=-0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) + FRESF=0, ! Reserve Fuel + FRESF2=-0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) + FRESF3=2, ! Use Reserve Fuel fraction RF(1)=.05, ! Reserve Fuel Input: Time for Missed Approach RF(2)=125., ! Reserve Fuel Input: Range to alternate RF(3)=20000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/utils/legacy_code_data/gasp_default_values.dat b/aviary/utils/legacy_code_data/gasp_default_values.dat index 57a3de66c..9121140fb 100644 --- a/aviary/utils/legacy_code_data/gasp_default_values.dat +++ b/aviary/utils/legacy_code_data/gasp_default_values.dat @@ -83,7 +83,9 @@ EYEW=1.5,deg FLAPN=1,unitless FN_REF=28690,lbf FPYL=0.7,unitless -FRESF=4998,unitless +FRESF=4998,lbm +FRESF2=-0.1,unitless +FRESF3=1,unitless FUELD=6.687,lbm/galUS FVOL_MRG=0,unitless HAPP=50,ft diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 46c9256a5..22bc6ae05 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -45,7 +45,9 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val('mass_defect', val=10000, units='lbm') aircraft_values.set_val('problem_type', val=ProblemType.SIZING) aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998) + aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998, units='lbm') + aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') + aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, val=0, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -164,10 +166,56 @@ def update_dependent_options(aircraft_values: AviaryValues(), dependent_options) def initial_guessing(aircraft_values: AviaryValues()): problem_type = aircraft_values.get_val('problem_type') + reserves_option = aircraft_values.get_val(Aircraft.Design.RESERVES_OPTION) reserves = aircraft_values.get_val( - Aircraft.Design.RESERVES) if initial_guesses['reserves'] == 0 else initial_guesses['reserves'] + Aircraft.Design.RESERVES, units='lbm') if initial_guesses['reserves'] == 0 else initial_guesses['reserves'] + if reserves_option == 1: + aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') + if reserves < 10: + raise ValueError('"aircraft:design:reserves" must be greater than 10 lbm.') + elif reserves_option == 2: + if initial_guesses['reserves'] == 0: + reserves = aircraft_values.get_val( + Aircraft.Design.RESERVES_FRACTION, units='unitless') + else: + reserves = initial_guesses['reserves'] + aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, + reserves, units='unitless') + if reserves < -1 or reserves > 0: + raise ValueError('"aircraft:design:reserves_fraction" must be in [-1, 0].') + else: + # if aircraft:design:reserves_option is not set, + # then determine reserves based on initial_guesses['reserves'] + if initial_guesses['reserves'] > 10: + reserves = initial_guesses['reserves'] + reserves_option = 1 + aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') + elif initial_guesses['reserves'] < 0: + reserves = initial_guesses['reserves'] + reserves_option = 2 + aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, + reserves, units='unitless') + elif initial_guesses['reserves'] == 0 and reserves > 10: + reserves_option = 1 + aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') + elif initial_guesses['reserves'] == 0 and reserves < 0: + reserves_option = 2 + aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, + reserves, units='unitless') + aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, + reserves_option, units='unitless') + num_pax = aircraft_values.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) + if reserves_option == 2: + if reserves <= 0: + reserves *= -(num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * + aircraft_values.get_val(Mission.Design.RANGE, units='NM')) + else: + raise ValueError( + 'The case that "aircraft:design:reserves_fraction" is between 0 and 1 is not implemented.') + initial_guesses['reserves'] = reserves + if Mission.Summary.GROSS_MASS in aircraft_values: mission_mass = aircraft_values.get_val(Mission.Summary.GROSS_MASS, units='lbm') else: @@ -179,11 +227,6 @@ def initial_guessing(aircraft_values: AviaryValues()): else: cruise_mass_final = initial_guesses['cruise_mass_final'] - if reserves < 0: - reserves *= -(num_pax * - initial_guesses['fuel_burn_per_passenger_mile'] * aircraft_values.get_val(Mission.Design.RANGE, units='NM')) - initial_guesses['reserves'] = reserves - # takeoff mass not given if mission_mass <= 0: if problem_type == ProblemType.ALTERNATE: diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index bd44af54c..f8aeb4c27 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1204,9 +1204,35 @@ "LEAPS1": None }, option=True, + units="lbm", + desc='required fuel reserves: directly in lbm', + default_value=0, +) + +add_meta_data( + Aircraft.Design.RESERVES_FRACTION, + meta_data=_MetaData, + historical_name={"GASP": 'INGASP.FRESF2', # the real name is INGASP.FRESF + "FLOPS": None, + "LEAPS1": None + }, + option=True, + units="unitless", + desc='required fuel reserves: given as a proportion of mission fuel', + default_value=0, +) + +add_meta_data( + Aircraft.Design.RESERVES_OPTION, + meta_data=_MetaData, + historical_name={"GASP": 'INGASP.FRESF3', # the real name is INGASP.FRESF + "FLOPS": None, + "LEAPS1": None + }, + option=True, + types=int, units="unitless", - desc='required fuel reserves: given either as a proportion of mission fuel' - '(<0) or directly in lbf (>10)', + desc='if 1, use Aircraft.Design.RESERVES; if 2, use Aircraft.Design.RESERVES_FRACTION', default_value=0, ) diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 51d5df4c6..df40a30ad 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -149,6 +149,8 @@ class Design: OPERATING_MASS = 'aircraft:design:operating_mass' PART25_STRUCTURAL_CATEGORY = 'aircraft:design:part25_structural_category' RESERVES = 'aircraft:design:reserves' + RESERVES_FRACTION = 'aircraft:design:reserves_fraction' + RESERVES_OPTION = 'aircraft:design:reserves_option' SMOOTH_MASS_DISCONTINUITIES = 'aircraft:design:smooth_mass_discontinuities' STATIC_MARGIN = 'aircraft:design:static_margin' STRUCTURAL_MASS_INCREMENT = 'aircraft:design:structural_mass_increment' From cda06b0f1bff9df52e053d76d6c4d37bd4004452 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 5 Jan 2024 13:40:45 -0500 Subject: [PATCH 002/111] minor change to doc file --- aviary/docs/getting_started/input_csv_phase_info.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index 447c43733..b3a8358d9 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -19,9 +19,9 @@ This section is under development. - reserves: 0 The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than 10 or anything between -1 and 0. There are three variables to control the reserve fuel in the model file (`.csv`): -- Aircraft.Design.RESERVES: the required fuel reserves: directly in lbm, -- Aircraft.Design.RESERVES_FRACTION: the required fuel reserves: given as a proportion of mission fuel, -- Aircraft.Design.RESERVES_OPTION: if 1, use Aircraft.Design.RESERVES; if 2, use Aircraft.Design.RESERVES_FRACTION +- `Aircraft.Design.RESERVES`: the required fuel reserves: directly in lbm, +- `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel, +- `Aircraft.Design.RESERVES_OPTION`: if 1, use `Aircraft.Design.RESERVES`; if 2, use `Aircraft.Design.RESERVES_FRACTION` If the value of parameter `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: - if `reserves > 10.0`, we set `Aircraft.Design.RESERVES = reserves` and `Aircraft.Design.RESERVES_OPTION = 1`, From 73b528c1c6b1a7ed756a7165926b4e0c31083c5c Mon Sep 17 00:00:00 2001 From: "Kenneth T. Moore" Date: Fri, 5 Jan 2024 15:53:21 -0500 Subject: [PATCH 003/111] Switch some interps to more efficient versions; cleaned up a couple failing benches --- .../phases/detailed_takeoff_phases.py | 20 +++++++------- .../gasp_based/flaps_model/meta_model.py | 26 +++++++++---------- .../aerodynamics/gasp_based/gaspaero.py | 2 +- .../benchmark_tests/test_bench_FwGm.py | 8 +++--- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py index 742c774f8..c044fd9b8 100644 --- a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py +++ b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py @@ -198,7 +198,7 @@ def build_phase(self, aviary_options=None): phase.add_state( Dynamic.MASS, fix_initial=True, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -368,7 +368,7 @@ def build_phase(self, aviary_options=None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -651,7 +651,7 @@ def build_phase(self, aviary_options=None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -852,7 +852,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -1088,7 +1088,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -1320,7 +1320,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -1548,7 +1548,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -1764,7 +1764,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -1993,7 +1993,7 @@ def build_phase(self, aviary_options: AviaryValues = None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) @@ -2199,7 +2199,7 @@ def build_phase(self, aviary_options=None): phase.add_state( Dynamic.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', + lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, targets=Dynamic.MASS, ) diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py index fc711963d..a1736cdcd 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py @@ -21,7 +21,7 @@ def setup(self): # VDEL1 VDEL1_interp = self.add_subsystem( "VDEL1_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "aircraft:*", ], @@ -61,7 +61,7 @@ def setup(self): # VDEL2 VDEL2_interp = self.add_subsystem( "VDEL2_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "flap_defl_ratio", ], @@ -149,7 +149,7 @@ def setup(self): # VLAM1 VLAM1_interp = self.add_subsystem( "VLAM1_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "aircraft:*", ], @@ -215,7 +215,7 @@ def setup(self): # VLAM2 VLAM2_interp = self.add_subsystem( "VLAM2_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], @@ -275,7 +275,7 @@ def setup(self): # VLAM3 VLAM3_interp = self.add_subsystem( "VLAM3_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "aircraft:*", ], @@ -339,7 +339,7 @@ def setup(self): # VLAM4 VLAM4_interp = self.add_subsystem( "VLAM4_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], @@ -430,7 +430,7 @@ def setup(self): # VLAM5 VLAM5_interp = self.add_subsystem( "VLAM5_intep", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "aircraft:*", ], @@ -482,7 +482,7 @@ def setup(self): # VLAM6 VLAM6_interp = self.add_subsystem( "VLAM6_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "flap_defl", ], @@ -603,7 +603,7 @@ def setup(self): # VLAM7 VLAM7_interp = self.add_subsystem( "VLAM7_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ Aircraft.Wing.FLAP_SPAN_RATIO, ], @@ -631,7 +631,7 @@ def setup(self): # VLAM10 VLAM10_interp = self.add_subsystem( "VLAM10_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "slat_defl_ratio", ], @@ -689,7 +689,7 @@ def setup(self): # VLAM11 VLAM11_interp = self.add_subsystem( "VLAM11_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ Aircraft.Wing.SLAT_SPAN_RATIO, ], @@ -717,7 +717,7 @@ def setup(self): # VLAM13 VLAM13_interp = self.add_subsystem( "VLAM13_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ "reynolds", ], @@ -775,7 +775,7 @@ def setup(self): # VLAM14 VLAM14_interp = self.add_subsystem( "VLAM14_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), + om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), promotes_inputs=[ Dynamic.Mission.MACH, ], diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index a5ca197fe..a0fb90a81 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -789,7 +789,7 @@ def setup(self): self.add_subsystem("xlifts", Xlifts(num_nodes=nn), promotes=["*"]) # implements EAERO - interp = om.MetaModelStructuredComp(method="slinear") + interp = om.MetaModelStructuredComp(method="2D-slinear") interp.add_input("bbar", 0.0, units="unitless", training_data=xbbar) interp.add_input("hbar", 0.0, units="unitless", training_data=xhbar) interp.add_output("sigma", 0.0, units="unitless", training_data=sig1) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index c73db751c..057f480f4 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -21,16 +21,16 @@ def bench_test_swap_3_FwGm(self): # There are no truth values for these. assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), - 184426., tolerance=rtol) + 186418., tolerance=rtol) assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), - 104215., tolerance=rtol) + 104530., tolerance=rtol) assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), - 42355., tolerance=rtol) + 44032., tolerance=rtol) assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), - 2544.3, tolerance=rtol) + 2528., tolerance=rtol) assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], 3675.0, tolerance=rtol) From 1798c04bae99caebebc83c7789d8e6820dd17529 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 5 Jan 2024 17:17:43 -0500 Subject: [PATCH 004/111] updates based on review comments --- .../getting_started/input_csv_phase_info.md | 2 +- aviary/interface/methods_for_level2.py | 15 ++++++----- aviary/utils/process_input_decks.py | 26 +++++++++---------- aviary/variable_info/enums.py | 23 ++++++++++++++++ aviary/variable_info/variable_meta_data.py | 9 ++++--- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index b3a8358d9..c60fad220 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -21,7 +21,7 @@ This section is under development. The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than 10 or anything between -1 and 0. There are three variables to control the reserve fuel in the model file (`.csv`): - `Aircraft.Design.RESERVES`: the required fuel reserves: directly in lbm, - `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel, -- `Aircraft.Design.RESERVES_OPTION`: if 1, use `Aircraft.Design.RESERVES`; if 2, use `Aircraft.Design.RESERVES_FRACTION` +- `Aircraft.Design.RESERVES_OPTION`: if `Set_Direct` (1), use `Aircraft.Design.RESERVES`; if `Set_Fraction` (2), use `Aircraft.Design.RESERVES_FRACTION`. If the value of parameter `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: - if `reserves > 10.0`, we set `Aircraft.Design.RESERVES = reserves` and `Aircraft.Design.RESERVES_OPTION = 1`, diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 26d89e116..4847119b0 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -48,7 +48,7 @@ from aviary.variable_info.functions import setup_trajectory_params, override_aviary_vars from aviary.variable_info.variables import Aircraft, Mission, Dynamic -from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes +from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes, Reserves_Type from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData from aviary.variable_info.variables_in import VariablesIn @@ -2441,7 +2441,7 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) Aircraft.Design.RESERVES_FRACTION, units='unitless') reserves_opt = self.aviary_inputs.get_val( Aircraft.Design.RESERVES_OPTION, units='unitless') - if reserves_opt == 1: + if reserves_opt == Reserves_Type.Set_Direct: if reserves_val > 10: self.model.add_subsystem( "reserves_calc", @@ -2452,8 +2452,8 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) promotes_outputs=[("reserve_fuel", reserves_name)], ) else: - raise ValueError('"aircraft:design:reserves" is not valid below 10.') - elif reserves_opt == 2: + raise ValueError(f'"{Aircraft.Design.RESERVES}" is not valid below 10.') + elif reserves_opt == Reserves_Type.Set_Fraction: if reserves_fac <= 0 and reserves_fac >= -1: reserves_fac = -reserves_fac self.model.add_subsystem( @@ -2472,9 +2472,10 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) ) elif reserves_fac > 0 and reserves_fac <= 1: raise ValueError( - '"aircraft:design:reserves_fraction" between 0 and 1 is not implemented.') + f'"{Aircraft.Design.RESERVES_FRACTION}" between 0 and 1 is not implemented.') else: raise ValueError( - '"aircraft:design:reserves_fraction" is not valid if less than -1 or larger than 1.') + f'"{Aircraft.Design.RESERVES_FRACTION}" is not valid if less than -1 or larger than 1.') else: - raise ValueError('"aircraft:design:reserves_option" must be 1 or 2.') + raise ValueError(f'"{Aircraft.Design.RESERVES_OPTION}" must be \ + {Reserves_Type.Set_Directn} or {Reserves_Type.Set_Fraction}.') diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 22bc6ae05..4baf00f29 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -22,7 +22,7 @@ from aviary.utils.aviary_values import AviaryValues, get_keys from aviary.utils.functions import convert_strings_to_data, set_value from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.enums import ProblemType +from aviary.variable_info.enums import ProblemType, Reserves_Type from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission from aviary.utils.functions import get_path @@ -47,7 +47,7 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998, units='lbm') aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') - aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, val=0, units='unitless') + aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, val=Reserves_Type.Set_None, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -169,11 +169,11 @@ def initial_guessing(aircraft_values: AviaryValues()): reserves_option = aircraft_values.get_val(Aircraft.Design.RESERVES_OPTION) reserves = aircraft_values.get_val( Aircraft.Design.RESERVES, units='lbm') if initial_guesses['reserves'] == 0 else initial_guesses['reserves'] - if reserves_option == 1: + if reserves_option == Reserves_Type.Set_Direct: aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') if reserves < 10: - raise ValueError('"aircraft:design:reserves" must be greater than 10 lbm.') - elif reserves_option == 2: + raise ValueError(f'"{Aircraft.Design.RESERVES}" must be greater than 10 lbm.') + elif reserves_option == Reserves_Type.Set_Fraction: if initial_guesses['reserves'] == 0: reserves = aircraft_values.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') @@ -182,24 +182,24 @@ def initial_guessing(aircraft_values: AviaryValues()): aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') if reserves < -1 or reserves > 0: - raise ValueError('"aircraft:design:reserves_fraction" must be in [-1, 0].') + raise ValueError(f'"{Aircraft.Design.RESERVES_FRACTION}" must be in [-1, 0].') else: - # if aircraft:design:reserves_option is not set, + # if Aircraft.Design.RESERVES_FRACTION is not set, # then determine reserves based on initial_guesses['reserves'] if initial_guesses['reserves'] > 10: reserves = initial_guesses['reserves'] - reserves_option = 1 + reserves_option = Reserves_Type.Set_Direct aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') elif initial_guesses['reserves'] < 0: reserves = initial_guesses['reserves'] - reserves_option = 2 + reserves_option = Reserves_Type.Set_Fraction aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') elif initial_guesses['reserves'] == 0 and reserves > 10: - reserves_option = 1 + reserves_option = Reserves_Type.Set_Direct aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') elif initial_guesses['reserves'] == 0 and reserves < 0: - reserves_option = 2 + reserves_option = Reserves_Type.Set_Fraction aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, @@ -207,13 +207,13 @@ def initial_guessing(aircraft_values: AviaryValues()): num_pax = aircraft_values.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - if reserves_option == 2: + if reserves_option == Reserves_Type.Set_Fraction: if reserves <= 0: reserves *= -(num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * aircraft_values.get_val(Mission.Design.RANGE, units='NM')) else: raise ValueError( - 'The case that "aircraft:design:reserves_fraction" is between 0 and 1 is not implemented.') + f'The case that "{Aircraft.Design.RESERVES_FRACTION}" is between 0 and 1 is not implemented.') initial_guesses['reserves'] = reserves if Mission.Summary.GROSS_MASS in aircraft_values: diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 912283e50..3c9cafc78 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -181,3 +181,26 @@ class Flap_Type(Enum): """ Double-slotted Fowler flaps """ + +@unique +class Reserves_Type(Enum): + """ + Defines the type of reserves used. Currently, Set_by_Time is not implemented. + """ + + Set_None = 0 + """ + Do not set it and let initial_guess['reserves'] decide. + """ + Set_Direct = 1 + """ + Set required fuel reserves directly in lbm (must be larger than 10). + """ + Set_Fraction = 2 + """ + Set required fuel reserves as a proportion of mission fuel (must be btween -1 and 0). + """ + Set_by_Time = 3 + """ + Set required fuel reserves as a proportion of time (must be btween 0 and 1 which correspond to 0 and 45 minutes). + """ \ No newline at end of file diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index f8aeb4c27..cb3e9f42f 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -7,7 +7,7 @@ import numpy as np from aviary.utils.develop_metadata import add_meta_data -from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type +from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type, Reserves_Type from aviary.variable_info.variables import Aircraft, Dynamic, Mission # --------------------------- @@ -1230,10 +1230,11 @@ "LEAPS1": None }, option=True, - types=int, + types=Reserves_Type, units="unitless", - desc='if 1, use Aircraft.Design.RESERVES; if 2, use Aircraft.Design.RESERVES_FRACTION', - default_value=0, + desc=f'if {Reserves_Type.Set_Direct}, use Aircraft.Design.RESERVES; \ + if {Reserves_Type.Set_Fraction}, use Aircraft.Design.RESERVES_FRACTION', + default_value=Reserves_Type.Set_None, ) add_meta_data( From eb56dccd2b79e12a2c7149c506c4e4e20e73ef70 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 5 Jan 2024 17:41:48 -0500 Subject: [PATCH 005/111] update due to autopep8 requirements --- aviary/utils/process_input_decks.py | 9 ++++++--- aviary/variable_info/enums.py | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 4baf00f29..c7fa8c26b 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -47,7 +47,8 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998, units='lbm') aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') - aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, val=Reserves_Type.Set_None, units='unitless') + aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, + val=Reserves_Type.Set_None, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -172,7 +173,8 @@ def initial_guessing(aircraft_values: AviaryValues()): if reserves_option == Reserves_Type.Set_Direct: aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') if reserves < 10: - raise ValueError(f'"{Aircraft.Design.RESERVES}" must be greater than 10 lbm.') + raise ValueError( + f'"{Aircraft.Design.RESERVES}" must be greater than 10 lbm.') elif reserves_option == Reserves_Type.Set_Fraction: if initial_guesses['reserves'] == 0: reserves = aircraft_values.get_val( @@ -182,7 +184,8 @@ def initial_guessing(aircraft_values: AviaryValues()): aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') if reserves < -1 or reserves > 0: - raise ValueError(f'"{Aircraft.Design.RESERVES_FRACTION}" must be in [-1, 0].') + raise ValueError( + f'"{Aircraft.Design.RESERVES_FRACTION}" must be in [-1, 0].') else: # if Aircraft.Design.RESERVES_FRACTION is not set, # then determine reserves based on initial_guesses['reserves'] diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 3c9cafc78..aabe458d1 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -182,6 +182,7 @@ class Flap_Type(Enum): Double-slotted Fowler flaps """ + @unique class Reserves_Type(Enum): """ @@ -203,4 +204,4 @@ class Reserves_Type(Enum): Set_by_Time = 3 """ Set required fuel reserves as a proportion of time (must be btween 0 and 1 which correspond to 0 and 45 minutes). - """ \ No newline at end of file + """ From b345ac3ee00822a1f8849cdd055007c5c419188d Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Mon, 8 Jan 2024 11:46:10 -0500 Subject: [PATCH 006/111] Added check to see if the reports directory exists before creating the dashboard --- aviary/visualization/dashboard.py | 320 ++++++++++++++++++------------ 1 file changed, 197 insertions(+), 123 deletions(-) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index 342efc704..f31110571 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -17,13 +17,15 @@ import openmdao.api as om from openmdao.utils.general_utils import env_truthy -pn.extension(sizing_mode='stretch_width') +pn.extension(sizing_mode="stretch_width") # Constants # Can't get using CSS to work with frames and the raw_css for the template so going with # this for now -iframe_css = "width=100% height=4000vh overflow=hidden margin=0px padding=0px border=none" -aviary_variables_json_file_name = 'aviary_vars.json' +iframe_css = ( + "width=100% height=4000vh overflow=hidden margin=0px padding=0px border=none" +) +aviary_variables_json_file_name = "aviary_vars.json" def _dashboard_setup_parser(parser): @@ -36,21 +38,41 @@ def _dashboard_setup_parser(parser): The parser we're adding options to. """ parser.add_argument( - 'script_name', + "script_name", type=str, - help='Name of aviary script that was run (not including .py).' + help="Name of aviary script that was run (not including .py).", ) - parser.add_argument('--problem_recorder', type=str, help="Problem case recorder file name", - dest='problem_recorder', default='aviary_history.db') - parser.add_argument('--driver_recorder', type=str, help="Driver case recorder file name", - dest='driver_recorder', default=None) - parser.add_argument('--port', dest='port', type=int, - default=5000, help="dashboard server port ID (default is 5000)") + parser.add_argument( + "--problem_recorder", + type=str, + help="Problem case recorder file name", + dest="problem_recorder", + default="aviary_history.db", + ) + parser.add_argument( + "--driver_recorder", + type=str, + help="Driver case recorder file name", + dest="driver_recorder", + default=None, + ) + parser.add_argument( + "--port", + dest="port", + type=int, + default=5000, + help="dashboard server port ID (default is 5000)", + ) # For future use - parser.add_argument('-d', '--debug', action='store_true', dest='debug_output', - help="show debugging output") + parser.add_argument( + "-d", + "--debug", + action="store_true", + dest="debug_output", + help="show debugging output", + ) def _dashboard_cmd(options, user_args): @@ -64,8 +86,12 @@ def _dashboard_cmd(options, user_args): user_args : list of str Args to be passed to the user script. """ - dashboard(options.script_name, options.problem_recorder, - options.driver_recorder, options.port) + dashboard( + options.script_name, + options.problem_recorder, + options.driver_recorder, + options.port, + ) def create_report_frame(format, text_filepath): @@ -82,21 +108,22 @@ def create_report_frame(format, text_filepath): Returns ------- pane : Panel.Pane or None - A Panel Pane object to be displayed in the dashboard. Or None if the file + A Panel Pane object to be displayed in the dashboard. Or None if the file does not exist. """ if os.path.exists(text_filepath): - if format == 'html': + if format == "html": report_pane = pn.pane.HTML( - f'') - elif format in ['markdown', 'text']: + f"" + ) + elif format in ["markdown", "text"]: with open(text_filepath, "rb") as f: file_text = f.read() # need to deal with some encoding errors - file_text = file_text.decode('latin-1') - if format == 'markdown': + file_text = file_text.decode("latin-1") + if format == "markdown": report_pane = pn.pane.Markdown(file_text) - elif format == 'text': + elif format == "text": report_pane = pn.pane.Markdown(f"```\n{file_text}\n```\n") else: raise RuntimeError(f"Report format of {format} is not supported.") @@ -110,8 +137,8 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): Create a JSON file with information about Aviary variables. The JSON file has one level of hierarchy of the variables. The file - is written to aviary_vars.json. That file is then read in by the - aviary/visualization/assets/aviary_vars/script.js script. That is inside the + is written to aviary_vars.json. That file is then read in by the + aviary/visualization/assets/aviary_vars/script.js script. That is inside the aviary/visualization/assets/aviary_vars/index.html file that is embedded in the dashboard. @@ -129,18 +156,29 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): """ cr = om.CaseReader(recorder_file) - case = cr.get_case('final') - outputs = case.list_outputs(explicit=True, implicit=True, val=True, - residuals=True, residuals_tol=None, - units=True, shape=True, bounds=True, desc=True, - scaling=False, hierarchical=True, print_arrays=True, - out_stream=None, return_format='dict') + case = cr.get_case("final") + outputs = case.list_outputs( + explicit=True, + implicit=True, + val=True, + residuals=True, + residuals_tol=None, + units=True, + shape=True, + bounds=True, + desc=True, + scaling=False, + hierarchical=True, + print_arrays=True, + out_stream=None, + return_format="dict", + ) sorted_abs_names = sorted(outputs.keys()) grouped = {} for s in sorted_abs_names: - prefix = s.split(':')[0] + prefix = s.split(":")[0] if prefix not in grouped: grouped[prefix] = [] grouped[prefix].append(s) @@ -154,8 +192,8 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): table_data_nested.append( { "abs_name": group_name, - "prom_name": outputs[var_info]['prom_name'], - "value": str(outputs[var_info]['val']), + "prom_name": outputs[var_info]["prom_name"], + "value": str(outputs[var_info]["val"]), } ) else: @@ -166,8 +204,8 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): children_list.append( { "abs_name": children_name, - "prom_name": outputs[children_name]['prom_name'], - "value": str(outputs[children_name]['val']), + "prom_name": outputs[children_name]["prom_name"], + "value": str(outputs[children_name]["val"]), } ) table_data_nested.append( # not a real var, just a group of vars so no values @@ -179,8 +217,10 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): } ) - aviary_variables_file_path = f'reports/{script_name}/aviary_vars/{aviary_variables_json_file_name}' - with open(aviary_variables_file_path, 'w') as fp: + aviary_variables_file_path = ( + f"reports/{script_name}/aviary_vars/{aviary_variables_json_file_name}" + ) + with open(aviary_variables_file_path, "w") as fp: json.dump(table_data_nested, fp) return table_data_nested @@ -196,7 +236,7 @@ def convert_case_recorder_file_to_df(recorder_file_name): Name of the case recorder file. """ cr = om.CaseReader(recorder_file_name) - driver_cases = cr.list_cases('driver', out_stream=None) + driver_cases = cr.list_cases("driver", out_stream=None) df = None for i, case in enumerate(driver_cases): @@ -231,7 +271,9 @@ def convert_case_recorder_file_to_df(recorder_file_name): df = pd.DataFrame(columns=header) # Now fill up a row - row = [i,] + row = [ + i, + ] # important to do in this order since that is the order added to the header for varname in objectives_names: value = objectives[varname] @@ -268,7 +310,13 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): driver_recorder : str Name of the recorder file containing the Driver cases. """ - reports_dir = f'reports/{script_name}/' + reports_dir = f"reports/{script_name}/" + + if not Path(reports_dir).is_dir(): + raise ValueError( + f"The script name, '{script_name}', does not have a reports folder associated with it. " + f"The directory '{reports_dir}' does not exist." + ) # TODO - use lists and functions to do this with a lot less code @@ -276,125 +324,140 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): design_tabs_list = [] # Inputs - inputs_pane = create_report_frame('html', f'{reports_dir}/inputs.html') + inputs_pane = create_report_frame("html", f"{reports_dir}/inputs.html") if inputs_pane: - design_tabs_list.append(('Inputs', inputs_pane)) + design_tabs_list.append(("Inputs", inputs_pane)) # Debug Input List - input_list_pane = create_report_frame('text', 'input_list.txt') + input_list_pane = create_report_frame("text", "input_list.txt") if input_list_pane: - design_tabs_list.append(('Debug Input List', input_list_pane)) + design_tabs_list.append(("Debug Input List", input_list_pane)) # Debug Output List - output_list_pane = create_report_frame('text', 'output_list.txt') + output_list_pane = create_report_frame("text", "output_list.txt") if output_list_pane: - design_tabs_list.append(('Debug Output List', output_list_pane)) + design_tabs_list.append(("Debug Output List", output_list_pane)) # N2 - n2_pane = create_report_frame('html', f'{reports_dir}/n2.html') + n2_pane = create_report_frame("html", f"{reports_dir}/n2.html") if n2_pane: - design_tabs_list.append(('N2', n2_pane)) + design_tabs_list.append(("N2", n2_pane)) # Trajectory Linkage - traj_linkage_report_pane = create_report_frame('html', - f'{reports_dir}/traj_linkage_report.html') + traj_linkage_report_pane = create_report_frame( + "html", f"{reports_dir}/traj_linkage_report.html" + ) if traj_linkage_report_pane: - design_tabs_list.append(('Trajectory Linkage Report', - traj_linkage_report_pane)) + design_tabs_list.append(("Trajectory Linkage Report", traj_linkage_report_pane)) ####### Optimization Tab ####### optimization_tabs_list = [] # Driver scaling - driver_scaling_report_pane = create_report_frame('html', - f'{reports_dir}/driver_scaling_report.html') + driver_scaling_report_pane = create_report_frame( + "html", f"{reports_dir}/driver_scaling_report.html" + ) if driver_scaling_report_pane: - optimization_tabs_list.append(('Driver Scaling Report', - driver_scaling_report_pane)) + optimization_tabs_list.append( + ("Driver Scaling Report", driver_scaling_report_pane) + ) # Coloring report - coloring_report_pane = create_report_frame('html', - f'{reports_dir}/total_coloring.html') + coloring_report_pane = create_report_frame( + "html", f"{reports_dir}/total_coloring.html" + ) if coloring_report_pane: - optimization_tabs_list.append(('Total Coloring Report', - coloring_report_pane)) + optimization_tabs_list.append(("Total Coloring Report", coloring_report_pane)) # Optimization report - opt_report_pane = create_report_frame('html', - f'{reports_dir}/opt_report.html') + opt_report_pane = create_report_frame("html", f"{reports_dir}/opt_report.html") if opt_report_pane: - optimization_tabs_list.append(('Optimization Report', - opt_report_pane)) + optimization_tabs_list.append(("Optimization Report", opt_report_pane)) # IPOPT report - ipopt_pane = create_report_frame('text', - f'{reports_dir}/IPOPT.out') + ipopt_pane = create_report_frame("text", f"{reports_dir}/IPOPT.out") if ipopt_pane: - optimization_tabs_list.append(('IPOPT Output', ipopt_pane)) + optimization_tabs_list.append(("IPOPT Output", ipopt_pane)) # SNOPT report - snopt_pane = create_report_frame('text', - f'{reports_dir}/SNOPT_print.out') + snopt_pane = create_report_frame("text", f"{reports_dir}/SNOPT_print.out") if snopt_pane: - optimization_tabs_list.append(('SNOPT Output', snopt_pane)) + optimization_tabs_list.append(("SNOPT Output", snopt_pane)) # SNOPT summary - snopt_summary_pane = create_report_frame('text', - f'{reports_dir}/SNOPT_summary.out') + snopt_summary_pane = create_report_frame("text", f"{reports_dir}/SNOPT_summary.out") if snopt_summary_pane: - optimization_tabs_list.append(('SNOPT Summary', snopt_summary_pane)) + optimization_tabs_list.append(("SNOPT Summary", snopt_summary_pane)) # PyOpt report - pyopt_solution_pane = create_report_frame('text', - f'{reports_dir}/pyopt_solution.txt') + pyopt_solution_pane = create_report_frame( + "text", f"{reports_dir}/pyopt_solution.txt" + ) if pyopt_solution_pane: - optimization_tabs_list.append(('PyOpt Solution', pyopt_solution_pane)) + optimization_tabs_list.append(("PyOpt Solution", pyopt_solution_pane)) # Desvars, cons, opt interactive plot if driver_recorder: if os.path.exists(driver_recorder): - df = convert_case_recorder_file_to_df(f'{driver_recorder}') + df = convert_case_recorder_file_to_df(f"{driver_recorder}") if df is not None: variables = pn.widgets.CheckBoxGroup( name="Variables", options=list(df.columns), # just so all of them aren't plotted from the beginning. Skip the iter count - value=list(df.columns)[1:2] + value=list(df.columns)[1:2], ) ipipeline = df.interactive() - ihvplot = ipipeline.hvplot(y=variables, responsive=True, min_height=400, - color=list(Category10[10]), - yformatter="%.0f", - title="Model Optimization using OpenMDAO") + ihvplot = ipipeline.hvplot( + y=variables, + responsive=True, + min_height=400, + color=list(Category10[10]), + yformatter="%.0f", + title="Model Optimization using OpenMDAO", + ) optimization_plot_pane = pn.Column( pn.Row( pn.Column( variables, pn.VSpacer(height=30), pn.VSpacer(height=30), - width=300 + width=300, ), ihvplot.panel(), ) ) optimization_tabs_list.append( - ('Desvars, cons, opt', optimization_plot_pane)) + ("Desvars, cons, opt", optimization_plot_pane) + ) else: - optimization_tabs_list.append(('Desvars, cons, opt', pn.pane.Markdown( - f"# Recorder file '{driver_recorder}' does not have Driver case recordings"))) + optimization_tabs_list.append( + ( + "Desvars, cons, opt", + pn.pane.Markdown( + f"# Recorder file '{driver_recorder}' does not have Driver case recordings" + ), + ) + ) else: - optimization_tabs_list.append(('Desvars, cons, opt', pn.pane.Markdown( - f"# Recorder file '{driver_recorder}' not found"))) + optimization_tabs_list.append( + ( + "Desvars, cons, opt", + pn.pane.Markdown(f"# Recorder file '{driver_recorder}' not found"), + ) + ) ####### Results Tab ####### results_tabs_list = [] # Trajectory results - traj_results_report_pane = create_report_frame('html', - f'{reports_dir}/traj_results_report.html') + traj_results_report_pane = create_report_frame( + "html", f"{reports_dir}/traj_results_report.html" + ) if traj_results_report_pane: - results_tabs_list.append(('Trajectory Results Report', - traj_results_report_pane)) + results_tabs_list.append( + ("Trajectory Results Report", traj_results_report_pane) + ) # Make the Aviary variables table pane if problem_recorder: @@ -406,26 +469,32 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): # copy index.html file to reports/script_name/aviary_vars/index.html aviary_dir = pathlib.Path(importlib.util.find_spec("aviary").origin).parent - shutil.copy(aviary_dir.joinpath( - 'visualization/assets/aviary_vars/index.html'), aviary_vars_dir.joinpath('index.html')) - shutil.copy(aviary_dir.joinpath( - 'visualization/assets/aviary_vars/script.js'), aviary_vars_dir.joinpath('script.js')) + shutil.copy( + aviary_dir.joinpath("visualization/assets/aviary_vars/index.html"), + aviary_vars_dir.joinpath("index.html"), + ) + shutil.copy( + aviary_dir.joinpath("visualization/assets/aviary_vars/script.js"), + aviary_vars_dir.joinpath("script.js"), + ) # copy script.js file to reports/script_name/aviary_vars/index.html. # mod the script.js file to point at the json file # create the json file and put it in reports/script_name/aviary_vars/aviary_vars.json create_aviary_variables_table_data_nested( - script_name, problem_recorder) # create the json file - aviary_vars_pane = create_report_frame('html', - f'{reports_dir}/aviary_vars/index.html') + script_name, problem_recorder + ) # create the json file + aviary_vars_pane = create_report_frame( + "html", f"{reports_dir}/aviary_vars/index.html" + ) - results_tabs_list.append(('Aviary Variables', aviary_vars_pane)) + results_tabs_list.append(("Aviary Variables", aviary_vars_pane)) ####### Subsystems Tab ####### subsystem_tabs_list = [] # Look through subsystems directory for markdown files - for md_file in Path(f'{reports_dir}subsystems').glob('*.md'): - example_subsystems_pane = create_report_frame('markdown', str(md_file)) + for md_file in Path(f"{reports_dir}subsystems").glob("*.md"): + example_subsystems_pane = create_report_frame("markdown", str(md_file)) subsystem_tabs_list.append((md_file.stem, example_subsystems_pane)) design_tabs = pn.Tabs(*design_tabs_list) @@ -458,48 +527,53 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): # Add subtabs to tabs high_level_tabs = [] - high_level_tabs.append(('Model', design_tabs)) - high_level_tabs.append(('Optimization', optimization_tabs)) - high_level_tabs.append(('Results', results_tabs)) + high_level_tabs.append(("Model", design_tabs)) + high_level_tabs.append(("Optimization", optimization_tabs)) + high_level_tabs.append(("Results", results_tabs)) if subsystem_tabs_list: - high_level_tabs.append(('Subsystems', subsystem_tabs)) - tabs = pn.Tabs(*high_level_tabs, styles={'background': 'white'}) + high_level_tabs.append(("Subsystems", subsystem_tabs)) + tabs = pn.Tabs(*high_level_tabs, styles={"background": "white"}) template = pn.template.FastListTemplate( - title=f'Aviary Dashboard for {script_name}', + title=f"Aviary Dashboard for {script_name}", logo="assets/aviary_logo.png", favicon="assets/aviary_logo.png", main=[tabs], accent_base_color="black", header_background="rgb(0, 212, 169)", - background_color='white', + background_color="white", theme=DefaultTheme, theme_toggle=False, ) - if env_truthy('TESTFLO_RUNNING'): + if env_truthy("TESTFLO_RUNNING"): show = False threaded = True else: show = True threaded = False - assets_dir = pathlib.Path(importlib.util.find_spec( - "aviary").origin).parent.joinpath('visualization/assets/') - home_dir = '.' - server = pn.serve(template, port=port, address='localhost', - websocket_origin=f'localhost:{port}', - show=show, - threaded=threaded, - static_dirs={ - 'reports': reports_dir, - 'home': home_dir, - 'assets': assets_dir, - }) + assets_dir = pathlib.Path( + importlib.util.find_spec("aviary").origin + ).parent.joinpath("visualization/assets/") + home_dir = "." + server = pn.serve( + template, + port=port, + address="localhost", + websocket_origin=f"localhost:{port}", + show=show, + threaded=threaded, + static_dirs={ + "reports": reports_dir, + "home": home_dir, + "assets": assets_dir, + }, + ) server.stop() -if __name__ == '__main__': +if __name__ == "__main__": # so we can get the files written to the repo top directory # os.chdir('/Users/hschilli/Documents/OpenMDAO/dev/I365-create-launcher/') parser = argparse.ArgumentParser() From 95459c2e60c3c7278ac1b7a2dbb43eae0fd6a1e5 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Mon, 8 Jan 2024 13:36:04 -0500 Subject: [PATCH 007/111] Fixed bug in test that tested dashboard. It assumed the reports would be in a tmp directory but they are actually in the name of the script, test_simple_mission. The new test to make sure reports directory exist caused this to fail --- aviary/interface/test/test_simple_mission.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 1b5762dcb..327843fcd 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -4,7 +4,6 @@ from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs import subprocess - @use_tempdirs class AircraftMissionTestSuite(unittest.TestCase): @@ -119,7 +118,7 @@ def test_mission_basic_and_dashboard(self): self.assertIsNotNone(prob) self.assertFalse(prob.failed) - cmd = f'aviary dashboard --problem_recorder dymos_solution.db --driver_recorder driver_test.db tmp' + cmd = f'aviary dashboard --problem_recorder dymos_solution.db --driver_recorder driver_test.db test_simple_mission' # this only tests that a given command line tool returns a 0 return code. It doesn't # check the expected output at all. The underlying functions that implement the # commands should be tested seperately. From 474bc6c3d101673edeec176d794274aafebad3e6 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 8 Jan 2024 17:37:25 -0500 Subject: [PATCH 008/111] removed RESERVES_OPTION and set RESERVES_FRACTION to positive --- .../getting_started/input_csv_phase_info.md | 9 ++- aviary/interface/methods_for_level2.py | 64 +++++++------------ aviary/interface/test/test_reserve_support.py | 2 +- .../large_single_aisle_1_GwGm.csv | 1 - .../large_single_aisle_1_GwGm.dat | 2 - .../small_single_aisle_GwGm.dat | 4 +- .../test_aircraft/aircraft_for_bench_FwFm.csv | 1 - .../test_aircraft/aircraft_for_bench_FwGm.csv | 1 - .../test_aircraft/aircraft_for_bench_GwFm.csv | 1 - .../test_aircraft/aircraft_for_bench_GwGm.csv | 1 - ...converter_configuration_test_data_GwGm.csv | 1 - ...converter_configuration_test_data_GwGm.dat | 4 +- aviary/utils/Fortran_to_Aviary.py | 7 ++ .../legacy_code_data/gasp_default_values.dat | 2 - aviary/utils/process_input_decks.py | 63 +++++------------- aviary/variable_info/variable_meta_data.py | 19 +----- aviary/variable_info/variables.py | 1 - 17 files changed, 57 insertions(+), 126 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index c60fad220..a1b309d8a 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -18,14 +18,13 @@ This section is under development. - climb_range: 0, - reserves: 0 -The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than 10 or anything between -1 and 0. There are three variables to control the reserve fuel in the model file (`.csv`): +The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than or equal to 0. There are two variables to control the reserve fuel in the model file (`.csv`): - `Aircraft.Design.RESERVES`: the required fuel reserves: directly in lbm, - `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel, -- `Aircraft.Design.RESERVES_OPTION`: if `Set_Direct` (1), use `Aircraft.Design.RESERVES`; if `Set_Fraction` (2), use `Aircraft.Design.RESERVES_FRACTION`. -If the value of parameter `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: -- if `reserves > 10.0`, we set `Aircraft.Design.RESERVES = reserves` and `Aircraft.Design.RESERVES_OPTION = 1`, -- if `-1.0 <= reserves <= 0`, we set `Aircraft.Design.RESERVES_FRACTION = reserves` and `Aircraft.Design.RESERVES_OPTION = 2`. +If the value of initial guess of `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: +- if `reserves > 1.0`, we set `Aircraft.Design.RESERVES = reserves`, +- if `0.0 <= reserves <= 1.0`, we set `Aircraft.Design.RESERVES_FRACTION = reserves`. The initial guess of `reserves` is always converted to the actual design reserves (instead of reserve factor) and is used to update the initial guesses of `fuel_burn_per_passenger_mile` and `cruise_mass_final`. diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 4847119b0..68e5ff51c 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -48,7 +48,7 @@ from aviary.variable_info.functions import setup_trajectory_params, override_aviary_vars from aviary.variable_info.variables import Aircraft, Mission, Dynamic -from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes, Reserves_Type +from aviary.variable_info.enums import AnalysisScheme, ProblemType, SpeedType, AlphaModes from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData from aviary.variable_info.variables_in import VariablesIn @@ -2439,43 +2439,27 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) reserves_val = self.aviary_inputs.get_val(Aircraft.Design.RESERVES, units='lbm') reserves_fac = self.aviary_inputs.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') - reserves_opt = self.aviary_inputs.get_val( - Aircraft.Design.RESERVES_OPTION, units='unitless') - if reserves_opt == Reserves_Type.Set_Direct: - if reserves_val > 10: - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_val}", - reserve_fuel={"val": reserves_val, "units": "lbm"} - ), - promotes_outputs=[("reserve_fuel", reserves_name)], - ) - else: - raise ValueError(f'"{Aircraft.Design.RESERVES}" is not valid below 10.') - elif reserves_opt == Reserves_Type.Set_Fraction: - if reserves_fac <= 0 and reserves_fac >= -1: - reserves_fac = -reserves_fac - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_fac}*(takeoff_mass - final_mass)", - takeoff_mass={"units": "lbm"}, - final_mass={"units": "lbm"}, - reserve_fuel={"units": "lbm"} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Summary.GROSS_MASS), - ("final_mass", Mission.Landing.TOUCHDOWN_MASS), - ], - promotes_outputs=[("reserve_fuel", reserves_name)], - ) - elif reserves_fac > 0 and reserves_fac <= 1: - raise ValueError( - f'"{Aircraft.Design.RESERVES_FRACTION}" between 0 and 1 is not implemented.') - else: - raise ValueError( - f'"{Aircraft.Design.RESERVES_FRACTION}" is not valid if less than -1 or larger than 1.') + if reserves_val > 0.0: + self.model.add_subsystem( + "reserves_calc", + om.ExecComp( + f"reserve_fuel = {reserves_val}", + reserve_fuel={"val": reserves_val, "units": "lbm"} + ), + promotes_outputs=[("reserve_fuel", reserves_name)], + ) else: - raise ValueError(f'"{Aircraft.Design.RESERVES_OPTION}" must be \ - {Reserves_Type.Set_Directn} or {Reserves_Type.Set_Fraction}.') + self.model.add_subsystem( + "reserves_calc", + om.ExecComp( + f"reserve_fuel = {reserves_fac}*(takeoff_mass - final_mass)", + takeoff_mass={"units": "lbm"}, + final_mass={"units": "lbm"}, + reserve_fuel={"units": "lbm"} + ), + promotes_inputs=[ + ("takeoff_mass", Mission.Summary.GROSS_MASS), + ("final_mass", Mission.Landing.TOUCHDOWN_MASS), + ], + promotes_outputs=[("reserve_fuel", reserves_name)], + ) diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 7fed83a67..8109be9e5 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -76,7 +76,7 @@ def test_gasp_relative_reserve(self): Aircraft.Design.RESERVES_FRACTION, units='unitless') td_mass = prob.model.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm') reserve = prob.model.get_val(Mission.Design.RESERVE_FUEL, units='lbm') - assert_near_equal(reserve, -res_frac * (140000.0 - td_mass), 1e-3) + assert_near_equal(reserve, res_frac * (140000.0 - td_mass), 1e-3) if __name__ == '__main__': diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index 2092a85fb..0bf88a607 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -16,7 +16,6 @@ aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,4998,lbm aircraft:design:reserves_fraction,0,unitless -aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat index b8a4d51f3..f23fff285 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat @@ -195,8 +195,6 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) FRESF=4998, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) - FRESF2=0, ! Reserve fuel fraction of mission fuel (negative sign trigger) - FRESF3=1, ! Use Reserve Fuel RF(1)=.05, ! Reserve Fuel Input: Time for Missed Approach RF(2)=125., ! Reserve Fuel Input: Range to alternate RF(3)=20000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat index d6736b834..9ad297777 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat @@ -205,9 +205,7 @@ OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=0, ! Reserve Fuel - FRESF2=-.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) - FRESF3=2, ! Use Reserve Fuel + FRESF=0.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) RF(1)=2.0, ! Reserve Fuel Input: Time for Missed Approach (min) RF(2)=100., ! Reserve Fuel Input: Range to alternate RF(3)=25000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index a3b66e387..c415c912b 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -26,7 +26,6 @@ aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:reserves,3000.,lbm -aircraft:design:reserves_option,1,unitless aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index 316c73a5c..2224b8ba5 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -13,7 +13,6 @@ aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551, aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,3000.,lbm -aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 4881c183b..9688bdf8d 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -40,7 +40,6 @@ aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,5000.,lbm -aircraft:design:reserves_option,1,unitless aircraft:design:smooth_mass_discontinuities,False,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index 17f76a7c0..de310d32c 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -14,7 +14,6 @@ aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551, aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,4998,lbm -aircraft:design:reserves_option,1,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index 4367304b9..a9e6e1ce0 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -16,7 +16,6 @@ aircraft:design:max_structural_speed,440,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,0,lbm aircraft:design:reserves_fraction,-0.15,unitless -aircraft:design:reserves_option,2,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat index e6ed8dbee..ce493357c 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat @@ -209,9 +209,7 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=0, ! Reserve Fuel - FRESF2=-0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) - FRESF3=2, ! Use Reserve Fuel fraction + FRESF=0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) RF(1)=.05, ! Reserve Fuel Input: Time for Missed Approach RF(2)=125., ! Reserve Fuel Input: Range to alternate RF(3)=20000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index 63a035830..e46b1f27d 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -434,6 +434,13 @@ def update_gasp_options(vehicle_data): input_values.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, [[.12, .23, .13, .23, .23, .1, .15][flap_ind]]) + res = input_values.get_val(Aircraft.Design.RESERVES, units='lbm')[0] + if res <= 1.0: + input_values.set_val(Aircraft.Design.RESERVES, [0], units='lbm') + input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [-res], units='unitless') + else: + input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [0], units='unitless') + vehicle_data['input_values'] = input_values return vehicle_data diff --git a/aviary/utils/legacy_code_data/gasp_default_values.dat b/aviary/utils/legacy_code_data/gasp_default_values.dat index 9121140fb..686f5f1d7 100644 --- a/aviary/utils/legacy_code_data/gasp_default_values.dat +++ b/aviary/utils/legacy_code_data/gasp_default_values.dat @@ -84,8 +84,6 @@ FLAPN=1,unitless FN_REF=28690,lbf FPYL=0.7,unitless FRESF=4998,lbm -FRESF2=-0.1,unitless -FRESF3=1,unitless FUELD=6.687,lbm/galUS FVOL_MRG=0,unitless HAPP=50,ft diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index c7fa8c26b..49ea338a5 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -22,7 +22,7 @@ from aviary.utils.aviary_values import AviaryValues, get_keys from aviary.utils.functions import convert_strings_to_data, set_value from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.enums import ProblemType, Reserves_Type +from aviary.variable_info.enums import ProblemType from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission from aviary.utils.functions import get_path @@ -47,8 +47,6 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998, units='lbm') aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') - aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, - val=Reserves_Type.Set_None, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -167,56 +165,29 @@ def update_dependent_options(aircraft_values: AviaryValues(), dependent_options) def initial_guessing(aircraft_values: AviaryValues()): problem_type = aircraft_values.get_val('problem_type') - reserves_option = aircraft_values.get_val(Aircraft.Design.RESERVES_OPTION) - reserves = aircraft_values.get_val( - Aircraft.Design.RESERVES, units='lbm') if initial_guesses['reserves'] == 0 else initial_guesses['reserves'] - if reserves_option == Reserves_Type.Set_Direct: - aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') - if reserves < 10: - raise ValueError( - f'"{Aircraft.Design.RESERVES}" must be greater than 10 lbm.') - elif reserves_option == Reserves_Type.Set_Fraction: - if initial_guesses['reserves'] == 0: + if initial_guesses['reserves'] == 0: + reserves = aircraft_values.get_val(Aircraft.Design.RESERVES, units='lbm') + if reserves == 0: reserves = aircraft_values.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') - else: - reserves = initial_guesses['reserves'] - aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, - reserves, units='unitless') - if reserves < -1 or reserves > 0: - raise ValueError( - f'"{Aircraft.Design.RESERVES_FRACTION}" must be in [-1, 0].') else: - # if Aircraft.Design.RESERVES_FRACTION is not set, - # then determine reserves based on initial_guesses['reserves'] - if initial_guesses['reserves'] > 10: - reserves = initial_guesses['reserves'] - reserves_option = Reserves_Type.Set_Direct - aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') - elif initial_guesses['reserves'] < 0: - reserves = initial_guesses['reserves'] - reserves_option = Reserves_Type.Set_Fraction - aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, - reserves, units='unitless') - elif initial_guesses['reserves'] == 0 and reserves > 10: - reserves_option = Reserves_Type.Set_Direct + reserves = initial_guesses['reserves'] + if reserves < 0.0: + raise ValueError('initial_guesses["reserves"] must be greater than 0.') + elif reserves <= 1.0: + aircraft_values.set_val(Aircraft.Design.RESERVES, 0.0, units='lbm') + aircraft_values.set_val( + Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') + else: aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') - elif initial_guesses['reserves'] == 0 and reserves < 0: - reserves_option = Reserves_Type.Set_Fraction - aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, - reserves, units='unitless') - aircraft_values.set_val(Aircraft.Design.RESERVES_OPTION, - reserves_option, units='unitless') + aircraft_values.set_val( + Aircraft.Design.RESERVES_FRACTION, 0.0, units='unitless') num_pax = aircraft_values.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - if reserves_option == Reserves_Type.Set_Fraction: - if reserves <= 0: - reserves *= -(num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * - aircraft_values.get_val(Mission.Design.RANGE, units='NM')) - else: - raise ValueError( - f'The case that "{Aircraft.Design.RESERVES_FRACTION}" is between 0 and 1 is not implemented.') + if reserves <= 0: + reserves *= -(num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * + aircraft_values.get_val(Mission.Design.RANGE, units='NM')) initial_guesses['reserves'] = reserves if Mission.Summary.GROSS_MASS in aircraft_values: diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index cb3e9f42f..ac3334802 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -7,7 +7,7 @@ import numpy as np from aviary.utils.develop_metadata import add_meta_data -from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type, Reserves_Type +from aviary.variable_info.enums import Flap_Type, GASP_Engine_Type from aviary.variable_info.variables import Aircraft, Dynamic, Mission # --------------------------- @@ -1212,7 +1212,7 @@ add_meta_data( Aircraft.Design.RESERVES_FRACTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FRESF2', # the real name is INGASP.FRESF + historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None }, @@ -1222,21 +1222,6 @@ default_value=0, ) -add_meta_data( - Aircraft.Design.RESERVES_OPTION, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FRESF3', # the real name is INGASP.FRESF - "FLOPS": None, - "LEAPS1": None - }, - option=True, - types=Reserves_Type, - units="unitless", - desc=f'if {Reserves_Type.Set_Direct}, use Aircraft.Design.RESERVES; \ - if {Reserves_Type.Set_Fraction}, use Aircraft.Design.RESERVES_FRACTION', - default_value=Reserves_Type.Set_None, -) - add_meta_data( Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, meta_data=_MetaData, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index df40a30ad..a8cdad7cb 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -150,7 +150,6 @@ class Design: PART25_STRUCTURAL_CATEGORY = 'aircraft:design:part25_structural_category' RESERVES = 'aircraft:design:reserves' RESERVES_FRACTION = 'aircraft:design:reserves_fraction' - RESERVES_OPTION = 'aircraft:design:reserves_option' SMOOTH_MASS_DISCONTINUITIES = 'aircraft:design:smooth_mass_discontinuities' STATIC_MARGIN = 'aircraft:design:static_margin' STRUCTURAL_MASS_INCREMENT = 'aircraft:design:structural_mass_increment' From 54cdb4ee537ffa8c50bfa9f0a2a616a78475fb83 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 8 Jan 2024 17:38:14 -0500 Subject: [PATCH 009/111] removed RESERVES_OPTION and set RESERVES_FRACTION to positive --- aviary/models/small_single_aisle/small_single_aisle_GwGm.csv | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index c444f9a8e..8b6bae066 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -16,7 +16,6 @@ aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserves,0,lbm aircraft:design:reserves_fraction,-0.125,unitless -aircraft:design:reserves_option,2,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless From 24713b66d1f4beb5f154a6ce796f4e743f2e8dd7 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 17:31:11 -0600 Subject: [PATCH 010/111] Converting over tests to not use FLOPS mission method --- aviary/interface/methods_for_level2.py | 82 +++++----------- aviary/interface/test/test_interface_bugs.py | 2 +- aviary/interface/test/test_reserve_support.py | 16 +-- .../test/test_custom_engine_model.py | 97 +++++-------------- .../test/test_external_subsystem_bus.py | 16 ++- 5 files changed, 58 insertions(+), 155 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 3801359aa..3d867983c 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -18,9 +18,6 @@ from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.mission.flops_based.phases.descent_phase import Descent from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE from aviary.mission.gasp_based.ode.params import ParamPort @@ -146,6 +143,10 @@ def __init__(self, phase_info, mission_method, mass_method, analysis_scheme=Anal self.phase_info = phase_info self.traj = None + if mission_method == "FLOPS": + raise NotImplementedError( + "The FLOPS mission method is no longer supported in Aviary. Please use the `simple` mission method. This might require updating your `phase_info` object defintion.") + self.mission_method = mission_method self.mass_method = mass_method self.analysis_scheme = analysis_scheme @@ -361,7 +362,7 @@ def add_pre_mission_systems(self): self._add_gasp_takeoff_systems() # Check for 'FLOPS' mission method - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + elif self.mission_method == "simple": self._add_flops_takeoff_systems() def _add_flops_takeoff_systems(self): @@ -651,30 +652,9 @@ def _get_flops_phase(self, phase_name, phase_idx): default_mission_subsystems = [ subsystems['aerodynamics'], subsystems['propulsion']] - if self.mission_method == "FLOPS" or self.mission_method == "simple": - if self.mission_method == "simple": - climb_builder = EnergyPhase - cruise_builder = EnergyPhase - descent_builder = EnergyPhase - else: - climb_builder = Climb - cruise_builder = Cruise - descent_builder = Descent - - if phase_name == 'climb': - phase_object = climb_builder.from_phase_info( - phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) - - elif phase_name == 'cruise': - phase_object = cruise_builder.from_phase_info( - phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) - - elif phase_name == 'descent': - phase_object = descent_builder.from_phase_info( - phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) - else: - phase_object = EnergyPhase.from_phase_info( - phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) + if self.mission_method == "simple": + phase_object = EnergyPhase.from_phase_info( + phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) phase = phase_object.build_phase(aviary_options=self.aviary_inputs) @@ -1009,7 +989,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): if phase_name == 'ascent': self._add_groundroll_eq_constraint(phase) - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + elif self.mission_method == "simple": for phase_idx, phase_name in enumerate(phases): phase = traj.add_phase( phase_name, self._get_flops_phase(phase_name, phase_idx)) @@ -1131,7 +1111,7 @@ def add_post_mission_systems(self, include_landing=True): """ if include_landing and self.post_mission_info['include_landing']: - if self.mission_method == "FLOPS" or self.mission_method == "simple": + if self.mission_method == "simple": self._add_flops_landing_systems() elif self.mission_method == "GASP": self._add_gasp_landing_systems() @@ -1150,7 +1130,7 @@ def add_post_mission_systems(self, include_landing=True): self.post_mission.add_subsystem(external_subsystem.name, subsystem_postmission) - if self.mission_method == "FLOPS" or self.mission_method == "simple": + if self.mission_method == "simple": phases = list(self.phase_info.keys()) ecomp = om.ExecComp('fuel_burned = initial_mass - mass_final', initial_mass={'units': 'lbm'}, @@ -1325,13 +1305,6 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): self._link_phases_helper_with_options( phases, 'optimize_mach', Dynamic.Mission.MACH) - elif self.mission_method == "FLOPS": - self.traj.link_phases( - phases, ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=False, ref=1.e4) - self.traj.link_phases( - phases, [Dynamic.Mission.VELOCITY], connected=False, ref=250.) - elif self.mission_method == "GASP": if self.analysis_scheme is AnalysisScheme.COLLOCATION: self.traj.link_phases(["groundroll", "rotation", "ascent"], [ @@ -1584,7 +1557,7 @@ def add_design_variables(self): for dv_name, dv_dict in dv_dict.items(): self.model.add_design_var(dv_name, **dv_dict) - if self.mission_method == "FLOPS" or self.mission_method == "simple": + if self.mission_method == "simple": optimize_mass = self.pre_mission_info.get('optimize_mass') if optimize_mass: self.model.add_design_var(Mission.Design.GROSS_MASS, units='lbm', @@ -1707,7 +1680,7 @@ def add_objective(self, objective_type=None, ref=None): self.model.add_objective(Mission.Objectives.FUEL, ref=ref) # If 'mission_method' is 'FLOPS', add a 'fuel_burned' objective - elif self.mission_method == "FLOPS" or self.mission_method == "simple": + elif self.mission_method == "simple": ref = ref if ref is not None else default_ref_values.get("fuel_burned", 1) self.model.add_objective("fuel_burned", ref=ref) @@ -2347,30 +2320,19 @@ def _add_flops_landing_systems(self): 'traj.climb.initial_states:mass') self.model.connect(Mission.Takeoff.GROUND_DISTANCE, 'traj.climb.initial_states:range') - if self.mission_method == "FLOPS": - self.model.connect(Mission.Takeoff.FINAL_VELOCITY, - 'traj.climb.initial_states:velocity') - self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'traj.climb.initial_states:altitude') - else: - pass - # TODO: connect this correctly - # mass is the most important to connect but these others should - # be connected as well - # self.model.connect(Mission.Takeoff.FINAL_VELOCITY, - # 'traj.climb.initial_states:mach') - # self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - # 'traj.climb.controls:altitude') + # TODO: connect this correctly + # mass is the most important to connect but these others should + # be connected as well + # self.model.connect(Mission.Takeoff.FINAL_VELOCITY, + # 'traj.climb.initial_states:mach') + # self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, + # 'traj.climb.controls:altitude') self.model.connect('traj.descent.states:mass', Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) # TODO: approach velocity should likely be connected - if self.mission_method == "FLOPS": - self.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[-1]) - else: - self.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[0]) + self.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE, + src_indices=[0]) def _add_gasp_landing_systems(self): self.model.add_subsystem( diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index cf60b67f8..44089da8b 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -67,7 +67,7 @@ def test_post_mission_promotion(self): WingWeightBuilder(name="wing_external") ] - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS") csv_path = pkg_resources.resource_filename( "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index b0b3982d8..5419efd15 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -1,12 +1,11 @@ from copy import deepcopy -import pkg_resources import unittest from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.default_phase_info.flops import phase_info as ph_in_flops +from aviary.interface.default_phase_info.simple import phase_info as ph_in_flops from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp from aviary.variable_info.variables import Aircraft, Mission @@ -17,12 +16,9 @@ class StaticGroupTest(unittest.TestCase): def test_post_mission_promotion(self): phase_info = deepcopy(ph_in_flops) - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS") - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - - prob.load_inputs(csv_path) + prob.load_inputs("models/test_aircraft/aircraft_for_bench_FwFm.csv") prob.check_inputs() # TODO: This needs to be converted into a reserve and a scaler so that it can @@ -40,6 +36,7 @@ def test_post_mission_promotion(self): prob.add_objective(objective_type="mass", ref=-1e5) prob.setup() + prob.set_initial_guesses() prob.run_model() @@ -53,10 +50,7 @@ def test_gasp_relative_reserve(self): prob = AviaryProblem(phase_info, mission_method="GASP", mass_method="GASP") - csv_path = pkg_resources.resource_filename( - "aviary", "models/small_single_aisle/small_single_aisle_GwGm.csv") - - prob.load_inputs(csv_path) + prob.load_inputs("models/small_single_aisle/small_single_aisle_GwGm.csv") prob.check_inputs() prob.aviary_inputs.set_val(Mission.Summary.GROSS_MASS, 140000.0, units='lbm') diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index 0619d5ff3..40fee525e 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -1,16 +1,12 @@ import unittest -import openmdao import dymos as dm import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal -from packaging import version from aviary.subsystems.propulsion.engine_model import EngineModel from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic -import dymos as dm -import unittest from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs @@ -126,13 +122,8 @@ def get_initial_guesses(self): @use_tempdirs class CustomEngineTest(unittest.TestCase): def test_custom_engine(self): - - import pkg_resources - from aviary.interface.methods_for_level2 import AviaryProblem - aero_data = "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt" - phase_info = { 'pre_mission': { 'include_takeoff': False, @@ -140,38 +131,28 @@ def test_custom_engine(self): 'optimize_mass': True, }, 'cruise': { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'solved_alpha', 'aero_data': aero_data, 'training_data': False} + "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, + "user_options": { + "optimize_mach": False, + "optimize_altitude": False, + "polynomial_control_order": 1, + "num_segments": 2, + "order": 3, + "solve_for_range": False, + "initial_mach": (0.72, "unitless"), + "final_mach": (0.72, "unitless"), + "mach_bounds": ((0.7, 0.74), "unitless"), + "initial_altitude": (35000.0, "ft"), + "final_altitude": (35000.0, "ft"), + "altitude_bounds": ((23000.0, 38000.0), "ft"), + "throttle_enforcement": "boundary_constraint", + "fix_initial": False, + "constrain_final": False, + "fix_duration": False, + "initial_bounds": ((0.0, 0.0), "min"), + "duration_bounds": ((10., 30.), "min"), }, - 'external_subsystems': [], - 'user_options': { - 'fix_initial': False, - 'fix_final': False, - 'fix_duration': False, - 'num_segments': 2, - 'order': 3, - 'initial_ref': (1., 's'), - 'initial_bounds': ((0., 0.), 's'), - 'duration_ref': (21.e3, 's'), - 'duration_bounds': ((1.e3, 10.e3), 's'), - 'min_altitude': (10.668e3, 'm'), - 'max_altitude': (10.668e3, 'm'), - 'min_mach': 0.8, - 'max_mach': 0.8, - 'required_available_climb_rate': (1.524, 'm/s'), - 'input_initial': False, - 'mass_f_cruise': (1.e4, 'lbm'), - 'range_f_cruise': (1.e6, 'm'), - }, - 'initial_guesses': { - 'times': ([0., 30.], 'min'), - 'altitude': ([35.e3, 35.e3], 'ft'), - 'velocity': ([455.49, 455.49], 'kn'), - 'mass': ([130.e3, 128.e3], 'lbm'), - 'range': ([0., 300.], 'nmi'), - 'velocity_rate': ([0., 0.], 'm/s**2'), - 'throttle': ([0.6, 0.6], 'unitless'), - } + "initial_guesses": {"times": ([0, 30], "min")}, }, 'post_mission': { 'include_landing': False, @@ -179,15 +160,13 @@ def test_custom_engine(self): } } - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - - prob = AviaryProblem(phase_info, mission_method="FLOPS", + prob = AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS", reports=False) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(csv_path, engine_builder=SimpleTestEngine()) + prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", + engine_builder=SimpleTestEngine()) # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -226,34 +205,6 @@ def test_custom_engine(self): assert_near_equal(float(prob.get_val('traj.cruise.rhs_all.y')), 4., tol) - prob_vars = prob.list_problem_vars( - print_arrays=True, driver_scaling=False, out_stream=None) - - design_vars_dict = dict(prob_vars['design_vars']) - - # List of all expected variable names in design_vars - expected_var_names = [ - 'traj.phases.cruise.indep_states.states:altitude', - 'traj.phases.cruise.indep_states.states:velocity', - 'traj.phases.cruise.indep_states.states:mass', - 'traj.phases.cruise.indep_states.states:range', - ] - - # Check that all expected variable names are present in design_vars - for var_name in expected_var_names: - self.assertIn(var_name, design_vars_dict) - - # Check values - assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:altitude']['val'], [ - 10668.] * 7, tolerance=tol) - assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:velocity']['val'], [ - 234.3243] * 7, tolerance=tol) - # print the mass and range - assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:mass']['val'], [ - 58967.0081, 58805.95966377, 58583.74569223, 58513.41573, 58352.36729377, 58130.15332223, 58059.82336], tolerance=tol) - assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:range']['val'], [ - 0., 98633.17494548, 234726.82505452, 277800., 376433.17494548, 512526.82505452, 555600.], tolerance=tol) - if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/test/test_external_subsystem_bus.py b/aviary/subsystems/test/test_external_subsystem_bus.py index f8257a1b5..a88f1067b 100644 --- a/aviary/subsystems/test/test_external_subsystem_bus.py +++ b/aviary/subsystems/test/test_external_subsystem_bus.py @@ -1,8 +1,7 @@ """ - Test external subsystem bus API. +Test external subsystem bus API. """ from copy import deepcopy -import pkg_resources import unittest import numpy as np @@ -10,8 +9,7 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal -import aviary.api as av -from aviary.interface.default_phase_info.flops import phase_info as ph_in +from aviary.interface.default_phase_info.simple import phase_info as ph_in from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase @@ -23,7 +21,7 @@ def setup(self): self.add_output('for_cruise', np.ones((2, 1)), units='ft') self.add_output('for_descent', np.ones((2, 1)), units='ft') - def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + def compute(self, inputs, outputs): outputs['for_climb'] = np.array([[3.1], [1.7]]) outputs['for_cruise'] = np.array([[1.2], [4.1]]) outputs['for_descent'] = np.array([[3.], [8.]]) @@ -39,7 +37,7 @@ def setup(self): self.add_input('xx', shape=shape, units='ft') self.add_output('yy', shape=shape, units='ft') - def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + def compute(self, inputs, outputs): outputs['yy'] = 2.0 * inputs['xx'] @@ -90,11 +88,9 @@ def test_external_subsystem_bus(self): phase_info['cruise']['external_subsystems'] = [CustomBuilder(name='test')] phase_info['descent']['external_subsystems'] = [CustomBuilder(name='test')] - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS") - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_FwFm.csv") - prob.load_inputs(csv_path) + prob.load_inputs("models/test_aircraft/aircraft_for_bench_FwFm.csv") prob.check_inputs() prob.add_pre_mission_systems() From c91210b2ff133c12280e6fde285310363bf22e1c Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 17:39:19 -0600 Subject: [PATCH 011/111] updating more tests --- .../test/test_solved_aero_group.py | 10 +- .../test_subsystems_within_a_mission.py | 92 ++++++++----------- 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index 59c5dc0b7..117d5854e 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -14,7 +14,7 @@ from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.csv_data_file import read_data_file from aviary.utils.named_values import NamedValues -from aviary.interface.default_phase_info.flops import phase_info +from aviary.interface.default_phase_info.simple import phase_info from aviary.variable_info.variables import Aircraft from copy import deepcopy @@ -47,7 +47,7 @@ class TestSolvedAero(unittest.TestCase): def test_solved_aero_pass_polar(self): # Test that passing training data provides the same results prob = AviaryProblem( - phase_info, mission_method="FLOPS", mass_method="FLOPS") + phase_info, mission_method="simple", mass_method="FLOPS") csv_path = pkg_resources.resource_filename( "aviary", "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv") @@ -88,7 +88,7 @@ def test_solved_aero_pass_polar(self): ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} - prob = AviaryProblem(ph_in, mission_method="FLOPS", mass_method="FLOPS") + prob = AviaryProblem(ph_in, mission_method="simple", mass_method="FLOPS") prob.load_inputs(csv_path) @@ -203,6 +203,4 @@ def build_pre_mission(self, aviary_inputs): if __name__ == "__main__": - # unittest.main() - test = TestSolvedAero() - test.test_solved_aero_pass_polar() + unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index 795424041..1535269e4 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -1,7 +1,6 @@ import numpy as np import unittest -import pkg_resources from numpy.testing import assert_almost_equal from openmdao.utils.testing_utils import use_tempdirs @@ -15,48 +14,36 @@ @use_tempdirs class TestSubsystemsMission(unittest.TestCase): def setUp(self): - polar_file = "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt" - aero_data = pkg_resources.resource_filename("aviary", polar_file) - self.phase_info = { 'pre_mission': { 'include_takeoff': False, 'external_subsystems': [ArrayGuessSubsystemBuilder(), AdditionalArrayGuessSubsystemBuilder()], - 'optimize_mass': False, + 'optimize_mass': True, }, 'cruise': { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'solved_alpha', 'aero_data': aero_data, 'training_data': False} - }, + "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, 'external_subsystems': [ArrayGuessSubsystemBuilder(), AdditionalArrayGuessSubsystemBuilder()], - 'user_options': { - 'fix_initial': True, - 'fix_final': False, - 'fix_duration': False, - 'num_segments': 1, - 'order': 5, - 'initial_ref': (1., 's'), - 'initial_bounds': ((0., 0.), 's'), - 'duration_ref': (21.e3, 's'), - 'duration_bounds': ((10.e3, 20.e3), 's'), - 'min_altitude': (10.668e3, 'm'), - 'max_altitude': (10.668e3, 'm'), - 'min_mach': 0.8, - 'max_mach': 0.8, - 'required_available_climb_rate': (1.524, 'm/s'), - 'input_initial': False, - 'mass_f_cruise': (1.e4, 'lbm'), - 'range_f_cruise': (1.e6, 'm'), + "user_options": { + "optimize_mach": False, + "optimize_altitude": False, + "polynomial_control_order": 1, + "num_segments": 2, + "order": 3, + "solve_for_range": False, + "initial_mach": (0.72, "unitless"), + "final_mach": (0.72, "unitless"), + "mach_bounds": ((0.7, 0.74), "unitless"), + "initial_altitude": (35000.0, "ft"), + "final_altitude": (35000.0, "ft"), + "altitude_bounds": ((23000.0, 38000.0), "ft"), + "throttle_enforcement": "boundary_constraint", + "fix_initial": True, + "constrain_final": False, + "fix_duration": False, + "initial_bounds": ((0.0, 0.0), "min"), + "duration_bounds": ((10., 30.), "min"), }, - 'initial_guesses': { - 'times': ([0., 15000.], 's'), - 'altitude': ([35.e3, 35.e3], 'ft'), - 'velocity': ([455.49, 455.49], 'kn'), - 'mass': ([130.e3, 120.e3], 'lbm'), - 'range': ([0., 3000.], 'NM'), - 'velocity_rate': ([0., 0.], 'm/s**2'), - 'throttle': ([0.6, 0.6], 'unitless'), - } + "initial_guesses": {"times": ([0, 30], "min")}, }, 'post_mission': { 'include_landing': False, @@ -68,12 +55,9 @@ def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() prob = AviaryProblem( - phase_info, mission_method="FLOPS", mass_method="FLOPS") + phase_info, mission_method="simple", mass_method="FLOPS") - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - - prob.load_inputs(csv_path) + prob.load_inputs("models/test_aircraft/aircraft_for_bench_FwFm.csv") # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -102,29 +86,27 @@ def test_subsystems_in_a_mission(self): # add an assert to see if the initial guesses are correct for Mission.Dummy.VARIABLE assert_almost_equal(prob[f'traj.phases.cruise.states:{Mission.Dummy.VARIABLE}'], [[10.], - [22.57838779], - [47.47686109], - [75.08412877], - [94.86062235], - [100.],]) + [25.97729616], + [48.02270384], + [55.], + [70.97729616], + [93.02270384], + [100.]]) prob.run_aviary_problem() # add an assert to see if MoreMission.Dummy.TIMESERIES_VAR was correctly added to the dymos problem assert_almost_equal(prob[f'traj.phases.cruise.timeseries.{MoreMission.Dummy.TIMESERIES_VAR}'], np.array( - [[0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]).T) + [[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]).T) def test_bad_initial_guess_key(self): phase_info = self.phase_info.copy() phase_info['cruise']['initial_guesses']['bad_guess_name'] = ([10., 100.], 'm') - prob = AviaryProblem(phase_info, mission_method="FLOPS", + prob = AviaryProblem(phase_info, mission_method="simple", mass_method="FLOPS", reports=False) - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_GwFm.csv") - - prob.load_inputs(csv_path) + prob.load_inputs("models/test_aircraft/aircraft_for_bench_FwFm.csv") # Have checks for clashing user inputs # Raise warnings or errors depending on how clashing the issues are @@ -134,12 +116,10 @@ def test_bad_initial_guess_key(self): with self.assertRaises(TypeError) as context: prob.add_phases() + print(str(context.exception)) self.assertTrue( - 'Cruise: cruise: unsupported initial guess: bad_guess_name' in str(context.exception)) + 'EnergyPhase: cruise: unsupported initial guess: bad_guess_name' in str(context.exception)) if __name__ == "__main__": - # unittest.main() - test = TestSubsystemsMission() - test.setUp() - test.test_subsystems_in_a_mission() + unittest.main() From 0005f91cbfd35fb8dfafc1d07ada9d908f9810f1 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 17:41:13 -0600 Subject: [PATCH 012/111] All tests pass, benchmarks next --- .../benchmark_tests/test_0_iters.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 4656a3be2..a016efa4c 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -1,17 +1,12 @@ -import os import unittest -import pkg_resources import dymos from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from packaging import version -from aviary.api import Mission, Dynamic from aviary.interface.methods_for_level2 import AviaryProblem from aviary.interface.default_phase_info.gasp import phase_info as gasp_phase_info -from aviary.interface.default_phase_info.flops import phase_info as flops_phase_info -from aviary.interface.default_phase_info.flops import phase_info as ph_in +from aviary.interface.default_phase_info.simple import phase_info as flops_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info -from copy import deepcopy class BaseProblemPhaseTestCase(unittest.TestCase): @@ -50,7 +45,7 @@ class FLOPSZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_flops_zero_iters(self): - self.build_and_run_problem(flops_phase_info, "FLOPS", + self.build_and_run_problem(flops_phase_info, "simple", "FLOPS", 'models/test_aircraft/aircraft_for_bench_FwFm.csv') @@ -67,6 +62,6 @@ def test_zero_iters_solved(self): if __name__ == "__main__": - # unittest.main() - test = FLOPSZeroItersTestCase() - test.test_flops_zero_iters() + unittest.main() + # test = FLOPSZeroItersTestCase() + # test.test_flops_zero_iters() From ac6087d25a80d93242ed5e85a951907ebc3c8ec4 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 8 Jan 2024 19:23:47 -0500 Subject: [PATCH 013/111] rename Aircraft.Design.RESERVES to Aircraft.Design.FIXED_RESERVES_FUEL and remove Aircraft.Design.IJEFF --- .../getting_started/input_csv_phase_info.md | 4 +-- aviary/interface/methods_for_level2.py | 5 +-- aviary/interface/test/test_reserve_support.py | 3 +- .../large_single_aisle_1_GwGm.csv | 2 +- .../small_single_aisle_GwGm.csv | 4 +-- .../test_aircraft/aircraft_for_bench_FwFm.csv | 2 +- .../test_aircraft/aircraft_for_bench_FwGm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwGm.csv | 2 +- ...converter_configuration_test_data_GwGm.csv | 4 +-- aviary/utils/Fortran_to_Aviary.py | 6 ++-- aviary/utils/process_input_decks.py | 11 ++++--- aviary/variable_info/variable_meta_data.py | 32 ++++++------------- aviary/variable_info/variables.py | 3 +- 14 files changed, 37 insertions(+), 45 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index a1b309d8a..6f3781fd3 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -19,11 +19,11 @@ This section is under development. - reserves: 0 The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than or equal to 0. There are two variables to control the reserve fuel in the model file (`.csv`): -- `Aircraft.Design.RESERVES`: the required fuel reserves: directly in lbm, +- `Aircraft.Design.FIXED_RESERVES_FUEL`: the required fuel reserves: directly in lbm, - `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel, If the value of initial guess of `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: -- if `reserves > 1.0`, we set `Aircraft.Design.RESERVES = reserves`, +- if `reserves > 1.0`, we set `Aircraft.Design.FIXED_RESERVES_FUEL = reserves`, - if `0.0 <= reserves <= 1.0`, we set `Aircraft.Design.RESERVES_FRACTION = reserves`. The initial guess of `reserves` is always converted to the actual design reserves (instead of reserve factor) and is used to update the initial guesses of `fuel_burn_per_passenger_mile` and `cruise_mass_final`. diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 68e5ff51c..3667ae4e9 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2436,7 +2436,8 @@ def _add_gasp_landing_systems(self): ) def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL): - reserves_val = self.aviary_inputs.get_val(Aircraft.Design.RESERVES, units='lbm') + reserves_val = self.aviary_inputs.get_val( + Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') reserves_fac = self.aviary_inputs.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') if reserves_val > 0.0: @@ -2448,7 +2449,7 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) ), promotes_outputs=[("reserve_fuel", reserves_name)], ) - else: + elif reserves_fac >= 0 and reserves_fac <= 1: self.model.add_subsystem( "reserves_calc", om.ExecComp( diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 8109be9e5..860ac397e 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -25,7 +25,8 @@ def test_post_mission_promotion(self): prob.load_inputs(csv_path) prob.check_inputs() - prob.aviary_inputs.set_val(Aircraft.Design.RESERVES, 10000.0, units='lbm') + prob.aviary_inputs.set_val( + Aircraft.Design.FIXED_RESERVES_FUEL, 10000.0, units='lbm') prob.add_pre_mission_systems() prob.add_phases() diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index 0bf88a607..b9b9912fe 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -12,9 +12,9 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless +aircraft:design:fixed_reserves_fuel,4998,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,4998,lbm aircraft:design:reserves_fraction,0,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index 8b6bae066..f47ed1bfb 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -12,10 +12,10 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless aircraft:design:drag_increment,0.0018,unitless aircraft:design:equipment_mass_coefficients,778,0.06,0.112,0.14,1349,1.65,397,9071,7.6,3,50,6,12,unitless +aircraft:design:fixed_reserves_fuel,0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,0,lbm -aircraft:design:reserves_fraction,-0.125,unitless +aircraft:design:reserves_fraction,0.125,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index c415c912b..01633dc49 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -25,7 +25,7 @@ aircraft:design:base_area,0.0,ft**2 aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:reserves,3000.,lbm +aircraft:design:fixed_reserves_fuel,3000.,lbm aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index 2224b8ba5..3a4f5348e 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -12,7 +12,7 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,3000.,lbm +aircraft:design:fixed_reserves_fuel,3000.,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 9688bdf8d..01f9be0cc 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -39,7 +39,7 @@ aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,5000.,lbm +aircraft:design:fixed_reserves_fuel,5000.,lbm aircraft:design:smooth_mass_discontinuities,False,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index de310d32c..c6c89e6f3 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -13,7 +13,7 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,4998,lbm +aircraft:design:fixed_reserves_fuel,4998,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index a9e6e1ce0..ee9f695ca 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -12,10 +12,10 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,30,unitless aircraft:design:drag_increment,0.0014,unitless aircraft:design:equipment_mass_coefficients,1014,0.0736,0.085,0.105,1504,1.65,126,9114,5,3,0,10,12,unitless +aircraft:design:fixed_reserves_fuel,0,lbm aircraft:design:max_structural_speed,440,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,0,lbm -aircraft:design:reserves_fraction,-0.15,unitless +aircraft:design:reserves_fraction,0.15,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index e46b1f27d..ce0f09aae 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -434,10 +434,10 @@ def update_gasp_options(vehicle_data): input_values.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, [[.12, .23, .13, .23, .23, .1, .15][flap_ind]]) - res = input_values.get_val(Aircraft.Design.RESERVES, units='lbm')[0] + res = input_values.get_val(Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm')[0] if res <= 1.0: - input_values.set_val(Aircraft.Design.RESERVES, [0], units='lbm') - input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [-res], units='unitless') + input_values.set_val(Aircraft.Design.FIXED_RESERVES_FUEL, [0], units='lbm') + input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [res], units='unitless') else: input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [0], units='unitless') diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 49ea338a5..7f2698895 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -45,7 +45,7 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val('mass_defect', val=10000, units='lbm') aircraft_values.set_val('problem_type', val=ProblemType.SIZING) aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998, units='lbm') + aircraft_values.set_val(Aircraft.Design.FIXED_RESERVES_FUEL, val=4998, units='lbm') aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -166,7 +166,8 @@ def update_dependent_options(aircraft_values: AviaryValues(), dependent_options) def initial_guessing(aircraft_values: AviaryValues()): problem_type = aircraft_values.get_val('problem_type') if initial_guesses['reserves'] == 0: - reserves = aircraft_values.get_val(Aircraft.Design.RESERVES, units='lbm') + reserves = aircraft_values.get_val( + Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') if reserves == 0: reserves = aircraft_values.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') @@ -175,11 +176,13 @@ def initial_guessing(aircraft_values: AviaryValues()): if reserves < 0.0: raise ValueError('initial_guesses["reserves"] must be greater than 0.') elif reserves <= 1.0: - aircraft_values.set_val(Aircraft.Design.RESERVES, 0.0, units='lbm') + aircraft_values.set_val( + Aircraft.Design.FIXED_RESERVES_FUEL, 0.0, units='lbm') aircraft_values.set_val( Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') else: - aircraft_values.set_val(Aircraft.Design.RESERVES, reserves, units='lbm') + aircraft_values.set_val( + Aircraft.Design.FIXED_RESERVES_FUEL, reserves, units='lbm') aircraft_values.set_val( Aircraft.Design.RESERVES_FRACTION, 0.0, units='unitless') diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index ac3334802..0c949e1c2 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1049,26 +1049,27 @@ ) add_meta_data( - Aircraft.Design.FIXED_USEFUL_LOAD, + Aircraft.Design.FIXED_RESERVES_FUEL, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WFUL', + historical_name={"GASP": 'INGASP.FRESF', "FLOPS": None, "LEAPS1": None }, - units='lbm', - desc='total mass of fixed useful load: crew, service items, trapped oil, etc', + option=True, + units="lbm", + desc='required fuel reserves: directly in lbm', + default_value=0, ) add_meta_data( - Aircraft.Design.IJEFF, + Aircraft.Design.FIXED_USEFUL_LOAD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ijeff', + historical_name={"GASP": 'INGASP.WFUL', "FLOPS": None, "LEAPS1": None }, - desc="A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. \ - This flag is planted here to thank him for his hard work and dedication, Aviary wouldn't be what it is today \ - without his help.", + units='lbm', + desc='total mass of fixed useful load: crew, service items, trapped oil, etc', ) add_meta_data( @@ -1196,19 +1197,6 @@ desc='part 25 structural category', ) -add_meta_data( - Aircraft.Design.RESERVES, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FRESF', - "FLOPS": None, - "LEAPS1": None - }, - option=True, - units="lbm", - desc='required fuel reserves: directly in lbm', - default_value=0, -) - add_meta_data( Aircraft.Design.RESERVES_FRACTION, meta_data=_MetaData, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index a8cdad7cb..84deaf290 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -131,8 +131,8 @@ class Design: EXTERNAL_SUBSYSTEMS_MASS = 'aircraft:design:external_subsystems_mass' FINENESS = 'aircraft:design:fineness' FIXED_EQUIPMENT_MASS = 'aircraft:design:fixed_equipment_mass' + FIXED_RESERVES_FUEL = 'aircraft:design:fixed_reserves_fuel' FIXED_USEFUL_LOAD = 'aircraft:design:fixed_useful_load' - IJEFF = 'aircraft:design:ijeff' LAMINAR_FLOW_LOWER = 'aircraft:design:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:design:laminar_flow_upper' @@ -148,7 +148,6 @@ class Design: MAX_STRUCTURAL_SPEED = 'aircraft:design:max_structural_speed' OPERATING_MASS = 'aircraft:design:operating_mass' PART25_STRUCTURAL_CATEGORY = 'aircraft:design:part25_structural_category' - RESERVES = 'aircraft:design:reserves' RESERVES_FRACTION = 'aircraft:design:reserves_fraction' SMOOTH_MASS_DISCONTINUITIES = 'aircraft:design:smooth_mass_discontinuities' STATIC_MARGIN = 'aircraft:design:static_margin' From f3ad946f15ddd30cdfba7f17b6045be226b00f24 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 19:13:37 -0600 Subject: [PATCH 014/111] All benchmarks pass with simple mission --- .../benchmark_tests/test_bench_FwFm.py | 13 +++-------- .../benchmark_tests/test_bench_GwFm.py | 11 ++-------- aviary/validation_cases/benchmark_utils.py | 22 +++++++------------ 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index c86c541df..fc7087aa0 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -3,7 +3,6 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.flops import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values @@ -263,12 +262,6 @@ def setUp(self): self.expected_dict = expected_dict def bench_test_swap_4_FwFm(self): - prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, - mission_method="FLOPS", mass_method="FLOPS") - - compare_against_expected_values(prob, self.expected_dict) - - def bench_test_swap_4_FwFm_simple(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, "climb": { @@ -353,17 +346,17 @@ def bench_test_swap_4_FwFm_simple(self): "post_mission": { "include_landing": True, "constrain_range": True, - "target_range": (3360.0, "nmi"), + "target_range": (3350.0, "nmi"), }, } prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, mission_method="simple", mass_method="FLOPS") - compare_against_expected_values(prob, self.expected_dict, simple_flag=True) + compare_against_expected_values(prob, self.expected_dict) if __name__ == '__main__': test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_4_FwFm_simple() + test.bench_test_swap_4_FwFm() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 2dd22d79b..37ba996e4 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -10,7 +10,6 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.flops import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values @@ -269,12 +268,6 @@ def setUp(self): self.expected_dict = expected_dict def bench_test_swap_1_GwFm(self): - prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info, - mission_method="FLOPS", mass_method="GASP") - - compare_against_expected_values(prob, self.expected_dict) - - def bench_test_swap_1_GwFm_simple(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, "climb": { @@ -364,10 +357,10 @@ def bench_test_swap_1_GwFm_simple(self): prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info, mission_method="simple", mass_method="GASP", max_iter=15) - compare_against_expected_values(prob, self.expected_dict, simple_flag=True) + compare_against_expected_values(prob, self.expected_dict) if __name__ == '__main__': z = ProblemPhaseTestCase() z.setUp() - z.bench_test_swap_1_GwFm_simple() + z.bench_test_swap_1_GwFm() diff --git a/aviary/validation_cases/benchmark_utils.py b/aviary/validation_cases/benchmark_utils.py index 22b1b97dd..f7d011fd4 100644 --- a/aviary/validation_cases/benchmark_utils.py +++ b/aviary/validation_cases/benchmark_utils.py @@ -5,7 +5,7 @@ from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -def compare_against_expected_values(prob, expected_dict, simple_flag=False): +def compare_against_expected_values(prob, expected_dict): expected_times = expected_dict['times'] expected_altitudes = expected_dict['altitudes'] @@ -22,20 +22,14 @@ def compare_against_expected_values(prob, expected_dict, simple_flag=False): for idx, phase in enumerate(['climb', 'cruise', 'descent']): times.extend(prob.get_val(f'traj.{phase}.timeseries.time', units='s')) - if simple_flag: - try: - altitudes.extend(prob.get_val( - f'traj.{phase}.timeseries.polynomial_controls:altitude', units='m')) - except KeyError: - altitudes.extend(prob.get_val( - f'traj.{phase}.timeseries.controls:altitude', units='m')) - velocities.extend(prob.get_val( - f'traj.{phase}.timeseries.velocity', units='m/s')) - else: + try: altitudes.extend(prob.get_val( - f'traj.{phase}.timeseries.states:altitude', units='m')) - velocities.extend(prob.get_val( - f'traj.{phase}.timeseries.states:velocity', units='m/s')) + f'traj.{phase}.timeseries.polynomial_controls:altitude', units='m')) + except KeyError: + altitudes.extend(prob.get_val( + f'traj.{phase}.timeseries.controls:altitude', units='m')) + velocities.extend(prob.get_val( + f'traj.{phase}.timeseries.velocity', units='m/s')) masses.extend( prob.get_val(f'traj.{phase}.timeseries.states:mass', units='kg')) ranges.extend( From a7b0e50f6e6b860cfc2db61d349379b52c3332f6 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 19:56:29 -0600 Subject: [PATCH 015/111] All tests pass; benchmarks next --- aviary/api.py | 4 - aviary/interface/test/test_interface_bugs.py | 2 +- aviary/interface/test/test_phase_info.py | 53 +- aviary/mission/flops_based/ode/mission_EOM.py | 48 -- aviary/mission/flops_based/ode/mission_ODE.py | 154 ----- .../flops_based/ode/test/test_mission_EOM.py | 55 -- .../phases/benchmark_tests/__init__.py | 0 .../test_bench_climb_large_single_aisle_1.py | 260 --------- .../test_bench_climb_large_single_aisle_2.py | 366 ------------ ...bench_cruise_climb_large_single_aisle_1.py | 316 ---------- .../test_bench_cruise_large_single_aisle_1.py | 253 -------- .../test_bench_cruise_large_single_aisle_2.py | 247 -------- ...test_bench_descent_large_single_aisle_1.py | 255 --------- ...test_bench_descent_large_single_aisle_2.py | 256 --------- .../mission/flops_based/phases/climb_phase.py | 102 ---- .../flops_based/phases/cruise_phase.py | 437 -------------- .../flops_based/phases/descent_phase.py | 103 ---- .../flops_based/phases/energy_phase.py | 541 ------------------ .../flops_based/phases/phase_builder_base.py | 2 +- .../flops_based/phases/simple_energy_phase.py | 3 +- .../test_FLOPS_based_full_mission_N3CC.py | 4 - ...based_full_mission_large_single_aisle_1.py | 6 - ...based_full_mission_large_single_aisle_2.py | 5 - .../test_FLOPS_based_sizing_N3CC.py | 3 - 24 files changed, 9 insertions(+), 3466 deletions(-) delete mode 100644 aviary/mission/flops_based/ode/mission_EOM.py delete mode 100644 aviary/mission/flops_based/ode/mission_ODE.py delete mode 100644 aviary/mission/flops_based/ode/test/test_mission_EOM.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/__init__.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py delete mode 100644 aviary/mission/flops_based/phases/climb_phase.py delete mode 100644 aviary/mission/flops_based/phases/cruise_phase.py delete mode 100644 aviary/mission/flops_based/phases/descent_phase.py delete mode 100644 aviary/mission/flops_based/phases/energy_phase.py diff --git a/aviary/api.py b/aviary/api.py index 3e969c3f6..a7e55c7a5 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -68,7 +68,6 @@ from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.flops_based.ode.landing_ode import LandingODE as DetailedLandingODE from aviary.mission.flops_based.ode.landing_ode import FlareODE as DetailedFlareODE -from aviary.mission.flops_based.ode.mission_ODE import MissionODE as HeightEnergyMissionODE from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE as DetailedTakeoffODE from aviary.mission.gasp_based.ode.accel_ode import AccelODE as TwoDOFAccelerationODE from aviary.mission.gasp_based.ode.ascent_ode import AscentODE as TwoDOFAscentODE @@ -90,9 +89,6 @@ from aviary.mission.flops_based.phases.build_landing import Landing as HeightEnergyLandingPhaseBuilder # note that this is only for simplified right now from aviary.mission.flops_based.phases.build_takeoff import Takeoff as HeightEnergyTakeoffPhaseBuilder -from aviary.mission.flops_based.phases.climb_phase import Climb as HeightEnergyClimbPhaseBuilder -from aviary.mission.flops_based.phases.cruise_phase import Cruise as HeightEnergyCruisePhaseBuilder -from aviary.mission.flops_based.phases.descent_phase import Descent as HeightEnergyDescentPhaseBuilder from aviary.mission.flops_based.phases.detailed_landing_phases import LandingApproachToMicP3 as DetailedLandingApproachToMicP3PhaseBuilder from aviary.mission.flops_based.phases.detailed_landing_phases import LandingMicP3ToObstacle as DetailedLandingMicP3ToObstaclePhaseBuilder from aviary.mission.flops_based.phases.detailed_landing_phases import LandingObstacleToFlare as DetailedLandingObstacleToFlarePhaseBuilder diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index 44089da8b..7fd0f93d3 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -6,7 +6,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.interface.default_phase_info.flops import phase_info as ph_in +from aviary.interface.default_phase_info.simple import phase_info as ph_in from aviary.variable_info.variables import Aircraft from openmdao.utils.testing_utils import use_tempdirs diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index d1691db82..3facf1c45 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -8,8 +8,6 @@ from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.flops import phase_info as ph_in_flops -from aviary.interface.default_phase_info.flops import phase_info_parameterization as phase_info_parameterization_flops from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp from aviary.interface.default_phase_info.gasp import phase_info_parameterization as phase_info_parameterization_gasp from aviary.interface.methods_for_level2 import AviaryProblem @@ -17,7 +15,7 @@ from aviary.mission.flops_based.phases.phase_builder_base import \ PhaseBuilderBase as PhaseBuilder, phase_info_to_builder # must keep this import to register the phase -from aviary.mission.flops_based.phases.climb_phase import Climb +from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase from aviary.variable_info.variables import Aircraft, Mission @@ -80,11 +78,11 @@ def _test_phase_info_dict(self, phase_info_dict, name): raise RuntimeError( f'value mismatch ({key}): {lhs_value} != {rhs_value}') - def test_default_phase_flops(self): - """Tests the roundtrip conversion for default_phase_info.flops""" - from aviary.interface.default_phase_info.flops import phase_info + def test_default_phase_simple(self): + """Tests the roundtrip conversion for default_phase_info.simple""" + from aviary.interface.default_phase_info.simple import phase_info local_phase_info = deepcopy(phase_info) - self._test_phase_info_dict(local_phase_info, 'climb') + self._test_phase_info_dict(local_phase_info, 'cruise') class TestParameterizePhaseInfo(unittest.TestCase): @@ -126,47 +124,6 @@ def test_phase_info_parameterization_gasp(self): assert_near_equal(prob.get_val("traj.cruise.rhs.mach")[0], 0.6) - def test_phase_info_parameterization_flops(self): - phase_info = deepcopy(ph_in_flops) - - prob = AviaryProblem(phase_info, mission_method="FLOPS", mass_method="FLOPS") - - csv_path = pkg_resources.resource_filename( - "aviary", "models/test_aircraft/aircraft_for_bench_FwFm.csv") - - prob.load_inputs(csv_path) - prob.check_inputs() - - # We can set some crazy vals, since we aren't going to optimize. - prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000, 'km') - prob.aviary_inputs.set_val(Mission.Design.CRUISE_ALTITUDE, 31000, units='ft') - prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 195000, 'lbm') - prob.aviary_inputs.set_val(Mission.Summary.CRUISE_MACH, 0.6, 'unitless') - - prob.add_pre_mission_systems() - prob.add_phases(phase_info_parameterization=phase_info_parameterization_flops) - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - prob.set_initial_guesses() - - prob.run_model() - - assert_near_equal(prob.get_val("traj.descent.timeseries.input_values:states:range", units='km')[-1], - 5000.0 * 3378.7 / 3500) - assert_near_equal(prob.get_val("traj.cruise.timeseries.input_values:states:altitude", units='ft')[0], - 31000.0) - assert_near_equal(prob.get_val("traj.climb.timeseries.input_values:states:mass", units='lbm')[-1], - 195000.0 * 165000 / 175400) - - # Mach enters as a constraint, so it won't impact openmdao outputs until successful optimization. - # So, to verify we are setting it, reach into internal constraint dicts. - # Order may change if more path constraints are added. - assert_near_equal(prob.model.traj.phases.cruise._path_constraints[1]['equals'], - 0.6) - # To run the tests if __name__ == '__main__': diff --git a/aviary/mission/flops_based/ode/mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py deleted file mode 100644 index 946a85468..000000000 --- a/aviary/mission/flops_based/ode/mission_EOM.py +++ /dev/null @@ -1,48 +0,0 @@ -import openmdao.api as om - -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate -from aviary.mission.flops_based.ode.range_rate import RangeRate -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.variable_info.variables import Dynamic - - -class MissionEOM(om.Group): - def initialize(self): - self.options.declare('num_nodes', types=int, - desc='Number of nodes to be evaluated in the RHS') - - def setup(self): - nn = self.options['num_nodes'] - - self.add_subsystem(name='specific_power', - subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG], - promotes_outputs=[Dynamic.Mission.SPECIFIC_ENERGY_RATE]) - self.add_subsystem(name=Dynamic.Mission.ALTITUDE_RATE, - subsys=AltitudeRate(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.VELOCITY], - promotes_outputs=[Dynamic.Mission.ALTITUDE_RATE]) - self.add_subsystem(name='groundspeed', - subsys=RangeRate(num_nodes=nn), - promotes_inputs=[ - Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], - promotes_outputs=[Dynamic.Mission.RANGE_RATE]) - self.add_subsystem(name='excess_specific_power', - subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=[(Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DRAG], - promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)]) - self.add_subsystem( - name=Dynamic.Mission.ALTITUDE_RATE_MAX, - subsys=AltitudeRate( - num_nodes=nn), - promotes_inputs=[ - (Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), - Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.VELOCITY], - promotes_outputs=[ - (Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.ALTITUDE_RATE_MAX)]) diff --git a/aviary/mission/flops_based/ode/mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py deleted file mode 100644 index 0ce3b3541..000000000 --- a/aviary/mission/flops_based/ode/mission_ODE.py +++ /dev/null @@ -1,154 +0,0 @@ -import numpy as np -import openmdao.api as om -from dymos.models.atmosphere import USatm1976Comp - -from aviary.mission.flops_based.ode.mission_EOM import MissionEOM -from aviary.subsystems.aerodynamics.flops_based.mach_number import MachNumber - -from aviary.mission.flops_based.ode.mission_EOM import MissionEOM -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import promote_aircraft_and_mission_vars -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Dynamic, Mission -from aviary.variable_info.variables_in import VariablesIn - - -class ExternalSubsystemGroup(om.Group): - def configure(self): - promote_aircraft_and_mission_vars(self) - - -class MissionODE(om.Group): - def initialize(self): - self.options.declare( - 'num_nodes', types=int, - desc='Number of nodes to be evaluated in the RHS') - self.options.declare( - 'subsystem_options', types=dict, default={}, - desc='dictionary of parameters to be passed to the subsystem builders') - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( - 'core_subsystems', - desc='list of core subsystem builder instances to be added to the ODE' - ) - self.options.declare( - 'external_subsystems', default=[], - desc='list of external subsystem builder instances to be added to the ODE') - self.options.declare( - 'meta_data', default=_MetaData, - desc='metadata associated with the variables to be passed into the ODE') - self.options.declare( - 'use_actual_takeoff_mass', default=False, - desc='flag to use actual takeoff mass in the climb phase, otherwise assume 100 kg fuel burn') - - def setup(self): - options = self.options - nn = options['num_nodes'] - aviary_options = options['aviary_options'] - core_subsystems = options['core_subsystems'] - subsystem_options = options['subsystem_options'] - engine_count = len(aviary_options.get_val('engine_models')) - - self.add_subsystem( - 'input_port', - VariablesIn(aviary_options=aviary_options, - meta_data=self.options['meta_data'], - context='mission'), - promotes_inputs=['*'], - promotes_outputs=['*']) - self.add_subsystem( - name='atmosphere', - subsys=USatm1976Comp(num_nodes=nn), - promotes_inputs=[('h', Dynamic.Mission.ALTITUDE)], - promotes_outputs=[ - ('sos', Dynamic.Mission.SPEED_OF_SOUND), ('rho', Dynamic.Mission.DENSITY), - ('temp', Dynamic.Mission.TEMPERATURE), ('pres', Dynamic.Mission.STATIC_PRESSURE)]) - self.add_subsystem( - name=Dynamic.Mission.MACH, - subsys=MachNumber(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Mission.SPEED_OF_SOUND], - promotes_outputs=[Dynamic.Mission.MACH]) - - base_options = {'num_nodes': nn, 'aviary_inputs': aviary_options} - - for subsystem in core_subsystems: - # check if subsystem_options has entry for a subsystem of this name - if subsystem.name in subsystem_options: - kwargs = subsystem_options[subsystem.name] - else: - kwargs = {} - - kwargs.update(base_options) - system = subsystem.build_mission(**kwargs) - - if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) - - # Create a lightly modified version of an OM group to add external subsystems - # to the ODE with a special configure() method that promotes - # all aircraft:* and mission:* variables to the ODE. - external_subsystem_group = ExternalSubsystemGroup() - add_subsystem_group = False - - for subsystem in self.options['external_subsystems']: - subsystem_mission = subsystem.build_mission( - num_nodes=nn, aviary_inputs=aviary_options) - if subsystem_mission is not None: - add_subsystem_group = True - external_subsystem_group.add_subsystem(subsystem.name, subsystem_mission) - - # Only add the external subsystem group if it has at least one subsystem. - # Without this logic there'd be an empty OM group added to the ODE. - if add_subsystem_group: - self.add_subsystem( - name='external_subsystems', - subsys=external_subsystem_group, - promotes_inputs=['*'], - promotes_outputs=['*']) - - self.add_subsystem( - name='mission_EOM', - subsys=MissionEOM(num_nodes=nn), - promotes_inputs=[ - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL, - Dynamic.Mission.DRAG, Dynamic.Mission.VELOCITY_RATE], - promotes_outputs=[ - Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.RANGE_RATE]) - - self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s') - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.ones(nn), units='m') - self.set_input_defaults( - Dynamic.Mission.THROTTLE, val=np.ones((nn, engine_count)), - units='unitless') - - if options['use_actual_takeoff_mass']: - exec_comp_string = 'initial_mass_residual = initial_mass - mass[0]' - initial_mass_string = Mission.Takeoff.FINAL_MASS - else: - exec_comp_string = 'initial_mass_residual = initial_mass - mass[0] - 100.' - initial_mass_string = Mission.Design.GROSS_MASS - - # Experimental: Add a component to constrain the initial mass to be equal to design gross weight. - initial_mass_residual_constraint = om.ExecComp( - exec_comp_string, - initial_mass={'units': 'kg'}, - mass={'units': 'kg', 'shape': (nn,)}, - initial_mass_residual={'units': 'kg'}, - ) - - self.add_subsystem('initial_mass_residual_constraint', initial_mass_residual_constraint, - promotes_inputs=[ - ('initial_mass', initial_mass_string), - ('mass', Dynamic.Mission.MASS) - ], - promotes_outputs=['initial_mass_residual']) diff --git a/aviary/mission/flops_based/ode/test/test_mission_EOM.py b/aviary/mission/flops_based/ode/test/test_mission_EOM.py deleted file mode 100644 index c2210d1f1..000000000 --- a/aviary/mission/flops_based/ode/test/test_mission_EOM.py +++ /dev/null @@ -1,55 +0,0 @@ -import unittest - -import openmdao.api as om - -from aviary.mission.flops_based.ode.mission_EOM import MissionEOM -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ - data -from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic - - -class MissionEOMTest(unittest.TestCase): - def setUp(self): - prob = self.prob = om.Problem() - - time, _ = data.get_item('time') - - prob.model.add_subsystem( - "mission_EOM", - MissionEOM(num_nodes=len(time)), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - prob.setup(check=False, force_alloc_complex=True) - - def test_case1(self): - - do_validation_test(self.prob, - 'full_mission_test_data', - input_validation_data=data, - output_validation_data=data, - input_keys=[Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.THRUST_MAX_TOTAL, - Dynamic.Mission.VELOCITY, - Dynamic.Mission.VELOCITY_RATE], - output_keys=[Dynamic.Mission.ALTITUDE_RATE, - # TODO: why does altitude_rate_max fail for cruise? - # - actual: 760.55416759 - # - desired: 3.86361517135375 - # Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.RANGE_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS], - tol=1e-12) - - def test_IO(self): - assert_match_varnames(self.prob.model) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/__init__.py b/aviary/mission/flops_based/phases/benchmark_tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py deleted file mode 100644 index 80ba4fb2e..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py +++ /dev/null @@ -1,260 +0,0 @@ -''' -NOTES: -Includes: -Climb -Computed Aero -Large Single Aisle 1 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark currently hits iteration limit - problem only converges when velocity ref & ref0 in energyphase is changed to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_climb = 0*_units.foot # m - alt_f_climb = 35000.0*_units.foot # m - mass_i_climb = 180623*_units.lb # kg - mass_f_climb = 176765*_units.lb # kg - v_i_climb = 198.44*_units.knot # m/s - v_f_climb = 455.49*_units.knot # m/s - mach_i_climb = 0.3 - mach_f_climb = 0.79 - 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 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - - climb_options = Climb( - 'test_climb', - initial_altitude=alt_i_climb, - final_altitude=alt_f_climb, - no_descent=False, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - initial_mach=mach_i_climb, - final_mach=mach_f_climb, - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=6, order=3, compressed=False) - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - climb = climb_options.build_phase(MissionODE, transcription) - - traj.add_phase('climb', climb) - - climb.add_objective('time', loc='final', ref=1e3) - # climb.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - climb.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_climb*2), duration_ref=t_duration_climb) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - 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.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='climb_max.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_climb_large_single_aisle_1 currently broken') -class ClimbPhaseTestCase(unittest.TestCase): - def bench_test_climb_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') - - expected_times_s = [ - [120.], [194.07139282], [296.27479672], [328.62182461], - [328.62182461], [402.69321743], [504.89662133], [537.24364922], - [537.24364922], [611.31504204], [713.51844594], [745.86547383], - [745.86547383], [819.93686665], [922.14027055], [954.48729844], - [954.48729844], [1028.55869126], [1130.76209516], [1163.10912305], - [1163.10912305], [1237.18051587], [1339.38391977], [1371.73094766]] - expected_altitudes_m = [ - [0.], [682.4957554], [2476.9915886], [3148.23528025], - [3148.23528025], [4477.82410739], [5953.00480303], [6351.40548265], - [6351.40548265], [7144.57711953], [8022.01978103], [8258.96785373], - [8258.96785373], [8740.86702454], [9286.23944667], [9434.70712276], - [9434.70712276], [9740.61479402], [10091.17192047], [10187.1054111], - [10187.1054111], [10383.06677812], [10606.85289388], [10668.]] - expected_masses_kg = [ - [81929.21464651], [81734.3159625], [81482.28032417], [81409.67409534], - [81409.67409534], [81261.52268984], [81089.79910736], [81041.35712905], - [81041.35712905], [80939.57475401], [80815.51316484], [80779.24867668], - [80779.24867668], [80700.64682801], [80600.66210256], [80570.67210015], - [80570.67210015], [80504.18318007], [80416.95604372], [80390.28585848], - [80390.28585848], [80330.69704984], [80251.40682218], [80226.91650584]] - expected_ranges_m = [ - [0.], [11134.82482615], [33305.36225275], [40552.08037408], - [40552.08037408], [57694.75967874], [81567.92031544], [89129.68416299], - [89129.68416299], [106463.26453256], [130389.14274257], [137962.93786], - [137962.93786], [155308.03326502], [179243.7729914], [186819.85564691], - [186819.85564691], [204168.96379317], [228108.3526042], [235685.29047396], - [235685.29047396], [253035.99320713], [276976.90557005], [284554.20584747]] - expected_velocities_ms = [ - [102.08605905], [190.58935413], [228.38194188], [230.69562115], - [230.69562115], [233.30227629], [234.24467254], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132]] - expected_thrusts_N = [ - [218457.50162414], [171332.33326933], [141120.77188326], [131766.72736631], - [131766.72736631], [112828.24508393], [94178.64187388], [89529.25529378], - [89529.25529378], [80383.22196309], [71047.86501907], [68765.74648505], - [68765.74648505], [64112.90745184], [59068.27795964], [57877.0412593], - [57877.0412593], [55418.69760271], [52595.0053262], [51821.03735429], - [51821.03735429], [50238.39534494], [48428.26539664], [47933.1465328]] - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py deleted file mode 100644 index b924184b9..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py +++ /dev/null @@ -1,366 +0,0 @@ -''' -NOTES: -Includes: -Climb -Computed Aero -Large Single Aisle 2 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs -from packaging import version -from aviary.variable_info.variables_in import VariablesIn - -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 40 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_climb = 35 * _units.foot # m - alt_f_climb = 35000.0 * _units.foot # m - mass_i_climb = 169172 * _units.lb # kg - mass_f_climb = 164160 * _units.lb # kg - v_i_climb = 198.44 * _units.knot # m/s - v_f_climb = 452.61 * _units.knot # m/s - mach_i_climb = 0.3 - mach_f_climb = 0.775 - range_i_climb = 0 * _units.nautical_mile # m - range_f_climb = 124 * _units.nautical_mile # m - t_i_climb = 0 - t_f_climb = 20.14 * _units.minute # sec - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - transcription = dm.Radau(num_segments=6, order=3, compressed=False) - climb_options = Climb( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (True, 'unitless'), - 'fix_range': (False, 'unitless'), - 'input_initial': (False, 'unitless'), - }), - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - core_subsystems=[aero, prop], - transcription=transcription, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - climb = climb_options.build_phase(aviary_options=aviary_inputs) - - traj.add_phase('climb', climb) - - climb.timeseries_options['use_prefix'] = True - - climb.add_objective('time', loc='final', ref=t_f_climb) - - climb.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(t_f_climb * 0.5, t_f_climb * 2), duration_ref=t_f_climb) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs, phases=['climb']) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - prob.set_val('traj.climb.t_initial', t_i_climb, units='s') - prob.set_val('traj.climb.t_duration', t_f_climb, units='s') - - prob.set_val('traj.climb.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='climb_large_single_aisle_2.db') - prob.record("final") - prob.cleanup() - - return prob - - -@use_tempdirs -class ClimbPhaseTestCase(unittest.TestCase): - def bench_test_climb_large_single_aisle_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') - - expected_times_s = [[0.], - [47.24020828], - [112.42205385], - [133.05188512], - [133.05188512], - [180.2920934], - [245.47393897], - [266.10377023], - [266.10377023], - [313.34397852], - [378.52582409], - [399.15565535], - [399.15565535], - [446.39586363], - [511.5777092], - [532.20754047], - [532.20754047], - [579.44774875], - [644.62959432], - [665.25942558], - [665.25942558], - [712.49963387], - [777.68147944], - [798.3113107]] - expected_altitudes_m = [[1.06680000e+01], - [1.64717443e+02], - [1.21077165e+03], - [1.65467452e+03], - [1.65467452e+03], - [2.63158548e+03], - [3.89195114e+03], - [4.26784031e+03], - [4.26784031e+03], - [5.08501440e+03], - [6.12319963e+03], - [6.43302565e+03], - [6.43302565e+03], - [7.11281142e+03], - [7.98114971e+03], - [8.23811059e+03], - [8.23811059e+03], - [8.78587957e+03], - [9.45185516e+03], - [9.64164118e+03], - [9.64164118e+03], - [1.00442465e+04], - [1.05301137e+04], - [1.06680000e+04]] - expected_masses_kg = [[76735.12841764], - [76606.6291851], - [76423.55875817], - [76369.21098493], - [76369.21098493], - [76249.27821197], - [76096.52180626], - [76051.03001076], - [76051.03001076], - [75951.61028918], - [75824.47689696], - [75786.47518169], - [75786.47518169], - [75703.26334226], - [75596.63038983], - [75564.65308165], - [75564.65308165], - [75493.66861479], - [75400.85356264], - [75372.67886333], - [75372.67886333], - [75310.24572772], - [75228.35359487], - [75203.34794937]] - expected_ranges_m = [[0.], - [6656.35106052], - [19411.34037117], - [23606.44276229], - [23606.44276229], - [33597.9222712], - [47757.51502804], - [52308.8364503], - [52308.8364503], - [62843.02681099], - [77579.88662088], - [82280.86896803], - [82280.86896803], - [93082.94529627], - [108032.30577631], - [112765.20449737], - [112765.20449737], - [123607.6358803], - [138572.23956024], - [143309.37828794], - [143309.37828794], - [154158.17439593], - [169129.72020176], - [173868.65393385]] - expected_velocities_ms = [[102.08635556], - [173.4078533], - [206.56979636], - [209.71234319], - [209.71234319], - [215.12096513], - [220.69657248], - [222.14669648], - [222.14669648], - [225.06833215], - [228.02045426], - [228.64470582], - [228.64470582], - [229.49739505], - [229.80567178], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554]] - expected_thrusts_N = [[183100.97258682], - [163996.9938714], - [144753.36497874], - [140427.87965941], - [140427.87965941], - [131136.19372391], - [119398.47487166], - [115939.50935006], - [115939.50935006], - [108449.59352749], - [99269.67371293], - [96533.89180294], - [96533.89180294], - [90902.4892038], - [84031.52375462], - [81889.41102505], - [81889.41102505], - [77138.3352612], - [71330.53467419], - [69720.96587699], - [69720.96587699], - [66405.48655242], - [62587.8225939], - [61541.80174696]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - test = ClimbPhaseTestCase() - test.bench_test_climb_large_single_aisle_2() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py deleted file mode 100644 index b5b42004c..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py +++ /dev/null @@ -1,316 +0,0 @@ -############################################################### -# NOTES: -# Includes: -# Cruise -# Computed Aero -# Large Single Aisle 1 data -############################################################### -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 30 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-5 - driver.opt_settings["iSumm"] = 6 - driver.opt_settings["Verify level"] = 3 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_min_cruise = 30000*_units.foot # m - alt_max_cruise = 36000*_units.foot # m - alt_i_cruise = alt_min_cruise - alt_f_cruise = 36000*_units.foot # m - mass_i_cruise = 176765*_units.lb # kg - mass_f_cruise = 143521*_units.lb # kg - velocity_i_cruise = 465.55*_units.knot # m/s - velocity_f_cruise = 465.55*_units.knot # m/s - mach_i_cruise = 0.79 - mach_f_cruise = 0.79 - mach_min_cruise = 0.78999 - mach_max_cruise = 0.79001 - 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 - - prob.set_solver_print(level=0) - - transcription = dm.Radau(num_segments=8, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - # engine_models = aviary_inputs['engine_models'] - - cruise_options = Cruise( - 'test_cruise', - min_altitude=alt_min_cruise, # m - max_altitude=alt_max_cruise, # m - # note, Mach = 0.0 causes an error in aero, perhaps in other code - min_mach=mach_min_cruise, - max_mach=mach_max_cruise, - required_available_climb_rate=300*_units.foot/_units.minute, # ft/min to m/s - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - # engine_models=engine_models, - no_descent=True, - velocity_f_cruise=velocity_f_cruise, - mass_f_cruise=mass_f_cruise, - range_f_cruise=range_f_cruise, - - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(MissionODE, transcription) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-mass_f_cruise) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - # IVC = prob.model.add_subsystem('IVC', om.IndepVarComp(), promotes_outputs=['*']) - # IVC.add_output('alt_i', val=32000, units='ft') - prob.model.add_constraint( - 'traj.cruise.states:altitude', - indices=[0], equals=alt_min_cruise, units='m', ref=alt_max_cruise) - - # Alternative implmentation of above - # holds the first node in altitude constant - # cruise.set_state_options(Dynamic.Mission.ALTITUDE, fix_initial=True) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[ - alt_i_cruise, (alt_f_cruise + alt_i_cruise) / 2]), units='m') - prob.set_val( - 'traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[ - velocity_i_cruise, velocity_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_climb_max.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@unittest.skip('benchmark cruise climb currently broken') -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_climb_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') - - expected_times_s = [ - [1572.0], [2654.1067424751645], [4147.193185981006], - [4619.749940380141], [4619.749940380141], [5701.856682855307], - [7194.943126361148], [7667.499880760283], [7667.499880760283], - [8749.606623235448], [10242.693066741289], [10715.249821140425], - [10715.249821140425], [11797.356563615589], [13290.44300712143], - [13762.999761520567], [13762.999761520567], [14845.106503995732], - [16338.192947501573], [16810.749701900706], [16810.749701900706], - [17892.856444375873], [19385.942887881713], [19858.49964228085], - [19858.49964228085], [20940.606384756014], [22433.692828261857], - [22906.249582660992], [22906.249582660992], [23988.356325136156], - [25481.442768642], [25953.999523041133]] - expected_altitudes_m = [ - [9143.999999999998], [9708.208298692567], [10127.822388940609], - [10214.217379879337], [10214.217379879337], [10369.633608560018], - [10522.493213427248], [10561.102831034279], [10561.102831034279], - [10628.89921313077], [10700.84689461149], [10720.94842484514], - [10720.94842484514], [10759.7268947497], [10811.373374694173], - [10828.933975559758], [10828.933975559758], [10866.85055516194], - [10912.976573928156], [10924.787065056735], [10924.787065056735], - [10948.28098891448], [10967.163582971652], [10969.578328436102], - [10969.578328436102], [10971.188528219269], [10971.305320817934], - [10972.40306787028], [10972.40306787028], [10972.800000000001], - [10972.682828875833], [10972.8]] - expected_masses_kg = [ - [80179.25528304999], [79388.27899969438], [78357.5492916318], - [78038.12469387538], [78038.12469387538], [77318.48636094612], - [76344.12665022336], [76039.40895912607], [76039.40895912607], - [75347.90752400359], [74405.46275374181], [74109.60273338258], - [74109.60273338258], [73436.39272100825], [72516.3728326044], - [72227.22710472894], [72227.22710472894], [71569.02331279762], - [70669.56072490575], [70386.99122373879], [70386.99122373879], - [69743.47490624938], [68863.48019743375], [68586.78382987661], - [68586.78382987661], [67956.17424058718], [67092.43136900471], - [66820.49389265837], [66820.49389265837], [66200.47169407656], - [65350.50275054499], [65082.74154168183]] - expected_ranges_m = [ - [296875.60000000003], [554932.6549301515], [908399.8849826958], - [1019938.0213070473], [1019938.0213070473], [1274830.9442516388], - [1625714.5770829467], [1736624.0715069345], [1736624.0715069345], - [1990386.259724133], [2340154.5629672543], [2450786.080862452], - [2450786.080862452], [2704005.1890667905], [3053155.1477462808], - [3163604.8984363866], [3163604.8984363866], [3416419.8294669725], - [3765031.23567717], [3875315.9608939146], [3875315.9608939146], - [4127790.908533788], [4476045.826943081], [4586252.017090351], - [4586252.017090351], [4838601.188787049], [5186784.687764149], - [5296985.604312349], [5296985.604312349], [5549329.03066934], - [5897505.925045533], [6007702.8]] - expected_velocities_ms = [ - [239.49901683172416], [237.57721365239863], [236.1272332817375], - [235.83480578606836], [235.83480578606836], [235.29228140558052], - [234.76087668521515], [234.63268475430843], [234.63268475430843], - [234.3910317141664], [234.14254607637204], [234.07650600638797], - [234.07650600638797], [233.93612811601653], [233.75522209810927], - [233.69840302886462], [233.69840302886462], [233.56754384846963], - [233.4030426703855], [233.35949436934354], [233.35949436934354], - [233.28100688012185], [233.21763783283092], [233.20729273195352], - [233.20729273195352], [233.19770503012535], [233.1994910278998], - [233.19937577943125], [233.19937577943125], [233.19406389286172], - [233.19249705434646], [233.197992365194]] - expected_thrusts_N = [ - [46413.113617016286], [43959.216926887144], [42322.72191477366], - [42001.69876565644], [42001.698765656445], [41407.67462380937], - [40737.526959795134], [40531.856232353945], [40531.85623235394], - [40132.12747513132], [39640.66854140172], [39484.44541552107], - [39484.44541552107], [39159.04488467944], [38737.64967064259], - [38601.13281610918], [38601.13281610918], [38291.27389642972], - [37859.254019237305], [37729.15520426054], [37729.155204260525], - [37427.990254061384], [37028.69942780689], [36907.64255965252], - [36907.64255965253], [36649.2311134786], [36319.78199219473], - [36213.12929993469], [36213.12929994349], [35988.316744926444], - [35701.59647680185], [35614.98883340026]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # Objective - - rtol = 1e-2 - - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py deleted file mode 100644 index c1b907a07..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py +++ /dev/null @@ -1,253 +0,0 @@ -''' -NOTES: -Includes: -Cruise -Computed Aero -Large Single Aisle 1 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs -from packaging import version -from aviary.variable_info.variables_in import VariablesIn - -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import (get_flops_inputs, - get_flops_outputs) -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - 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 = 176765*_units.lb # kg - mass_f_cruise = 143521*_units.lb # kg - v_i_cruise = 455.49*_units.knot # m/s - v_f_cruise = 455.49*_units.knot # m/s - mach_i_cruise = 0.79 - mach_f_cruise = 0.79 - mach_min_cruise = 0.79 - mach_max_cruise = 0.79 - 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 - - prob.set_solver_print(level=2) - - transcription = dm.Radau(num_segments=1, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_outputs = get_flops_outputs('LargeSingleAisle1FLOPS') - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - cruise_options = Cruise( - 'test_cruise', - user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (True, 'unitless'), - 'fix_final': (True, 'unitless'), - }), - core_subsystems=core_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription, - ) - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.timeseries_options['use_prefix'] = True - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs, phases=['cruise']) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - key = Aircraft.Engine.THRUST_REVERSERS_MASS - val, units = aviary_outputs.get_item(key) - prob.model.set_input_defaults(key, val, units) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_max.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@use_tempdirs -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') - - expected_times_s = [[1572.], [10227.56555775], - [22170.47940152], [25950.37079939]] - expected_altitudes_m = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg = [[80179.25528305], [ - 74612.30190345], [67357.05992796], [65154.3328912]] - expected_ranges_m = [[296875.6], [2324510.6550793], - [5122233.1849208], [6007702.8]] - expected_velocities_ms = [[234.25795132], [ - 234.25795132], [234.25795132], [234.25795132]] - expected_thrusts_N = [[41817.82877662], [ - 39634.49609004], [36930.60549609], [36149.38784885]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py deleted file mode 100644 index 5990f8164..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py +++ /dev/null @@ -1,247 +0,0 @@ -''' -NOTES: -Includes: -Cruise -Computed Aero -Large Single Aisle 2 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import (get_flops_inputs, - get_flops_outputs) -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark currently hits iteration limit - problem only converges when velocity ref & ref0 in energyphase is changed to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - 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 = 169730*_units.lb # kg - mass_f_cruise = 139810*_units.lb # kg - v_i_cruise = 452.61*_units.knot # m/s - v_f_cruise = 452.61*_units.knot # m/s - mach_i_cruise = 0.785 - mach_f_cruise = 0.785 - mach_min_cruise = 0.785 - mach_max_cruise = 0.785 - range_i_cruise = 116.6*_units.nautical_mile # m - range_f_cruise = 2558.3*_units.nautical_mile # m - t_i_cruise = 19.08*_units.minute # sec - t_f_cruise = 342.77*_units.minute # sec - t_duration_cruise = t_f_cruise - t_i_cruise # sec - - prob.set_solver_print(level=2) - - transcription = dm.Radau(num_segments=1, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - aviary_outputs = get_flops_outputs('LargeSingleAisle2FLOPS') - - cruise_options = Cruise( - 'test_cruise', - min_altitude=alt_min_cruise, # m - max_altitude=alt_max_cruise, # m - # note, Mach = 0.0 causes an error in aero, perhaps in other code - min_mach=mach_min_cruise, - max_mach=mach_max_cruise, - required_available_climb_rate=300*_units.foot/_units.minute, # ft/min to m/s - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(MissionODE, transcription) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - key = Aircraft.Engine.THRUST_REVERSERS_MASS - val, units = aviary_outputs.get_item(key) - prob.model.set_input_defaults(key, val, units) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_large_single_aisle_2.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@unittest.skip('benchmark_cruise_large_single_aisle_2 currently broken') -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_large_single_asile_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net', units='N') - - expected_times_s = [[1144.8], [8042.22760495], - [17559.26991489], [20571.38126654]] - expected_altitudes_m = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg = [[76988.2329601], [ - 72122.85057432], [65811.40723995], [63888.48266274]] - expected_ranges_m = [[215943.2], [1821494.02176252], - [4036826.45823737], [4737971.6]] - expected_velocities_ms = [[232.77530606], [ - 232.77530606], [232.77530606], [232.77530606]] - expected_thrusts_N = [[40492.90002165], [ - 38252.99661427], [35778.79636585], [35144.49009256]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - # Changes to hardcoded tabular aero data changed this benchmark. Update benchmark - # test's expected values when aircraft-specific tabluar aero is avaliable - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py deleted file mode 100644 index f331ff733..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py +++ /dev/null @@ -1,255 +0,0 @@ -''' -NOTES: -Includes: -Descent -Computed Aero -Large Single Aisle 1 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE descent profile is improved when velocity ref in EnergyPhase change to 1e3 - Implementing that velocity ref change breaks several mission benchmarks -''' -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 5e-3 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_descent = 35000*_units.foot - alt_f_descent = 0*_units.foot - v_i_descent = 455.49*_units.knot - v_f_descent = 198.44*_units.knot - mach_i_descent = 0.79 - mach_f_descent = 0.3 - mass_i_descent = 143521*_units.pound - mass_f_descent = 143035*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_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 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - - descent_options = Descent( - 'test_descent', - final_altitude=alt_f_descent, - initial_altitude=alt_i_descent, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - final_mach=mach_f_descent, - initial_mach=mach_i_descent, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=5, order=3, compressed=True) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - descent = descent_options.build_phase(MissionODE, transcription) - - # descent.add_objective(Dynamic.Mission.MASS, ref=-1e4, loc='final') - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') - - traj.add_phase('descent', descent) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - # set initial conditions - 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.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='descent_max.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_descent_large_single_aisle_1 currently broken') -class DescentPhaseTestCase(unittest.TestCase): - def bench_test_descent_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.descent.timeseries.time', units='s') - altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') - - expected_times_s = [ - [25942.8], [26067.38110599], [26239.2776049], [26293.68225907], - [26293.68225907], [26418.26336507], [26590.15986397], [26644.56451815], - [26644.56451815], [26769.14562414], [26941.04212305], [26995.44677722], - [26995.44677722], [27120.02788321], [27291.92438212], [27346.3290363], - [27346.3290363], [27470.91014229], [27642.80664119], [27697.21129537]] - expected_altitudes_m = [ - [10668.], [9630.58727675], [8607.44716937], [8325.35146852], - [8325.35146852], [7618.26503578], [6519.12597312], [6144.16296733], - [6144.16296733], [5222.63590813], [3906.74184382], [3501.58245681], - [3501.58245681], [2693.56449806], [1613.14062128], [1227.34540813], - [1227.34540813], [472.05630168], [0.], [0.]] - expected_masses_kg = [ - [65100.03053477], [65068.4860871], [65009.01063053], [64988.47429787], - [64988.47429787], [64942.20142996], [64875.19680192], [64851.91888669], - [64851.91888669], [64793.85853886], [64706.58329093], [64678.30905669], - [64678.30905669], [64614.11135757], [64531.47572247], [64507.94243863], - [64507.94243863], [64464.03072407], [64420.28475648], [64408.7201039]] - expected_ranges_m = [ - [6007702.8], [6036868.3987895], [6077125.1955833], - [6089867.31136598], [6089867.31136598], [6119045.21397484], - [6159302.44709504], [6172042.94318126], [6172042.94318126], - [6201214.75820313], [6241466.48424821], [6254207.73380962], - [6254207.73380962], [6283402.65691348], [6322851.72600445], - [6334884.03220066], [6334884.03220066], [6360443.88994895], - [6388386.24507732], [6394712.53233535]] - expected_velocities_ms = [ - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [233.47298378], [223.67831268], [216.71997882], - [216.71997882], [190.9857791], [129.0266439], [102.08605905]] - expected_thrusts_N = [ - [9516.07730964], [18867.54655988], [26134.27560127], [26569.54809341], - [26569.54809341], [26513.67959312], [27279.65638053], [27558.344662], - [27558.344662], [29558.29975054], [37141.0454636], [40960.56830135], - [40960.56830135], [46197.31464087], [36817.32495137], [29341.51748247], - [29341.51748247], [14369.16584473], [0.], [2.27381718e-11]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py deleted file mode 100644 index a66015fc7..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py +++ /dev/null @@ -1,256 +0,0 @@ -''' -NOTES: -Includes: -Descent -Computed Aero -Large Single Aisle 2 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.flops import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark only reaches 0-3 after 50 iterations with bad plots - problem easily converges with 0-1 when velocity ref & ref0 in energyphase is changed - to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 5e-3 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i = 35000*_units.foot - alt_f = 35*_units.foot - v_i = 452.61*_units.knot - v_f = 198.44*_units.knot - mach_i = 0.785 - mach_f = 0.3 - mass_i = 140515*_units.pound - mass_f = 140002*_units.pound - range_i = 2830.8*_units.nautical_mile - range_f = 2960.0*_units.nautical_mile - t_i_descent = 0.0 - t_f_descent = 2000.0 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - - descent_options = Descent( - 'test_descent', - final_altitude=alt_f, - initial_altitude=alt_i, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - final_mach=mach_f, - initial_mach=mach_i, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=5, order=3, compressed=True) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - descent = descent_options.build_phase(MissionODE, transcription) - - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') - traj.add_phase('descent', descent) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - # set initial conditions - prob.set_val('traj.descent.t_initial', t_i_descent, units='s') - prob.set_val('traj.descent.t_duration', t_f_descent, units='s') - - prob.set_val('traj.descent.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i, alt_f]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i, v_f]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i, mass_f]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i, range_f]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='descent_large_single_aisle_2.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_descent_large_single_aisle_2 currently broken') -class DescentPhaseTestCase(unittest.TestCase): - def bench_test_descent_large_single_aisle_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.descent.timeseries.time', units='s') - altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') - - expected_times_s = [ - [0.], [142.02539503], [337.99145239], [400.01403952], - [400.01403952], [542.03943455], [738.0054919], [800.02807903], - [800.02807903], [942.05347406], [1138.01953142], [1200.04211855], - [1200.04211855], [1342.06751358], [1538.03357093], [1600.05615806], - [1600.05615806], [1742.08155309], [1938.04761045], [2000.07019758]] - expected_altitudes_m = [ - [10668.], [9548.97609287], [8538.42241675], [8275.01276129], - [8275.01276129], [7601.31902636], [6519.47805911], [6141.13701298], - [6141.13701298], [5205.26802003], [3963.90368243], [3634.87695679], - [3634.87695679], [3055.62551952], [2221.91470683], [1840.14771729], - [1840.14771729], [870.95857222], [10.668], [10.668]] - expected_masses_kg = [ - [63736.53187055], [63688.55056043], [63592.93766122], [63558.62366657], - [63558.62366657], [63480.12720033], [63368.68894184], [63331.87300229], - [63331.87300229], [63243.53017169], [63103.08546544], [63051.9162013], - [63051.9162013], [62922.36463692], [62748.94842397], [62704.12656931], - [62704.12656931], [62627.76510694], [62566.74093186], [62554.55364275]] - expected_ranges_m = [ - [5242641.6], [5275682.08024547], [5321287.43849558], - [5335722.05453227], [5335722.05453227], [5368775.18998604], - [5414378.40648958], [5428810.78044196], [5428810.78044196], - [5461857.5756481], [5507456.7101919], [5521890.39254914], - [5521890.39254914], [5554951.82532665], [5599686.46586361], - [5613370.90489204], [5613370.90489204], [5642618.8601419], - [5674799.0551216], [5682083.57281856]] - expected_velocities_ms = [ - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.05265856], [223.03560479], [216.62970611], - [216.62970611], [192.53473927], [130.45545087], [102.07377559]] - expected_thrusts_N = [ - [10348.85799036], [20322.69938272], [27901.58834456], - [28262.62341568], [28262.62341568], [28062.43245824], - [28590.47833586], [28815.02361611], [28815.02361611], - [30869.45928917], [38383.90751338], [41973.2222718], - [41973.2222718], [46287.80542225], [36032.4169276], - [28755.10323868], [28755.10323868], [13691.34754408], [0.], [0.]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/climb_phase.py b/aviary/mission/flops_based/phases/climb_phase.py deleted file mode 100644 index 977240d90..000000000 --- a/aviary/mission/flops_based/phases/climb_phase.py +++ /dev/null @@ -1,102 +0,0 @@ -from aviary.mission.flops_based.phases.energy_phase import EnergyPhase, register - - -Climb = None # forward declaration for type hints - - -@register -class Climb(EnergyPhase): - ''' - Define a phase builder class for a typical FLOPS based climb phase. - - Attributes - ---------- - name : str ('climb') - object label - - aero_builder (None) - utility for building and connecting a dynamic aerodynamics analysis component - - user_options : AviaryValues () - state/path constraint values and flags - - supported options: - - num_segments : int (5) - transcription: number of segments - - order : int (3) - transcription: order of the state transcription; the order of the control - transcription is `order - 1` - - fix_initial : bool (True) - - fix_initial_time : bool (None) - - initial_ref : float (1.0, 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - initial_bounds : pair ((0.0, 100.0) 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - duration_ref : float (1.0, 's') - - duration_bounds : pair ((0.0, 100.0) 's') - - initial_altitude : float (0.0, 'ft) - starting true altitude from mean sea level - - final_altitude : float - ending true altitude from mean sea level - - initial_mach : float (0.0, 'ft) - starting Mach number - - final_mach : float - ending Mach number - - required_altitude_rate : float (None) - minimum avaliable climb rate - - no_climb : bool (False) - aircraft is not allowed to climb during phase - - no_descent : bool (False) - aircraft is not allowed to descend during phase - - fix_range : bool (False) - - input_initial : bool (False) - - initial_guesses : AviaryValues () - state/path beginning values to be set on the problem - - supported options: - - times - - range - - altitude - - velocity - - velocity_rate - - mass - - throttle - - ode_class : type (None) - advanced: the type of system defining the ODE - - transcription : "Dymos transcription object" (None) - advanced: an object providing the transcription technique of the - optimal control problem - - external_subsystems : Sequence["subsystem builder"] () - advanced - - meta_data : dict (<"builtin" meta data>) - advanced: meta data associated with variables in the Aviary data hierarchy - - default_name : str - class attribute: derived type customization point; the default value - for name - - default_ode_class : type - class attribute: derived type customization point; the default value - for ode_class used by build_phase - - default_meta_data : dict - class attribute: derived type customization point; the default value for - meta_data - - Methods - ------- - build_phase - make_default_transcription - validate_options - assign_default_options - ''' - # region : derived type customization points - __slots__ = () - - default_name = 'climb' - # endregion : derived type customization points diff --git a/aviary/mission/flops_based/phases/cruise_phase.py b/aviary/mission/flops_based/phases/cruise_phase.py deleted file mode 100644 index 2f861c585..000000000 --- a/aviary/mission/flops_based/phases/cruise_phase.py +++ /dev/null @@ -1,437 +0,0 @@ -from math import isclose - -import dymos as dm - -from aviary.mission.flops_based.phases.phase_builder_base import ( - register, PhaseBuilderBase, InitialGuessControl, InitialGuessParameter, - InitialGuessPolynomialControl, InitialGuessState, InitialGuessTime) - -from aviary.utils.aviary_values import AviaryValues - -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial - - -Cruise = None # forward declaration for type hints - - -# TODO: support/handle the following in the base class -# - phase.set_time_options() -# - currently handled in level 3 interface implementation -# - self.external_subsystems -# - self.meta_data, with cls.default_meta_data customization point -class Cruise(PhaseBuilderBase): - ''' - Define a phase builder base class for typical energy phases such as climb and - descent. - - Attributes - ---------- - name : str ('energy_phase') - object label - - subsystem_options (None) - dictionary of parameters to be passed to the subsystem builders - - user_options : AviaryValues () - state/path constraint values and flags - - supported options: - - num_segments : int (5) - transcription: number of segments - - order : int (3) - transcription: order of the state transcription; the order of the control - transcription is `order - 1` - - fix_initial : bool (True) - - fix_initial_time : bool (None) - - initial_ref : float (1.0, 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - initial_bounds : pair ((0.0, 100.0) 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - duration_ref : float (1.0, 's') - - duration_bounds : pair ((0.0, 100.0) 's') - - min_altitude : float (0.0, 'ft) - starting true altitude from mean sea level - - max_altitude : float - ending true altitude from mean sea level - - min_mach : float (0.0, 'ft) - starting Mach number - - max_mach : float - ending Mach number - - required_available_climb_rate : float (None) - minimum avaliable climb rate - - fix_final : bool (False) - - input_initial : bool (False) - - polynomial_control_order : None or int - When set to an integer value, replace controls with - polynomial controls of that specified order. - - initial_guesses : AviaryValues () - state/path beginning values to be set on the problem - - supported options: - - times - - range - - altitude - - velocity - - velocity_rate - - mass - - throttle - - ode_class : type (None) - advanced: the type of system defining the ODE - - transcription : "Dymos transcription object" (None) - advanced: an object providing the transcription technique of the - optimal control problem - - external_subsystems : Sequence["subsystem builder"] () - advanced - - meta_data : dict (<"builtin" meta data>) - advanced: meta data associated with variables in the Aviary data hierarchy - - default_name : str - class attribute: derived type customization point; the default value - for name - - default_ode_class : type - class attribute: derived type customization point; the default value - for ode_class used by build_phase - - default_meta_data : dict - class attribute: derived type customization point; the default value for - meta_data - - Methods - ------- - build_phase - make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = ('external_subsystems', 'meta_data') - - # region : derived type customization points - _meta_data_ = {} - - _initial_guesses_meta_data_ = {} - - default_name = 'cruise_phase' - - # default_ode_class = MissionODE - - default_meta_data = _MetaData - - # endregion : derived type customization points - - def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None - ): - super().__init__( - name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) - - # TODO: support external_subsystems and meta_data in the base class - if external_subsystems is None: - external_subsystems = [] - - self.external_subsystems = external_subsystems - - if meta_data is None: - meta_data = self.default_meta_data - - self.meta_data = meta_data - - def build_phase(self, aviary_options: AviaryValues = None): - ''' - Return a new cruise phase for analysis using these constraints. - - If ode_class is None, default_ode_class is used. - - If transcription is None, the return value from calling - make_default_transcription is used. - - Parameters - ---------- - aviary_options : AviaryValues () - collection of Aircraft/Mission specific options - - Returns - ------- - dymos.Phase - ''' - phase: dm.Phase = super().build_phase(aviary_options) - - user_options: AviaryValues = self.user_options - - fix_initial = user_options.get_val('fix_initial') - min_mach = user_options.get_val('min_mach') - max_mach = user_options.get_val('max_mach') - min_altitude = user_options.get_val('min_altitude', units='m') - max_altitude = user_options.get_val('max_altitude', units='m') - fix_final = user_options.get_val('fix_final') - input_initial = user_options.get_val('input_initial') - num_engines = len(aviary_options.get_val('engine_models')) - input_initial = user_options.get_val('input_initial') - mass_f_cruise = user_options.get_val('mass_f_cruise', units='kg') - range_f_cruise = user_options.get_val('range_f_cruise', units='m') - polynomial_control_order = user_options.get_item('polynomial_control_order')[0] - - ############## - # Add States # - ############## - - input_initial_alt = get_initial(input_initial, Dynamic.Mission.ALTITUDE) - fix_initial_alt = get_initial(fix_initial, Dynamic.Mission.ALTITUDE) - phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=fix_initial_alt, fix_final=False, - lower=0.0, ref=max_altitude, defect_ref=max_altitude, units='m', - rate_source=Dynamic.Mission.ALTITUDE_RATE, targets=Dynamic.Mission.ALTITUDE, - input_initial=input_initial_alt - ) - - input_initial_vel = get_initial(input_initial, Dynamic.Mission.VELOCITY) - fix_initial_vel = get_initial(fix_initial, Dynamic.Mission.VELOCITY) - phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=fix_initial_vel, fix_final=False, - lower=0.0, ref=1e2, defect_ref=1e2, units='m/s', - rate_source=Dynamic.Mission.VELOCITY_RATE, targets=Dynamic.Mission.VELOCITY, - input_initial=input_initial_vel - ) - - input_initial_mass = get_initial(input_initial, Dynamic.Mission.MASS) - fix_initial_mass = get_initial(fix_initial, Dynamic.Mission.MASS, True) - phase.add_state( - Dynamic.Mission.MASS, fix_initial=fix_initial_mass, fix_final=False, - lower=0.0, ref=mass_f_cruise, defect_ref=mass_f_cruise, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, - input_initial=input_initial_mass - ) - - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) - phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=fix_final, - lower=0.0, ref=range_f_cruise, defect_ref=range_f_cruise, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range - ) - - phase = add_subsystem_variables_to_phase( - phase, self.name, self.external_subsystems) - - ################ - # Add Controls # - ################ - if polynomial_control_order is not None: - phase.add_polynomial_control( - Dynamic.Mission.VELOCITY_RATE, - targets=Dynamic.Mission.VELOCITY_RATE, units='m/s**2', - opt=True, lower=-2.12, upper=2.12, - order=polynomial_control_order, - ) - else: - phase.add_control( - Dynamic.Mission.VELOCITY_RATE, - targets=Dynamic.Mission.VELOCITY_RATE, units='m/s**2', - opt=True, lower=-2.12, upper=2.12, - ) - - if num_engines > 0: - if polynomial_control_order is not None: - phase.add_polynomial_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - order=polynomial_control_order, - ) - else: - phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - ) - - ################## - # Add Timeseries # - ################## - phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units='unitless' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_MAX_TOTAL, - output_name=Dynamic.Mission.THRUST_MAX_TOTAL, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE, units='m/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, units='m/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - output_name=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' - ) - - phase.add_timeseries_output( - Dynamic.Mission.ALTITUDE_RATE, - output_name=Dynamic.Mission.ALTITUDE_RATE, units='ft/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.ALTITUDE_RATE_MAX, - output_name=Dynamic.Mission.ALTITUDE_RATE_MAX, units='ft/min' - ) - - ################### - # Add Constraints # - ################### - required_available_climb_rate = user_options.get_val( - 'required_available_climb_rate', 'm/s') - - if required_available_climb_rate is not None: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE_RATE_MAX, - ref=required_available_climb_rate, - constraint_name='altitude_rate_minimum', - lower=required_available_climb_rate, units='m/s' - ) - - if isclose(min_mach, max_mach): - phase.add_path_constraint( - Dynamic.Mission.MACH, - equals=min_mach, units='unitless', - # ref=1.e4, - ) - - else: - phase.add_path_constraint( - Dynamic.Mission.MACH, - lower=min_mach, upper=max_mach, units='unitless', - # ref=1.e4, - ) - - # avoid scaling constraints by zero - ref = max_altitude - if ref == 0: - ref = None - - if isclose(min_altitude, max_altitude): - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE, - equals=min_altitude, units='m', ref=ref, - ) - - else: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE, - lower=min_altitude, upper=max_altitude, - units='m', ref=ref, - ) - - return phase - - def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - # TODO: support external_subsystems and meta_data in the base class - return { - 'external_subsystems': self.external_subsystems, - 'meta_data': self.meta_data} - - -Cruise._add_meta_data( - 'num_segments', val=1, desc='transcription: number of segments') - -Cruise._add_meta_data( - 'order', val=3, - desc='transcription: order of the state transcription; the order of the control' - ' transcription is `order - 1`') - -Cruise._add_meta_data('fix_initial', val=True) - -Cruise._add_meta_data('fix_initial_time', val=None) - -Cruise._add_meta_data('initial_ref', val=1., units='s') - -Cruise._add_meta_data('initial_bounds', val=(0., 100.), units='s') - -Cruise._add_meta_data('duration_ref', val=1., units='s') - -Cruise._add_meta_data('duration_bounds', val=(0., 100.), units='s') - -Cruise._add_meta_data( - 'min_altitude', val=0., units='m', - desc='starting true altitude from mean sea level') - -Cruise._add_meta_data( - 'max_altitude', val=None, units='m', - desc='ending true altitude from mean sea level') - -Cruise._add_meta_data('min_mach', val=0., desc='starting Mach number') - -Cruise._add_meta_data('max_mach', val=None, desc='ending Mach number') - -Cruise._add_meta_data('mass_i_cruise', val=1.e4, units='kg') - -Cruise._add_meta_data('mass_f_cruise', val=1.e4, units='kg') - -Cruise._add_meta_data('range_f_cruise', val=1.e6, units='m') - -Cruise._add_meta_data( - 'required_available_climb_rate', val=None, units='m/s', - desc='minimum avaliable climb rate') - -Cruise._add_meta_data('fix_final', val=True) - -Cruise._add_meta_data('input_initial', val=False) - -Cruise._add_meta_data('polynomial_control_order', val=None) - -Cruise._add_initial_guess_meta_data( - InitialGuessTime(), - desc='initial guess for initial time and duration specified as a tuple') - -Cruise._add_initial_guess_meta_data( - InitialGuessState('range'), - desc='initial guess for horizontal distance traveled') - -Cruise._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for vertical distances') - -Cruise._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for speed') - -Cruise._add_initial_guess_meta_data( - InitialGuessControl('velocity_rate'), - desc='initial guess for acceleration') - -Cruise._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') - -Cruise._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') diff --git a/aviary/mission/flops_based/phases/descent_phase.py b/aviary/mission/flops_based/phases/descent_phase.py deleted file mode 100644 index 78ad93a90..000000000 --- a/aviary/mission/flops_based/phases/descent_phase.py +++ /dev/null @@ -1,103 +0,0 @@ -from aviary.mission.flops_based.phases.energy_phase import EnergyPhase, register - - -Descent = None # forward declaration for type hints - - -@register -class Descent(EnergyPhase): - ''' - Define a phase builder class for a typical FLOPS based descent phase. - - Attributes - ---------- - name : str ('descent') - object label - - aero_builder (None) - utility for building and connecting a dynamic aerodynamics analysis component - - user_options : AviaryValues () - state/path constraint values and flags - - supported options: - - num_segments : int (5) - transcription: number of segments - - order : int (3) - transcription: order of the state transcription; the order of the control - transcription is `order - 1` - - fix_initial : bool (True) - - fix_initial_time : bool (None) - - initial_ref : float (1.0, 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - initial_bounds : pair ((0.0, 100.0) 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - duration_ref : float (1.0, 's') - - duration_bounds : pair ((0.0, 100.0) 's') - - initial_altitude : float (0.0, 'ft) - starting true altitude from mean sea level - - final_altitude : float - ending true altitude from mean sea level - - initial_mach : float (0.0, 'ft) - starting Mach number - - final_mach : float - ending Mach number - - required_altitude_rate : float (None) - minimum avaliable descent rate - - no_descent : bool (False) - aircraft is not allowed to descent during phase - - no_descent : bool (False) - aircraft is not allowed to descend during phase - - fix_range : bool (False) - - input_initial : bool (False) - - initial_guesses : AviaryValues () - state/path beginning values to be set on the problem - - supported options: - - times - - range - - altitude - - velocity - - velocity_rate - - mass - - throttle - - ode_class : type (None) - advanced: the type of system defining the ODE - - transcription : "Dymos transcription object" (None) - advanced: an object providing the transcription technique of the - optimal control problem - - external_subsystems : Sequence["subsystem builder"] () - advanced - - meta_data : dict (<"builtin" meta data>) - advanced: meta data associated with variables in the Aviary data hierarchy - - default_name : str - class attribute: derived type customization point; the default value - for name - - default_ode_class : type - class attribute: derived type customization point; the default value - for ode_class used by build_phase - - default_meta_data : dict - class attribute: derived type customization point; the default value for - meta_data - - Methods - ------- - build_phase - make_default_transcription - validate_options - assign_default_options - ''' - # region : derived type customization points - __slots__ = () - - default_name = 'descent' - - # endregion : derived type customization points diff --git a/aviary/mission/flops_based/phases/energy_phase.py b/aviary/mission/flops_based/phases/energy_phase.py deleted file mode 100644 index 94ac79e4a..000000000 --- a/aviary/mission/flops_based/phases/energy_phase.py +++ /dev/null @@ -1,541 +0,0 @@ -from math import isclose - -import dymos as dm - -from aviary.mission.flops_based.phases.phase_builder_base import ( - register, PhaseBuilderBase, InitialGuessControl, InitialGuessParameter, - InitialGuessPolynomialControl, InitialGuessState, InitialGuessTime) - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial -from aviary.variable_info.variables import Dynamic - - -# TODO: support/handle the following in the base class -# - phase.set_time_options() -# - currently handled in level 3 interface implementation -# - self.external_subsystems -# - self.meta_data, with cls.default_meta_data customization point -class EnergyPhase(PhaseBuilderBase): - ''' - Define a phase builder base class for typical energy phases such as climb and - descent. - - Attributes - ---------- - name : str ('energy_phase') - object label - - subsystem_options (None) - dictionary of parameters to be passed to the subsystem builders - - user_options : AviaryValues () - state/path constraint values and flags - - supported options: - - num_segments : int (5) - transcription: number of segments - - order : int (3) - transcription: order of the state transcription; the order of the control - transcription is `order - 1` - - fix_initial : bool (True) - - fix_initial_time : bool (None) - - initial_ref : float (1.0, 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - initial_bounds : pair ((0.0, 100.0) 's') - note: applied if, and only if, "fix_initial_time" is unspecified - - duration_ref : float (1.0, 's') - - duration_bounds : pair ((0.0, 100.0) 's') - - initial_altitude : float (0.0, 'ft) - starting true altitude from mean sea level - - final_altitude : float - ending true altitude from mean sea level - - initial_mach : float (0.0, 'ft) - starting Mach number - - final_mach : float - ending Mach number - - required_altitude_rate : float (None) - minimum avaliable climb rate - - no_climb : bool (False) - aircraft is not allowed to climb during phase - - no_descent : bool (False) - aircraft is not allowed to descend during phase - - fix_range : bool (False) - - input_initial : bool (False) - - polynomial_control_order : None or int - When set to an integer value, replace controls with - polynomial controls of that specified order. - - - initial_guesses : AviaryValues () - state/path beginning values to be set on the problem - - supported options: - - times - - range - - altitude - - velocity - - velocity_rate - - mass - - throttle - - ode_class : type (None) - advanced: the type of system defining the ODE - - transcription : "Dymos transcription object" (None) - advanced: an object providing the transcription technique of the - optimal control problem - - external_subsystems : Sequence["subsystem builder"] () - advanced - - meta_data : dict (<"builtin" meta data>) - advanced: meta data associated with variables in the Aviary data hierarchy - - default_name : str - class attribute: derived type customization point; the default value - for name - - default_ode_class : type - class attribute: derived type customization point; the default value - for ode_class used by build_phase - - default_meta_data : dict - class attribute: derived type customization point; the default value for - meta_data - - Methods - ------- - build_phase - make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = ('external_subsystems', 'meta_data') - - # region : derived type customization points - _meta_data_ = {} - - _initial_guesses_meta_data_ = {} - - default_name = 'energy_phase' - - # default_ode_class = MissionODE - - default_meta_data = _MetaData - # endregion : derived type customization points - - def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None - ): - super().__init__( - name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) - - # TODO: support external_subsystems and meta_data in the base class - if external_subsystems is None: - external_subsystems = [] - - self.external_subsystems = external_subsystems - - if meta_data is None: - meta_data = self.default_meta_data - - self.meta_data = meta_data - - def build_phase(self, aviary_options: AviaryValues = None): - ''' - Return a new energy phase for analysis using these constraints. - - If ode_class is None, default_ode_class is used. - - If transcription is None, the return value from calling - make_default_transcription is used. - - Parameters - ---------- - aviary_options : AviaryValues () - collection of Aircraft/Mission specific options - - Returns - ------- - dymos.Phase - ''' - phase: dm.Phase = super().build_phase(aviary_options) - - user_options: AviaryValues = self.user_options - - fix_initial = user_options.get_val('fix_initial') - initial_mach = user_options.get_val('initial_mach') - final_mach = user_options.get_val('final_mach') - initial_altitude = user_options.get_val('initial_altitude', 'm') - final_altitude = user_options.get_val('final_altitude', 'm') - no_descent = user_options.get_val('no_descent') - no_climb = user_options.get_val('no_climb') - fix_range = user_options.get_val('fix_range') - input_initial = user_options.get_val('input_initial') - polynomial_control_order = user_options.get_item('polynomial_control_order')[0] - num_engines = len(aviary_options.get_val('engine_models')) - - # NOTE currently defaulting to climb if altitudes match. Review at future date - climb = final_altitude >= initial_altitude - descent = initial_altitude > final_altitude - - max_altitude = max(initial_altitude, final_altitude) - min_altitude = min(initial_altitude, final_altitude) - max_mach = max(initial_mach, final_mach) - min_mach = min(initial_mach, final_mach) - - if climb: - lower_accel = 0.0 - else: - lower_accel = -2.12 - - if descent: - upper_accel = 0.0 - else: - upper_accel = 2.12 - - ############## - # Add States # - ############## - # TODO: critically think about how we should handle fix_initial and input_initial defaults. - # In keeping with Dymos standards, the default should be False instead of True. - - input_initial_alt = get_initial(input_initial, Dynamic.Mission.ALTITUDE) - fix_initial_alt = get_initial(fix_initial, Dynamic.Mission.ALTITUDE) - phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=fix_initial_alt, fix_final=False, - lower=0.0, ref=1e4, defect_ref=1e4, units='m', - rate_source=Dynamic.Mission.ALTITUDE_RATE, targets=Dynamic.Mission.ALTITUDE, - input_initial=input_initial_alt - ) - - input_initial_vel = get_initial(input_initial, Dynamic.Mission.VELOCITY) - fix_initial_vel = get_initial(fix_initial, Dynamic.Mission.VELOCITY) - phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=fix_initial_vel, fix_final=False, - lower=0.0, ref=1e2, defect_ref=1e2, units='m/s', - rate_source=Dynamic.Mission.VELOCITY_RATE, targets=Dynamic.Mission.VELOCITY, - input_initial=input_initial_vel - ) - - input_initial_mass = get_initial(input_initial, Dynamic.Mission.MASS) - fix_initial_mass = get_initial(fix_initial, Dynamic.Mission.MASS, True) - - # Experiment: use a constraint for mass instead of connected initial. - # This is due to some problems in mpi. - # This is needed for the cutting edge full subsystem integration. - # TODO: when a Dymos fix is in and we've verified that full case works with the fix, - # remove this argument. - if user_options.get_val('add_initial_mass_constraint'): - phase.add_constraint('rhs_all.initial_mass_residual', equals=0.0, ref=1e4) - input_initial_mass = False - - phase.add_state( - Dynamic.Mission.MASS, fix_initial=fix_initial_mass, fix_final=False, - lower=0.0, ref=1e4, defect_ref=1e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, - input_initial=input_initial_mass - ) - - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) - phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=fix_range, - lower=0.0, ref=1e6, defect_ref=1e6, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range - ) - - phase = add_subsystem_variables_to_phase( - phase, self.name, self.external_subsystems) - - ################ - # Add Controls # - ################ - if polynomial_control_order is not None: - phase.add_polynomial_control( - Dynamic.Mission.VELOCITY_RATE, - targets=Dynamic.Mission.VELOCITY_RATE, units='m/s**2', - opt=True, lower=lower_accel, upper=upper_accel, - order=polynomial_control_order, - ) - else: - phase.add_control( - Dynamic.Mission.VELOCITY_RATE, - targets=Dynamic.Mission.VELOCITY_RATE, units='m/s**2', - opt=True, lower=lower_accel, upper=upper_accel - ) - - if num_engines > 0: - if polynomial_control_order is not None: - phase.add_polynomial_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - order=polynomial_control_order, - ) - else: - phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - ) - if climb: - phase.add_path_constraint( - Dynamic.Mission.THROTTLE, - upper=1.0, - ) - - if descent: - phase.add_path_constraint( - Dynamic.Mission.THROTTLE, - lower=0.0, - ) - - # check if engine has use_hybrid_throttle - engine_models = aviary_options.get_val('engine_models') - if any([engine.use_hybrid_throttle for engine in engine_models]): - if polynomial_control_order is not None: - phase.add_polynomial_control( - Dynamic.Mission.HYBRID_THROTTLE, - targets=Dynamic.Mission.HYBRID_THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - order=polynomial_control_order, - ) - else: - phase.add_control( - Dynamic.Mission.HYBRID_THROTTLE, - targets=Dynamic.Mission.HYBRID_THROTTLE, units='unitless', - opt=True, lower=0.0, upper=1.0, scaler=1, - ) - - ################## - # Add Timeseries # - ################## - phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units='unitless' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_MAX_TOTAL, - output_name=Dynamic.Mission.THRUST_MAX_TOTAL, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE, units='m/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, units='m/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - output_name=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' - ) - - phase.add_timeseries_output( - Dynamic.Mission.ALTITUDE_RATE, - output_name=Dynamic.Mission.ALTITUDE_RATE, units='ft/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.ALTITUDE_RATE_MAX, - output_name=Dynamic.Mission.ALTITUDE_RATE_MAX, units='ft/min' - ) - - ################### - # Add Constraints # - ################### - if climb and no_descent: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE_RATE, constraint_name='no_descent', - lower=0.0 - ) - - if descent and no_climb: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE_RATE, constraint_name='no_climb', - upper=0.0 - ) - - if descent and num_engines > 0: - phase.add_boundary_constraint( - Dynamic.Mission.THROTTLE, - loc='final', - upper=1.0, - lower=0.0, - units='unitless') - - required_altitude_rate, units = user_options.get_item('required_altitude_rate') - - if required_altitude_rate is not None: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE_RATE_MAX, - lower=required_altitude_rate, units=units - ) - - phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc='final', equals=final_mach - ) - - if isclose(initial_mach, final_mach): - phase.add_path_constraint( - Dynamic.Mission.MACH, - equals=min_mach, units='unitless', - # ref=1.e4, - ) - - else: - phase.add_path_constraint( - Dynamic.Mission.MACH, - lower=min_mach, upper=max_mach, units='unitless', - # ref=1.e4, - ) - - # avoid scaling constraints by zero - ref = final_altitude - if ref == 0: - ref = None - - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='final', equals=final_altitude, ref=ref - ) - - # avoid scaling constraints by zero - ref = max_altitude - if ref == 0: - ref = None - - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE, - lower=min_altitude, upper=max_altitude, - units='m', ref=ref - ) - - return phase - - def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' - user_options = self.user_options - - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') - - seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) - - transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True, - segment_ends=seg_ends) - - return transcription - - def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - # TODO: support external_subsystems and meta_data in the base class - return { - 'external_subsystems': self.external_subsystems, - 'meta_data': self.meta_data, - 'subsystem_options': self.subsystem_options, - } - - -EnergyPhase._add_meta_data( - 'num_segments', val=5, desc='transcription: number of segments') - -EnergyPhase._add_meta_data( - 'order', val=3, - desc='transcription: order of the state transcription; the order of the control' - ' transcription is `order - 1`') - -EnergyPhase._add_meta_data('add_initial_mass_constraint', val=False) - -EnergyPhase._add_meta_data('fix_initial', val=True) - -EnergyPhase._add_meta_data('fix_initial_time', val=None) - -EnergyPhase._add_meta_data('initial_ref', val=1., units='s') - -EnergyPhase._add_meta_data('initial_bounds', val=(0., 100.), units='s') - -EnergyPhase._add_meta_data('duration_ref', val=1., units='s') - -EnergyPhase._add_meta_data('duration_bounds', val=(0., 100.), units='s') - -EnergyPhase._add_meta_data('cruise_alt', val=11.e3, units='m') - -EnergyPhase._add_meta_data( - 'initial_altitude', val=0., units='m', - desc='starting true altitude from mean sea level') - -EnergyPhase._add_meta_data( - 'final_altitude', val=None, units='m', - desc='ending true altitude from mean sea level') - -EnergyPhase._add_meta_data('initial_mach', val=0., desc='starting Mach number') - -EnergyPhase._add_meta_data('final_mach', val=None, desc='ending Mach number') - -EnergyPhase._add_meta_data( - 'required_altitude_rate', val=None, units='m/s', - desc='minimum avaliable climb rate') - -EnergyPhase._add_meta_data( - 'no_climb', val=False, desc='aircraft is not allowed to climb during phase') - -EnergyPhase._add_meta_data( - 'no_descent', val=False, desc='aircraft is not allowed to descend during phase') - -EnergyPhase._add_meta_data('fix_range', val=False) - -EnergyPhase._add_meta_data('input_initial', val=False) - -EnergyPhase._add_meta_data('polynomial_control_order', val=None) - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessTime(), - desc='initial guess for initial time and duration specified as a tuple') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('range'), - desc='initial guess for horizontal distance traveled') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for vertical distances') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for speed') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessControl('velocity_rate'), - desc='initial guess for acceleration') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') diff --git a/aviary/mission/flops_based/phases/phase_builder_base.py b/aviary/mission/flops_based/phases/phase_builder_base.py index b299689c5..0ff2b77f4 100644 --- a/aviary/mission/flops_based/phases/phase_builder_base.py +++ b/aviary/mission/flops_based/phases/phase_builder_base.py @@ -28,7 +28,7 @@ import numpy as np import openmdao.api as om -from aviary.mission.flops_based.ode.mission_ODE import MissionODE +from aviary.mission.flops_based.ode.simple_mission_ODE import MissionODE from aviary.utils.aviary_values import AviaryValues, get_keys _require_new_meta_data_class_attr_ = \ diff --git a/aviary/mission/flops_based/phases/simple_energy_phase.py b/aviary/mission/flops_based/phases/simple_energy_phase.py index 3514be333..8dd017613 100644 --- a/aviary/mission/flops_based/phases/simple_energy_phase.py +++ b/aviary/mission/flops_based/phases/simple_energy_phase.py @@ -16,6 +16,7 @@ # - currently handled in level 3 interface implementation # - self.external_subsystems # - self.meta_data, with cls.default_meta_data customization point +@register class EnergyPhase(PhaseBuilderBase): ''' A phase builder for a simple energy phase. @@ -98,7 +99,7 @@ class attribute: derived type customization point; the default value for _initial_guesses_meta_data_ = {} - default_name = 'energy_phase' + default_name = 'cruise' default_ode_class = MissionODE diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py index 090a26b9f..ee2c4c157 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py @@ -17,12 +17,8 @@ from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from packaging import version -from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.mission.flops_based.phases.descent_phase import Descent from aviary.utils.functions import set_aviary_initial_values from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal from aviary.utils.functions import get_path diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py index 44bf01c3f..5c8214267 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py @@ -13,19 +13,13 @@ import scipy.constants as _units from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs -from packaging import version -from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.mission.flops_based.phases.descent_phase import Descent from aviary.subsystems.premission import CorePreMission from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.utils.functions import get_path from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs from aviary.variable_info.functions import setup_trajectory_params from aviary.utils.preprocessors import preprocess_options diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py index 124c64e5b..a81566387 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py @@ -13,17 +13,12 @@ import scipy.constants as _units from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs -from packaging import version from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.mission.flops_based.phases.descent_phase import Descent from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.utils.functions import get_path from aviary.validation_cases.validation_tests import get_flops_inputs from aviary.variable_info.functions import setup_trajectory_params from aviary.variable_info.variables import Aircraft, Dynamic, Mission diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 69600d000..c195cff92 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -16,9 +16,6 @@ from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.mission.flops_based.phases.descent_phase import Descent from aviary.utils.functions import set_aviary_initial_values from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal from aviary.utils.functions import get_path From 46b74bf34e22cd39077ef79f87c6cbcfd2938b17 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 8 Jan 2024 20:32:41 -0600 Subject: [PATCH 016/111] Removed old FLOPS based L3 missions --- .../flops_based/phases/simple_energy_phase.py | 2 +- .../test_FLOPS_based_full_mission_N3CC.py | 709 ------------------ ...based_full_mission_large_single_aisle_1.py | 664 ---------------- ...based_full_mission_large_single_aisle_2.py | 701 ----------------- .../test_FLOPS_based_sizing_N3CC.py | 174 ++--- 5 files changed, 49 insertions(+), 2201 deletions(-) delete mode 100644 aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py delete mode 100644 aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py delete mode 100644 aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py diff --git a/aviary/mission/flops_based/phases/simple_energy_phase.py b/aviary/mission/flops_based/phases/simple_energy_phase.py index 8dd017613..6da23cbdb 100644 --- a/aviary/mission/flops_based/phases/simple_energy_phase.py +++ b/aviary/mission/flops_based/phases/simple_energy_phase.py @@ -373,7 +373,7 @@ def _extra_ode_init_kwargs(self): desc='transcription: order of the state transcription; the order of the control' ' transcription is `order - 1`') -EnergyPhase._add_meta_data('polynomial_control_order', val=None) +EnergyPhase._add_meta_data('polynomial_control_order', val=3) EnergyPhase._add_meta_data('use_polynomial_control', val=True) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py deleted file mode 100644 index ee2c4c157..000000000 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ /dev/null @@ -1,709 +0,0 @@ -''' -NOTES: -Includes: -Takeoff, Climb, Cruise, Descent, Landing -Computed Aero -N3CC data -''' -import unittest -import warnings - -import dymos as dm -import numpy as np -import openmdao.api as om -import scipy.constants as _units -from openmdao.core.driver import Driver -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from packaging import version - -from aviary.mission.flops_based.phases.build_landing import Landing -from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.variable_info.variables_in import VariablesIn -from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems -from aviary.utils.preprocessors import preprocess_crewpayload -from aviary.utils.aviary_values import AviaryValues - - -# benchmark based on N3CC (fixed cruise alt) FLOPS model - - -def run_trajectory(driver: Driver, sim=True): - prob = om.Problem(model=om.Group()) - prob.driver = driver - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('N3CC') - - aviary_inputs.set_val( - Mission.Landing.LIFT_COEFFICIENT_MAX, 2.4, units='unitless') - aviary_inputs.set_val( - Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, units='unitless') - aviary_inputs.set_val( - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=.0175, - units='unitless') - - takeoff_fuel_burned = 577 # lbm TODO: where should this get connected from? - takeoff_thrust_per_eng = 24555.5 # lbf TODO: where should this get connected from? - takeoff_L_over_D = 17.35 # TODO: should this come from aero? - - aviary_inputs.set_val( - Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm') - aviary_inputs.set_val( - Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless') - aviary_inputs.set_val( - Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf') - - alt_airport = 0 # ft - cruise_mach = .785 - - 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 - v_i_climb = 198.44*_units.knot # m/s - v_f_climb = 455.49*_units.knot # m/s - # 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 - v_i_cruise = 455.49*_units.knot # m/s - v_f_cruise = 455.49*_units.knot # m/s - mach_min_cruise = cruise_mach - mach_max_cruise = 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 - v_i_descent = 455.49*_units.knot - v_f_descent = 198.44*_units.knot - mach_i_descent = cruise_mach - mach_f_descent = 0.3 - mass_i_descent = 102000*_units.pound - mass_f_descent = 101000*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_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 - - ################## - # 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) - - takeoff_options = Takeoff( - airport_altitude=alt_airport, # ft - num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES) - ) - - climb_options = Climb( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (False, 'unitless'), - 'input_initial': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_climb, - ) - - cruise_options = Cruise( - 'test_cruise', - user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (False, 'unitless'), - 'fix_final': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_cruise, - ) - - descent_options = Descent( - 'test_descent', - user_options=AviaryValues({ - 'final_altitude': (alt_f_descent, 'm'), - 'initial_altitude': (alt_i_descent, 'm'), - 'initial_mach': (mach_i_descent, 'unitless'), - 'final_mach': (mach_f_descent, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_descent, - ) - - landing_options = Landing( - ref_wing_area=aviary_inputs.get_val(Aircraft.Wing.AREA, 'ft**2'), - Cl_max_ldg=aviary_inputs.get_val(Mission.Landing.LIFT_COEFFICIENT_MAX) - ) - - preprocess_crewpayload(aviary_inputs) - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'pre_mission', - CorePreMission(aviary_options=aviary_inputs, - subsystems=default_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) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - descent = descent_options.build_phase(aviary_options=aviary_inputs) - - 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=(1, t_duration_climb*2), duration_ref=t_duration_climb) - cruise.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - descent.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_descent*2), duration_ref=t_duration_descent) - - traj.add_phase('climb', climb) - - traj.add_phase('cruise', cruise) - - traj.add_phase('descent', descent) - - climb.timeseries_options['use_prefix'] = True - cruise.timeseries_options['use_prefix'] = True - descent.timeseries_options['use_prefix'] = True - - prob.model.add_subsystem( - 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - ################################## - # Connect in Takeoff and Landing # - ################################## - - prob.model.add_subsystem( - "takeoff_constraints", - om.ExecComp( - [ - "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", - "takeoff_vel_con=takeoff_vel-climb_start_vel", - "takeoff_alt_con=takeoff_alt-climb_start_alt" - ], - takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, - climb_start_mass={'units': 'lbm'}, - takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, - takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, - climb_start_vel={'units': 'm/s'}, - takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, - climb_start_alt={'units': 'ft'} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Takeoff.FINAL_MASS), - ("takeoff_range", Mission.Takeoff.GROUND_DISTANCE), - ("takeoff_vel", Mission.Takeoff.FINAL_VELOCITY), - ("takeoff_alt", Mission.Takeoff.FINAL_ALTITUDE), - ], - promotes_outputs=["takeoff_mass_con", "takeoff_range_con", - "takeoff_vel_con", "takeoff_alt_con"], - ) - - prob.model.connect('traj.climb.states:mass', - 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', - 'takeoff_constraints.climb_start_range', src_indices=[0]) - prob.model.connect('traj.climb.states:velocity', - 'takeoff_constraints.climb_start_vel', src_indices=[0]) - prob.model.connect('traj.climb.states:altitude', - 'takeoff_constraints.climb_start_alt', src_indices=[0]) - - prob.model.connect(Mission.Takeoff.FINAL_MASS, - 'traj.climb.initial_states:mass') - prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') - prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, - 'traj.climb.initial_states:velocity') - prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'traj.climb.initial_states:altitude') - - prob.model.connect('traj.descent.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[-1]) - ########################## - # 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 (makign each of the sub-objectives approx = 1 ) - prob.model.add_subsystem( - "regularization", - om.ExecComp( - # TODO: change the scaling on climb_duration - "reg_objective = - descent_mass_final/60000", - reg_objective=0.0, - descent_mass_final={"units": "kg", "shape": 1}, - ), - promotes_outputs=['reg_objective'] - ) - # connect the final mass from cruise into the objective - prob.model.connect("traj.descent.states:mass", - "regularization.descent_mass_final", src_indices=[-1]) - - prob.model.add_objective('reg_objective', ref=1) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - # suppress warnings: - # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' - with warnings.catch_warnings(): - - # Set initial default values for all LEAPS aircraft variables. - warnings.simplefilter("ignore", om.PromotionWarning) - set_aviary_initial_values(prob.model, aviary_inputs) - - warnings.simplefilter("ignore", om.PromotionWarning) - prob.setup() - - ########################################### - # Intial 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.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - # prob.set_val( - # 'traj.climb.states:velocity', climb.interp(Dynamic.Mission.VELOCITY, ys=[170, v_f_climb]), - # units='m/s') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[1.0, 1.0]), - units='unitless') - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.8, 0.75]), - units='unitless') - - 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.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=sim, make_plots=False, simulate_kwargs={ - 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9}, - solution_record_file='N3CC_full_mission.db') - prob.record("final") - prob.cleanup() - - return prob - - -@use_tempdirs -class ProblemPhaseTestCase(unittest.TestCase): - @require_pyoptsparse(optimizer='SNOPT') - def bench_test_full_mission_N3CC_SNOPT(self): - driver = _make_driver_SNOPT() - - self._do_run(driver) - - def _do_run(self, driver): - prob = run_trajectory(driver=driver, sim=False) - - times_climb = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes_climb = prob.get_val( - 'traj.climb.timeseries.states:altitude', units='m') - masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities_climb = prob.get_val( - 'traj.climb.timeseries.states: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.states:altitude', units='m') - masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities_cruise = prob.get_val( - 'traj.cruise.timeseries.states: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.states:altitude', units='m') - masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities_descent = prob.get_val( - 'traj.descent.timeseries.states:velocity', units='m/s') - thrusts_descent = prob.get_val( - 'traj.descent.timeseries.thrust_net_total', units='N') - - expected_times_s_climb = [[120.], [163.76276502], [224.14644864], [243.25767805], - [243.25767805], [336.40844168], [464.93748315], - [505.61648533], [505.61648533], [626.47047555], - [793.2243154], [846.00133557], [846.00133557], - [966.85532579], [1133.60916564], [1186.38618581], - [1186.38618581], [1279.53694944], [1408.06599092], - [1448.74499309], [1448.74499309], [1492.50775811], - [1552.89144173], [1572.00267114]] - expected_altitudes_m_climb = [[10.668], [0.], [490.31464488], [720.34099124], - [720.34099124], [2288.74497628], [4816.40500694], - [5464.87951761], [5464.87951761], [7025.37127556], - [8437.78568802], [8802.40370192], [8802.40370192], - [9511.72639581], [10229.15884616], [10382.97088649], - [10382.97088649], [10560.94435598], [10660.37367157], - [10668.], [10668.], [10668.], [10666.66785248], [10668.]] - expected_masses_kg_climb = [[58584.62973209], [58553.30079295], [58486.19463517], - [58461.90146352], [58461.90146352], [58339.61987692], - [58184.14978151], [58144.99942835], [58144.99942835], - [58041.54301581], [57927.14314383], [57894.10156256], - [57894.10156256], [57825.05181264], [57740.72348501], - [57716.38705856], [57716.38705856], [57675.62128122], - [57622.73581734], [57606.53973509], [57606.53973509], - [57589.20468199], [57563.40774787], [57554.3064769]] - expected_ranges_m_climb = [[1469.37868509], [5605.65587129], [13572.59161311], - [16576.93576947], [16576.93576947], [33254.75438651], - [59051.61685726], [67185.62511739], [67185.62511739], - [91756.36399005], [126369.47577928], [137576.80855552], - [137576.80855552], [163427.52300246], [199432.46291748], - [210871.48231952], [210871.48231952], [231238.09772766], - [259750.51731468], [268890.90216347], [268890.90216347], - [278771.58755554], [292561.32064207], [296983.91583583]] - expected_velocities_ms_climb = [[77.35938331], [111.19901718], [151.93398907], - [162.39904508], [162.39904508], [193.79386032], - [202.92916455], [202.83097007], [202.83097007], - [204.9548312], [211.13800405], [212.81677487], - [212.81677487], [215.00414951], [216.65184841], - [217.5075073], [217.5075073], [219.8725371], - [223.95818114], [225.18659652], [225.18659652], - [226.57877443], [230.5555138], [232.77530606]] - expected_thrusts_N_climb = [[50269.53763097], [89221.79391729], [105944.78221328], - [104742.61384096], [104742.61384096], [102539.17538465], - [80894.5840539], [74287.02308141], [74287.02308141], - [59565.00613161], [48715.65056776], [46229.53984695], - [46229.53984695], [41551.41074213], [35939.62791236], - [34345.57880903], [34345.57880903], [32008.34687504], - [29668.0461344], [29061.17556918], [29061.17556918], - [29571.25377648], [34034.12209303], [36366.13242869]] - - expected_times_s_cruise = [[1572.00267114], [10224.88157184], - [22164.08837724], [25942.80651013]] - expected_altitudes_m_cruise = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg_cruise = [[57554.3064769], [54168.16865196], - [49649.4641858], [48253.00754766]] - expected_ranges_m_cruise = [[296983.91583583], [2311160.45023764], - [5090312.96846673], [5969905.23836297]] - expected_velocities_ms_cruise = [[232.77530606], [232.77530606], - [232.77530606], [232.77530606]] - expected_thrusts_N_cruise = [[28599.34059358], [27655.863514], - [26491.25212162], [26155.81047559]] - - expected_times_s_descent = [[25942.80651013], [26025.25799534], [26139.02421633], - [26175.0308363], [26175.0308363], [26343.42020448], - [26575.76316382], [26649.29891605], [26649.29891605], - [26849.49721425], [27125.73000473], [27213.15673846], - [27213.15673846], [27381.54610664], [27613.88906597], - [27687.4248182], [27687.4248182], [27769.8763034], - [27883.6425244], [27919.64914437]] - expected_altitudes_m_descent = [[10668.], [10668.], [10142.61136584], - [9909.20496834], [9909.20496834], [8801.80844468], - [7273.17347505], [6802.45633892], [6802.45633892], - [5619.8230507], [4125.52995372], [3659.42225117], - [3659.42225117], [2735.99340162], [1425.57947265], - [1009.41898888], [1009.41898888], [561.99822911], - [94.31876192], [10.668]] - expected_masses_kg_descent = [[48253.00754766], [48247.14199102], [48243.08209003], - [48242.16864984], [48242.16864984], [48239.38631749], - [48238.09565644], [48238.10218909], [48238.10218909], - [48238.36804678], [48235.32226181], [48232.28685278], - [48232.28685278], [48219.23890964], [48194.77880065], - [48187.10389371], [48187.10389371], [48177.71262482], - [48164.36107545], [48160.10979474]] - expected_ranges_m_descent = [[5969905.23836297], [5987568.57791473], [6008764.81422574], - [6015233.86544087], [6015233.86544087], [ - 6044198.03874828], - [6081891.04303138], [6093386.547795], [6093386.547795], - [6123061.7076624], [6160342.11821306], [ - 6171307.0346796], - [6171307.0346796], [6192171.51704849], [ - 6220846.02761427], - [6230014.04117231], [6230014.04117231], [ - 6240198.28047116], - [6253503.06775949], [6257352.4]] - expected_velocities_ms_descent = [[232.77530606], [198.63654674], [179.66599067], - [176.95296882], [176.95296882], [167.50327408], - [157.55154249], [154.07756214], [154.07756214], - [142.57898741], [127.86775289], [125.11330664], - [125.11330664], [123.46196696], [124.28423824], - [124.03136002], [124.03136002], [122.19127487], - [109.94487807], [102.07377559]] - expected_thrusts_N_descent = [[4470.16874641], [2769.62977465], [1516.11359849], - [1315.10754789], [1315.10754789], [652.82279778], - [47.57054754], [-2.66626679e-13], [0.], - [4.84263343e-14], [1.42410958e-14], [-2.42743721e-14], - [0.], [0.], [1.77638636e-13], [2.84958986e-13], - [-1.39722436e-13], [0.], [0.], [-5.27816527e-14]] - - expected_times_s_climb = np.array(expected_times_s_climb) - expected_altitudes_m_climb = np.array(expected_altitudes_m_climb) - expected_masses_kg_climb = np.array(expected_masses_kg_climb) - expected_ranges_m_climb = np.array(expected_ranges_m_climb) - expected_velocities_ms_climb = np.array(expected_velocities_ms_climb) - expected_thrusts_N_climb = np.array(expected_thrusts_N_climb) - - expected_times_s_cruise = np.array(expected_times_s_cruise) - expected_altitudes_m_cruise = np.array(expected_altitudes_m_cruise) - expected_masses_kg_cruise = np.array(expected_masses_kg_cruise) - expected_ranges_m_cruise = np.array(expected_ranges_m_cruise) - expected_velocities_ms_cruise = np.array(expected_velocities_ms_cruise) - expected_thrusts_N_cruise = np.array(expected_thrusts_N_cruise) - - expected_times_s_descent = np.array(expected_times_s_descent) - expected_altitudes_m_descent = np.array(expected_altitudes_m_descent) - expected_masses_kg_descent = np.array(expected_masses_kg_descent) - expected_ranges_m_descent = np.array(expected_ranges_m_descent) - expected_velocities_ms_descent = np.array(expected_velocities_ms_descent) - expected_thrusts_N_descent = np.array(expected_thrusts_N_descent) - - # Check Objective and other key variables to a reasonably tight tolerance. - - rtol = 1e-2 - - # Mass at the end of Descent - assert_near_equal(masses_descent[-1], - expected_masses_kg_descent[-1], tolerance=rtol) - - # Range at the end of Descent - assert_near_equal(ranges_descent[-1], - expected_ranges_m_descent[-1], tolerance=rtol) - - # Flight time - assert_near_equal(times_descent[-1], - expected_times_s_descent[-1], tolerance=rtol) - - # Check mission values. - - # NOTE rtol = 0.05 = 5% different from truth (first timeseries) - # atol = 2 = no more than +/-2 meter/second/kg difference between values - # atol_altitude - 30 ft. There is occasional time-shifting with the N3CC - # model during climb and descent so we need a looser - # absolute tolerance for the points near the ground. - rtol = .05 - atol = 2.0 - atol_altitude = 30.0 - - # FLIGHT PATH - # CLIMB - warn_timeseries_near_equal( - times_climb, altitudes_climb, expected_times_s_climb, - expected_altitudes_m_climb, abs_tolerance=atol_altitude, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, masses_climb, expected_times_s_climb, - expected_masses_kg_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, ranges_climb, expected_times_s_climb, - expected_ranges_m_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, velocities_climb, expected_times_s_climb, - expected_velocities_ms_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, thrusts_climb, expected_times_s_climb, - expected_thrusts_N_climb, abs_tolerance=atol, rel_tolerance=rtol) - - # CRUISE - warn_timeseries_near_equal( - times_cruise, altitudes_cruise, expected_times_s_cruise, - expected_altitudes_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, masses_cruise, expected_times_s_cruise, - expected_masses_kg_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, ranges_cruise, expected_times_s_cruise, - expected_ranges_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, velocities_cruise, expected_times_s_cruise, - expected_velocities_ms_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, thrusts_cruise, expected_times_s_cruise, - expected_thrusts_N_cruise, abs_tolerance=atol, rel_tolerance=rtol) - - # DESCENT - warn_timeseries_near_equal( - times_descent, altitudes_descent, expected_times_s_descent, - expected_altitudes_m_descent, abs_tolerance=atol_altitude, - rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, masses_descent, expected_times_s_descent, - expected_masses_kg_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, ranges_descent, expected_times_s_descent, - expected_ranges_m_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, velocities_descent, expected_times_s_descent, - expected_velocities_ms_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, thrusts_descent, expected_times_s_descent, - expected_thrusts_N_descent, abs_tolerance=atol, rel_tolerance=rtol) - - -def _make_driver_IPOPT() -> Driver: - driver = om.pyOptSparseDriver(optimizer='IPOPT') - - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - return driver - - -def _make_driver_SNOPT() -> Driver: - driver = om.pyOptSparseDriver(optimizer='SNOPT') - - driver.opt_settings["Major iterations limit"] = 45 - driver.opt_settings["Major optimality tolerance"] = 1e-4 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - - return driver - - -def _make_driver_SLSQP() -> Driver: - driver = om.ScipyOptimizeDriver(optimizer='SLSQP') - - driver.opt_settings['maxiter'] = 100 - driver.opt_settings['ftol'] = 5.0e-3 - driver.opt_settings['eps'] = 1e-2 - - return driver - - -if __name__ == '__main__': - temp = ProblemPhaseTestCase() - temp.bench_test_full_mission_N3CC_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py deleted file mode 100644 index 5c8214267..000000000 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ /dev/null @@ -1,664 +0,0 @@ -''' -NOTES: -Includes: -Takeoff, Climb, Cruise, Descent, Landing -Computed Aero -Large Single Aisle 1 data -''' -import unittest - -import dymos as dm -import numpy as np -import openmdao.api as om -import scipy.constants as _units -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs - -from aviary.mission.flops_based.phases.build_landing import Landing -from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.subsystems.premission import CorePreMission -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.utils.preprocessors import preprocess_options -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.variable_info.variables_in import VariablesIn -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - -# benchmark based on large single aisle 1 (fixed cruise alt) FLOPS model - - -def run_trajectory(sim=True): - prob = om.Problem() - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - # driver.declare_coloring() # currently disabled pending resolve of issue 2507 - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 45 - driver.opt_settings["Major optimality tolerance"] = 1e-4 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_outputs = get_flops_outputs('LargeSingleAisle1FLOPS') - - preprocess_options(aviary_inputs) - - alt_airport = 0 # ft - - alt_i_climb = 0*_units.foot # m - alt_f_climb = 35000.0*_units.foot # m - mass_i_climb = 180623*_units.lb # kg - mass_f_climb = 176765*_units.lb # kg - v_i_climb = 198.44*_units.knot # m/s - v_f_climb = 455.49*_units.knot # m/s - # 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 = 0.79 - 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 = 176765*_units.lb # kg - mass_f_cruise = 143521*_units.lb # kg - v_i_cruise = 455.49*_units.knot # m/s - v_f_cruise = 455.49*_units.knot # m/s - # mach_i_cruise = 0.79 - # mach_f_cruise = 0.79 - mach_min_cruise = 0.79 - mach_max_cruise = 0.79 - 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 - v_i_descent = 455.49*_units.knot - v_f_descent = 198.44*_units.knot - mach_i_descent = 0.79 - mach_f_descent = 0.3 - mass_i_descent = 143521*_units.pound - mass_f_descent = 143035*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_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 - - ################## - # 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) - - takeoff_options = Takeoff( - airport_altitude=alt_airport, # ft - num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES) - ) - - climb_options = Climb( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (False, 'unitless'), - 'input_initial': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_climb, - ) - - cruise_options = Cruise( - 'test_cruise', - user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (False, 'unitless'), - 'fix_final': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_cruise, - ) - - descent_options = Descent( - 'test_descent', - user_options=AviaryValues({ - 'final_altitude': (alt_f_descent, 'm'), - 'initial_altitude': (alt_i_descent, 'm'), - 'initial_mach': (mach_i_descent, 'unitless'), - 'final_mach': (mach_f_descent, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_descent, - ) - - landing_options = Landing( - ref_wing_area=aviary_inputs.get_val(Aircraft.Wing.AREA, 'ft**2'), - Cl_max_ldg=aviary_inputs.get_val(Mission.Landing.LIFT_COEFFICIENT_MAX) - ) - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'pre_mission', - CorePreMission(aviary_options=aviary_inputs, - subsystems=default_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) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - descent = descent_options.build_phase(aviary_options=aviary_inputs) - - 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=(1, t_duration_climb*2), duration_ref=t_duration_climb) - cruise.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - descent.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_descent*2), duration_ref=t_duration_descent) - - traj.add_phase('climb', climb) - - traj.add_phase('cruise', cruise) - - traj.add_phase('descent', descent) - - climb.timeseries_options['use_prefix'] = True - cruise.timeseries_options['use_prefix'] = True - descent.timeseries_options['use_prefix'] = True - - prob.model.add_subsystem( - 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - ################################## - # Connect in Takeoff and Landing # - ################################## - - prob.model.add_subsystem( - "takeoff_constraints", - om.ExecComp( - [ - "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", - "takeoff_vel_con=takeoff_vel-climb_start_vel", - "takeoff_alt_con=takeoff_alt-climb_start_alt" - ], - takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, - climb_start_mass={'units': 'lbm'}, - takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, - takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, - climb_start_vel={'units': 'm/s'}, - takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, - climb_start_alt={'units': 'ft'} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Takeoff.FINAL_MASS), - ("takeoff_range", Mission.Takeoff.GROUND_DISTANCE), - ("takeoff_vel", Mission.Takeoff.FINAL_VELOCITY), - ("takeoff_alt", Mission.Takeoff.FINAL_ALTITUDE), - ], - promotes_outputs=["takeoff_mass_con", "takeoff_range_con", - "takeoff_vel_con", "takeoff_alt_con"], - ) - - prob.model.connect('traj.climb.states:mass', - 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', - 'takeoff_constraints.climb_start_range', src_indices=[0]) - prob.model.connect('traj.climb.states:velocity', - 'takeoff_constraints.climb_start_vel', src_indices=[0]) - prob.model.connect('traj.climb.states:altitude', - 'takeoff_constraints.climb_start_alt', src_indices=[0]) - - prob.model.connect(Mission.Takeoff.FINAL_MASS, - 'traj.climb.initial_states:mass') - prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') - prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, - 'traj.climb.initial_states:velocity') - prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'traj.climb.initial_states:altitude') - - prob.model.connect('traj.descent.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[-1]) - - ########################## - # 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 (makign each of the sub-objectives approx = 1 ) - prob.model.add_subsystem( - "regularization", - om.ExecComp( - # TODO: change the scaling on climb_duration - "reg_objective = - descent_mass_final/60000", - reg_objective=0.0, - descent_mass_final={"units": "kg", "shape": 1}, - ), - promotes_outputs=['reg_objective'] - ) - # connect the final mass from cruise into the objective - prob.model.connect("traj.descent.states:mass", - "regularization.descent_mass_final", src_indices=[-1]) - - prob.model.add_objective('reg_objective', ref=1) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - # TODO: Why is this in outputs and not inputs? - key = Aircraft.Engine.THRUST_REVERSERS_MASS - val, units = aviary_outputs.get_item(key) - prob.model.set_input_defaults(key, val, units) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - prob.setup() - - ########################################### - # Intial 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.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - # prob.set_val( - # 'traj.climb.states:velocity', climb.interp(Dynamic.Mission.VELOCITY, ys=[170, v_f_climb]), - # units='m/s') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - 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.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=sim, make_plots=False, simulate_kwargs={ - 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9}, - solution_record_file='large_single_aisle_1_solution.db') - prob.record("final") - prob.cleanup() - - return prob - - -@use_tempdirs -class ProblemPhaseTestCase(unittest.TestCase): - def bench_test_full_mission_large_single_aisle_1(self): - - prob = run_trajectory(sim=False) - - times_climb = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes_climb = prob.get_val( - 'traj.climb.timeseries.states:altitude', units='m') - masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities_climb = prob.get_val( - 'traj.climb.timeseries.states: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.states:altitude', units='m') - masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities_cruise = prob.get_val( - 'traj.cruise.timeseries.states: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.states:altitude', units='m') - masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities_descent = prob.get_val( - 'traj.descent.timeseries.states:velocity', units='m/s') - thrusts_descent = prob.get_val( - 'traj.descent.timeseries.thrust_net_total', units='N') - - expected_times_s_climb = [ - [120.], [163.76325456], [224.14761365], [243.25905685], - [243.25905685], [336.41086249], [464.94134172], [505.62079895], - [505.62079895], [626.47614107], [793.23184628], [846.00945683], - [846.00945683], [966.86479896], [1133.62050417], [1186.39811471], - [1186.39811471], [1279.54992036], [1408.08039959], [1448.75985682], - [1448.75985682], [1492.52311138], [1552.90747047], [1572.01891366]] - expected_altitudes_m_climb = [ - [10.668], [0.], [1014.96376993], [1474.88490893], - [1474.88490893], [3450.8992731], [5549.58991137], [6073.60289567], - [6073.60289567], [7247.65102441], [8313.09660771], [8596.21261844], - [8596.21261844], [9175.1805832], [9807.17741861], [9956.37909202], - [9956.37909202], [10156.95278577], [10387.66964669], [10469.50089961], - [10469.50089961], [10565.21436037], [10659.11220277], [10668.]] - expected_masses_kg_climb = [ - [81929.21464651], [81845.89383716], [81698.07677997], [81651.72896811], - [81651.72896811], [81451.5201184], [81238.04517346], [81180.70309604], - [81180.70309604], [81030.90916993], [80852.63402635], [80799.37995098], - [80799.37995098], [80685.66441919], [80541.42480306], [80497.91293126], - [80497.91293126], [80422.58418106], [80320.79494098], [80289.0126768], - [80289.0126768], [80255.43650168], [80209.81935885], [80195.47487578]] - expected_ranges_m_climb = [ - [2023.13728418], [7309.29529844], [17625.33986498], [21042.26607802], - [21042.26607802], [38595.24976097], [63501.20931809], [71333.49759313], - [71333.49759313], [95066.70557732], [129238.42790298], [140520.59490531], - [140520.59490531], [166712.77513886], [203467.60377384], [215173.95317494], - [215173.95317494], [236133.6275649], [265602.08094631], [275049.96491681], - [275049.96491681], [285205.23036747], [299246.15306878], [303707.66300732]] - expected_velocities_ms_climb = [ - [86.27497122], [150.21937278], [181.89204952], [185.19401741], - [185.19401741], [193.05567218], [193.94250629], [194.2274308], - [194.2274308], [199.49589035], [211.4364855], [214.57351446], - [214.57351446], [218.7009295], [221.65884364], [223.09827293], - [223.09827293], [226.88054212], [231.57590395], [232.11980164], - [232.11980164], [232.10881873], [233.15980248], [234.25795132]] - expected_thrusts_N_climb = [ - [132715.85627327], [165245.22863773], [167448.73291722], [160900.8406642], - [160900.8406642], [127136.48651829], [98045.08452667], [90929.93404254], - [90929.93404254], [77481.47159379], [66945.17202854], [64341.32162839], - [64341.32162839], [59055.89956031], [54151.63303545], [53020.95829213], - [53020.95829213], [51622.0422889], [50045.94083626], [49417.41803104], - [49417.41803104], [48644.32827828], [47944.25167088], [47933.1465328]] - - expected_times_s_cruise = [[1572.01891366], [ - 10224.87387308], [22164.04764439], [25942.75532212]] - expected_altitudes_m_cruise = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg_cruise = [[80195.47487578], [ - 74629.35731156], [67375.28255861], [65172.93890147]] - expected_ranges_m_cruise = [[303707.66300732], [ - 2330707.73887436], [5127554.12700399], [6012746.44622707]] - expected_velocities_ms_cruise = [[234.25795132], [ - 234.25795132], [234.25795132], [234.25795132]] - expected_thrusts_N_cruise = [[41824.96226832], [ - 39641.43620269], [36936.34901257], [36154.52769977]] - - expected_times_s_descent = [ - [25942.75532212], [26006.65447531], [26094.82226471], [26122.72706861], - [26122.72706861], [26253.22730164], [26433.29098775], [26490.28052876], - [26490.28052876], [26645.43239405], [26859.51030121], [26927.26522688], - [26927.26522688], [27057.76545992], [27237.82914603], [27294.81868703], - [27294.81868703], [27358.71784022], [27446.88562963], [27474.79043352]] - expected_altitudes_m_descent = [ - [1.06680000e+04], [1.06680000e+04], [1.01870034e+04], [9.98295734e+03], - [9.98295734e+03], [8.97976640e+03], [7.54858109e+03], [7.09637574e+03], - [7.09637574e+03], [5.88591590e+03], [4.22625069e+03], [3.69222380e+03], - [3.69222380e+03], [2.61250549e+03], [1.13888643e+03], [7.11625616e+02], - [7.11625616e+02], [3.06900655e+02], [1.06680000e+01], [1.06680000e+01]] - expected_masses_kg_descent = [ - [65172.93890147], [65166.80185527], [65159.70921571], [65157.42471584], - [65157.42471584], [65146.76382877], [65130.82732956], [65125.34524899], - [65125.34524899], [65109.28561058], [65083.64486622], [65074.44308601], - [65074.44308601], [65054.73517647], [65022.79856574], [65011.43379965], - [65011.43379965], [64998.13023434], [64979.19121811], [64973.1898506]] - expected_ranges_m_descent = [ - [6012746.44622707], [6026563.35875724], [6043156.61719684], - [6048186.41354773], [6048186.41354773], [6070643.2394269], - [6100144.8206876], [6109350.83226072], [6109350.83226072], - [6133985.78349596], [6167266.64464002], [6177671.71555852], - [6177671.71555852], [6197775.49290063], [6225243.66498946], - [6233748.78818454], [6233748.78818454], [6242933.61721041], - [6254285.51733338], [6257352.4]] - expected_velocities_ms_descent = [ - [234.25795132], [200.84994317], [180.71529791], [177.55751262], - [177.55751262], [167.72481926], [161.81636181], [160.6651682], - [160.6651682], [157.4025997], [154.14780084], [153.88934075], - [153.88934075], [154.23063023], [150.48828108], [146.76095672], - [146.76095672], [139.54419751], [115.31288595], [102.07377559]] - expected_thrusts_N_descent = [ - [0.00000000e+00], [8.47474799e-13], [1.05910816e-13], [-6.67104835e-13], - [0.00000000e+00], [2.74056170e-13], [6.93382542e-13], [8.33653923e-13], - [0.00000000e+00], [4.66122489e-14], [-1.43628962e-13], [-2.96621357e-13], - [0.00000000e+00], [0.00000000e+00], [-1.18597257e-14], [-1.95075855e-14], - [-9.53501847e-15], [0.00000000e+00], [0.00000000e+00], [-3.72692384e-15]] - - expected_times_s_climb = np.array(expected_times_s_climb) - expected_altitudes_m_climb = np.array(expected_altitudes_m_climb) - expected_masses_kg_climb = np.array(expected_masses_kg_climb) - expected_ranges_m_climb = np.array(expected_ranges_m_climb) - expected_velocities_ms_climb = np.array(expected_velocities_ms_climb) - expected_thrusts_N_climb = np.array(expected_thrusts_N_climb) - - expected_times_s_cruise = np.array(expected_times_s_cruise) - expected_altitudes_m_cruise = np.array(expected_altitudes_m_cruise) - expected_masses_kg_cruise = np.array(expected_masses_kg_cruise) - expected_ranges_m_cruise = np.array(expected_ranges_m_cruise) - expected_velocities_ms_cruise = np.array(expected_velocities_ms_cruise) - expected_thrusts_N_cruise = np.array(expected_thrusts_N_cruise) - - expected_times_s_descent = np.array(expected_times_s_descent) - expected_altitudes_m_descent = np.array(expected_altitudes_m_descent) - expected_masses_kg_descent = np.array(expected_masses_kg_descent) - expected_ranges_m_descent = np.array(expected_ranges_m_descent) - expected_velocities_ms_descent = np.array(expected_velocities_ms_descent) - expected_thrusts_N_descent = np.array(expected_thrusts_N_descent) - - # Check Objective and other key variables to a reasonably tight tolerance. - - rtol = 1e-2 - - # Mass at the end of Descent - assert_near_equal(masses_descent[-1], - expected_masses_kg_descent[-1], tolerance=rtol) - - # Range at the end of Descent - assert_near_equal(ranges_descent[-1], - expected_ranges_m_descent[-1], tolerance=rtol) - - # Flight time - assert_near_equal(times_descent[-1], - expected_times_s_descent[-1], tolerance=rtol) - - # Check mission values. - - # NOTE rtol = 0.05 = 5% different from truth (first timeseries) - # atol = 2 = no more than +/-2 meter/second/kg difference between values - # atol_altitude - 30 ft. There is occasional time-shifting with the N3CC - # model during climb and descent so we need a looser - # absolute tolerance for the points near the ground. - rtol = .05 - atol = 2.0 - atol_altitude = 30.0 - - # FLIGHT PATH - # CLIMB - warn_timeseries_near_equal( - times_climb, altitudes_climb, expected_times_s_climb, - expected_altitudes_m_climb, abs_tolerance=atol_altitude, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, masses_climb, expected_times_s_climb, - expected_masses_kg_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, ranges_climb, expected_times_s_climb, - expected_ranges_m_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, velocities_climb, expected_times_s_climb, - expected_velocities_ms_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, thrusts_climb, expected_times_s_climb, - expected_thrusts_N_climb, abs_tolerance=atol, rel_tolerance=rtol) - - # CRUISE - warn_timeseries_near_equal( - times_cruise, altitudes_cruise, expected_times_s_cruise, - expected_altitudes_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, masses_cruise, expected_times_s_cruise, - expected_masses_kg_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, ranges_cruise, expected_times_s_cruise, - expected_ranges_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, velocities_cruise, expected_times_s_cruise, - expected_velocities_ms_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, thrusts_cruise, expected_times_s_cruise, - expected_thrusts_N_cruise, abs_tolerance=atol, rel_tolerance=rtol) - - # DESCENT - warn_timeseries_near_equal( - times_descent, altitudes_descent, expected_times_s_descent, - expected_altitudes_m_descent, abs_tolerance=atol_altitude, - rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, masses_descent, expected_times_s_descent, - expected_masses_kg_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, ranges_descent, expected_times_s_descent, - expected_ranges_m_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, velocities_descent, expected_times_s_descent, - expected_velocities_ms_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, thrusts_descent, expected_times_s_descent, - expected_thrusts_N_descent, abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == '__main__': - unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py deleted file mode 100644 index a81566387..000000000 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ /dev/null @@ -1,701 +0,0 @@ -''' -NOTES: -Includes: -Takeoff, Climb, Cruise, Descent, Landing -Computed Aero -Large Single Aisle 2 data -''' -import unittest - -import dymos as dm -import numpy as np -import openmdao.api as om -import scipy.constants as _units -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs - -from aviary.mission.flops_based.phases.build_landing import Landing -from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.variable_info.variables_in import VariablesIn -from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems -from aviary.utils.preprocessors import preprocess_options - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - -# benchmark based on Large Single Aisle 2 (fixed cruise alt) FLOPS model - - -def run_trajectory(sim=True): - prob = om.Problem(model=om.Group()) - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - # driver.declare_coloring() # currently disabled pending resolve of issue 2507 - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 45 - driver.opt_settings["Major optimality tolerance"] = 1e-4 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - - preprocess_options(aviary_inputs) - - alt_airport = 0 # ft - - ref_wing_area = 1370 # ft^2 TODO: where should this get connected from? - - alt_i_climb = 35.0*_units.foot # m (comes from takeoff) - alt_f_climb = 35000.0*_units.foot # m - mass_i_climb = 178172*_units.lb # kg (comes from takeoff) - mass_f_climb = 174160*_units.lb # kg - v_i_climb = 198.44*_units.knot # m/s (comes from takeoff) - v_f_climb = 452.61*_units.knot # m/s - mach_i_climb = 0.2 # TODO: (need to compute this in takeoff) - mach_f_climb = 0.785 - range_i_climb = 0*_units.nautical_mile # m (comes from takeoff) - range_f_climb = 124*_units.nautical_mile # m - t_i_climb = 0 - t_duration_climb = 20.14*_units.minute # sec - - 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 = 174160*_units.lb # kg - mass_f_cruise = 140515*_units.lb # kg - v_i_cruise = 452.61*_units.knot # m/s - v_f_cruise = 452.61*_units.knot # m/s - mach_f_cruise = 0.785 - mach_min_cruise = 0.785 - mach_max_cruise = 0.785 - range_i_cruise = 124*_units.nautical_mile # m - range_f_cruise = 2830.8*_units.nautical_mile # m - t_i_cruise = t_i_climb + t_duration_climb # sec - t_duration_cruise = (378.95)*_units.minute - t_duration_climb # sec - - alt_i_descent = 35000*_units.foot # m - alt_f_descent = 35*_units.foot # m - v_i_descent = 452.61*_units.knot # m/s - v_f_descent = 198.44*_units.knot # m/s - mass_i_descent = 140515*_units.pound # kg - mass_f_descent = 140002*_units.pound # kg - mach_i_descent = mach_f_cruise - mach_f_descent = 0.3 - range_i_descent = 2830.8*_units.nautical_mile # m - range_f_descent = 2960.0*_units.nautical_mile # m - t_i_descent = t_duration_cruise+t_duration_climb # sec - t_duration_descent = 2000 # sec - - Cl_max_ldg = 3 # TODO: should this come from aero? - - ################## - # 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) - - takeoff_options = Takeoff( - airport_altitude=alt_airport, # ft - num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES) - ) - - climb_options = Climb( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (False, 'unitless'), - 'input_initial': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_climb, - ) - - cruise_options = Cruise( - 'test_cruise', - user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (False, 'unitless'), - 'fix_final': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_cruise, - ) - - descent_options = Descent( - 'test_descent', - user_options=AviaryValues({ - 'final_altitude': (alt_f_descent, 'm'), - 'initial_altitude': (alt_i_descent, 'm'), - 'initial_mach': (mach_i_descent, 'unitless'), - 'final_mach': (mach_f_descent, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'fix_range': (True, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_descent, - ) - - landing_options = Landing( - ref_wing_area=ref_wing_area, # ft**2 - Cl_max_ldg=Cl_max_ldg # no units - ) - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'pre_mission', - CorePreMission(aviary_options=aviary_inputs, - subsystems=default_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) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - descent = descent_options.build_phase(aviary_options=aviary_inputs) - - 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=(1, t_duration_climb*2), duration_ref=t_duration_climb) - cruise.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - descent.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(1, t_duration_descent*2), duration_ref=t_duration_descent) - - traj.add_phase('climb', climb) - - traj.add_phase('cruise', cruise) - - traj.add_phase('descent', descent) - - climb.timeseries_options['use_prefix'] = True - cruise.timeseries_options['use_prefix'] = True - descent.timeseries_options['use_prefix'] = True - - prob.model.add_subsystem( - 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - ################################## - # Connect in Takeoff and Landing # - ################################## - - prob.model.add_subsystem( - "takeoff_constraints", - om.ExecComp( - [ - "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", - "takeoff_vel_con=takeoff_vel-climb_start_vel", - "takeoff_alt_con=takeoff_alt-climb_start_alt" - ], - takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, - climb_start_mass={'units': 'lbm'}, - takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, - takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, - climb_start_vel={'units': 'm/s'}, - takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, - climb_start_alt={'units': 'ft'} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Takeoff.FINAL_MASS), - ("takeoff_range", Mission.Takeoff.GROUND_DISTANCE), - ("takeoff_vel", Mission.Takeoff.FINAL_VELOCITY), - ("takeoff_alt", Mission.Takeoff.FINAL_ALTITUDE), - ], - promotes_outputs=["takeoff_mass_con", "takeoff_range_con", - "takeoff_vel_con", "takeoff_alt_con"], - ) - - prob.model.connect('traj.climb.states:mass', - 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', - 'takeoff_constraints.climb_start_range', src_indices=[0]) - prob.model.connect('traj.climb.states:velocity', - 'takeoff_constraints.climb_start_vel', src_indices=[0]) - prob.model.connect('traj.climb.states:altitude', - 'takeoff_constraints.climb_start_alt', src_indices=[0]) - - prob.model.connect(Mission.Takeoff.FINAL_MASS, - 'traj.climb.initial_states:mass') - prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') - prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, - 'traj.climb.initial_states:velocity') - prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'traj.climb.initial_states:altitude') - - prob.model.connect('traj.descent.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[-1]) - - ########################## - # 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 (makign each of the sub-objectives approx = 1 ) - prob.model.add_subsystem( - "regularization", - om.ExecComp( - # TODO: change the scaling on climb_duration - "reg_objective = - descent_mass_final/60000", - reg_objective=0.0, - descent_mass_final={"units": "kg", "shape": 1}, - ), - promotes_outputs=['reg_objective'] - ) - # connect the final mass from cruise into the objective - prob.model.connect("traj.descent.states:mass", - "regularization.descent_mass_final", src_indices=[-1]) - - prob.model.add_objective('reg_objective', ref=1) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - prob.setup() - - ########################################### - # Intial 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.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - 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.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=sim, make_plots=False, simulate_kwargs={ - 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9}, - solution_record_file='large_single_aisle_2_solution.db') - prob.record("final") - prob.cleanup() - - return prob - - -@use_tempdirs -class ProblemPhaseTestCase(unittest.TestCase): - def bench_test_full_mission_large_single_aisle_2(self): - - prob = run_trajectory(sim=False) - - times_climb = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes_climb = prob.get_val( - 'traj.climb.timeseries.states:altitude', units='m') - masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities_climb = prob.get_val( - 'traj.climb.timeseries.states: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.states:altitude', units='m') - masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities_cruise = prob.get_val( - 'traj.cruise.timeseries.states: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.states:altitude', units='m') - masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities_descent = prob.get_val( - 'traj.descent.timeseries.states:velocity', units='m/s') - thrusts_descent = prob.get_val( - 'traj.descent.timeseries.thrust_net_total', units='N') - - expected_times_s_climb = [[0.], [36.42164779], [86.67608797], [102.58144646], - [102.58144646], [180.10635382], [287.07490293], - [320.93008299], [320.93008299], [421.51105549], - [560.29226869], [604.21604816], [604.21604816], - [704.79702067], [843.57823386], [887.50201334], - [887.50201334], [965.0269207], [1071.9954698], - [1105.85064986], [1105.85064986], [1142.27229765], - [1192.52673783], [1208.43209632]] - expected_altitudes_m_climb = [[10.668], [10.668], [756.40579584], [1094.69377576], - [1094.69377576], [2638.335354], [4474.82351314], - [4956.42872513], [4956.42872513], [6093.2556723], - [7216.10719049], [7539.50807227], [7539.50807227], - [8246.0164048], [9133.44034449], [9376.84106855], - [9376.84106855], [9769.35335562], [10235.21824927], - [10366.38189087], [10366.38189087], [10496.4112199], - [10637.33808625], [10668.]] - expected_masses_kg_climb = [[78716.87348217], [78630.56839717], [78501.99380919], - [78461.17568729], [78461.17568729], [78282.66956759], - [78079.48002171], [78024.13525417], [78024.13525417], - [77874.53619474], [77690.00183752], [77632.85287533], - [77632.85287533], [77506.6235826], [77341.2312645], - [77291.7130525], [77291.7130525], [77206.37945353], - [77094.28764289], [77060.26735586], [77060.26735586], - [77024.49553459], [76976.26878085], [76961.2011732]] - expected_ranges_m_climb = [[2020.172677], [6250.78127734], [14408.93179369], - [17152.5734179], [17152.5734179], [31361.95647109], - [51731.27335637], [58135.07173792], [58135.07173792], - [77558.59088335], [105627.83510378], [114946.12296084], - [114946.12296084], [136784.80542027], [167833.78601896], - [177796.59419893], [177796.59419893], [195533.43046681], - [220220.00511814], [228064.41792222], [228064.41792222], - [236500.76050256], [248152.97050119], [251848.92128258]] - expected_velocities_ms_climb = [[85.50188638], [142.5264918], [174.18896469], - [178.36168293], [178.36168293], [189.05364242], - [190.8409755], [191.10004849], [191.10004849], - [196.39829028], [209.55408002], [213.5660258], - [213.5660258], [220.53005733], [226.3795119], - [227.73490457], [227.73490457], [229.83816653], - [231.58844935], [231.71451888], [231.71451888], - [231.66373105], [232.22063654], [232.77530606]] - expected_thrusts_N_climb = [[189058.83725077], - [170072.62422304], - [158048.98358529], - [154385.46295721], - [154385.46295721], - [136940.62457029], - [116116.73671672], - [110355.92368163], - [110355.92368163], - [97102.32305726], - [84436.60128586], - [81321.06998036], - [81321.06998036], - [75575.9138158], - [69929.77214168], - [68233.54819255], - [68233.54819255], - [66906.31800496], - [64990.02370683], - [64226.67297361], - [64226.67297361], - [63890.14810601], - [62804.25695388], - [61976.46190808]] - - expected_times_s_cruise = [[1208.43209632], [8852.14330109], - [19398.90466014], [22736.91857014]] - expected_altitudes_m_cruise = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg_cruise = [[76961.2011732], [71368.01841021], - [64248.23842657], [62092.78518296]] - expected_ranges_m_cruise = [[251848.92128258], [2031116.13639915], - [4486141.73968515], [5263148.9492152]] - expected_velocities_ms_cruise = [[232.77530606], [232.77530606], - [232.77530606], [232.77530606]] - expected_thrusts_N_cruise = [[42313.90859903], - [39067.24395088], - [35950.87557908], - [35318.16856753]] - - expected_times_s_descent = [[22736.91857014], [22787.42540336], [22857.11452461], - [22879.17089321], [22879.17089321], [22982.32020233], - [23124.64519584], [23169.69056966], [23169.69056966], - [23292.32489254], [23461.53522808], [23515.08972074], - [23515.08972074], [23618.23902986], [23760.56402336], - [23805.60939719], [23805.60939719], [23856.11623041], - [23925.80535166], [24317.03614505]] - expected_altitudes_m_descent = [[10668.], [10434.7028388], [9960.79015066], - [9784.8421005], [9784.8421005], [8895.17761059], - [7537.33136949], [7090.56116653], [7090.56116653], - [5841.93815892], [3999.27122775], [3377.71804494], - [3377.71804494], [2138.48831166], [663.47208745], - [344.68854352], [344.68854352], [122.72341358], - [10.668], [10.668]] - expected_masses_kg_descent = [[62092.78518296], [62087.36440032], [62080.05896866], - [62077.72767582], [62077.72767582], [62066.62726287], - [62050.05526861], [62044.32456475], [62044.32456475], - [62027.35019169], [62000.0762637], [61990.36426104], - [61990.36426104], [61969.97789242], [61939.03538935], - [61928.82648685], [61928.82648685], [61917.76865363], - [61902.72792251], [60998.50259339]] - expected_ranges_m_descent = [[5263148.9492152], [5274432.80167853], [5288836.80724673], - [5293223.61558423], [ - 5293223.61558423], [5313013.5415642], - [5339348.96176189], [5347671.94897183], [ - 5347671.94897183], - [5370259.6353939], [5401419.10034695], [ - 5411278.66121681], - [5411278.66121681], [5430273.70362962], [ - 5455475.25800144], - [5462914.27715932], [5462914.27715932], [ - 5470553.18510276], - [5479541.42534675], [5481920.]] - expected_velocities_ms_descent = [[232.77530606], [215.12062535], [200.3306912], - [197.18540872], [197.18540872], [187.8799993], - [184.51577102], [184.46836756], [184.46836756], - [184.46836756], [184.46836756], [184.46836756], - [184.46836756], [183.31878177], [168.97447568], - [158.78398844], [158.78398844], [143.03675256], - [113.40966999], [102.07377559]] - expected_thrusts_N_descent = [[-10826.40055652], - [-4402.33172934], - [3254.14270948], - [5235.45930457], - [5235.45930457], - [12007.31061759], - [13032.5411879], - [10960.76992506], - [10960.76992506], - [5671.53535014], - [1824.89872243], - [1525.32410053], - [1525.32410053], - [-329.33574306], - [-9335.05085191], - [-13485.38001055], - [-13485.38001055], - [-17391.90310498], - [-14884.85752283], - [-12642.43964087]] - - expected_times_s_climb = np.array(expected_times_s_climb) - expected_altitudes_m_climb = np.array(expected_altitudes_m_climb) - expected_masses_kg_climb = np.array(expected_masses_kg_climb) - expected_ranges_m_climb = np.array(expected_ranges_m_climb) - expected_velocities_ms_climb = np.array(expected_velocities_ms_climb) - expected_thrusts_N_climb = np.array(expected_thrusts_N_climb) - - expected_times_s_cruise = np.array(expected_times_s_cruise) - expected_altitudes_m_cruise = np.array(expected_altitudes_m_cruise) - expected_masses_kg_cruise = np.array(expected_masses_kg_cruise) - expected_ranges_m_cruise = np.array(expected_ranges_m_cruise) - expected_velocities_ms_cruise = np.array(expected_velocities_ms_cruise) - expected_thrusts_N_cruise = np.array(expected_thrusts_N_cruise) - - expected_times_s_descent = np.array(expected_times_s_descent) - expected_altitudes_m_descent = np.array(expected_altitudes_m_descent) - expected_masses_kg_descent = np.array(expected_masses_kg_descent) - expected_ranges_m_descent = np.array(expected_ranges_m_descent) - expected_velocities_ms_descent = np.array(expected_velocities_ms_descent) - expected_thrusts_N_descent = np.array(expected_thrusts_N_descent) - - # Check Objective and other key variables to a reasonably tight tolerance. - - rtol = 1e-3 - - # Mass at the end of Descent - assert_near_equal(masses_descent[-1], - expected_masses_kg_descent[-1], tolerance=rtol) - - # Range at the end of Descent - assert_near_equal(ranges_descent[-1], - expected_ranges_m_descent[-1], tolerance=rtol) - - # Flight time - assert_near_equal(times_descent[-1], - expected_times_s_descent[-1], tolerance=rtol) - - # Check mission values. - - # NOTE rtol = 0.05 = 5% different from truth (first timeseries) - # atol = 2 = no more than +/-2 meter/second/kg difference between values - # atol_altitude - 30 ft. There is occasional time-shifting with the N3CC - # model during climb and descent so we need a looser - # absolute tolerance for the points near the ground. - rtol = .05 - atol = 2.0 - atol_altitude = 30.0 - - # FLIGHT PATH - # CLIMB - warn_timeseries_near_equal( - times_climb, altitudes_climb, expected_times_s_climb, - expected_altitudes_m_climb, abs_tolerance=atol_altitude, rel_tolerance=rtol) - - warn_timeseries_near_equal( - times_climb, masses_climb, expected_times_s_climb, - expected_masses_kg_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, ranges_climb, expected_times_s_climb, - expected_ranges_m_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, velocities_climb, expected_times_s_climb, - expected_velocities_ms_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, thrusts_climb, expected_times_s_climb, - expected_thrusts_N_climb, abs_tolerance=atol, rel_tolerance=rtol) - - # FLIGHT PATH - # CRUISE - warn_timeseries_near_equal( - times_cruise, altitudes_cruise, expected_times_s_cruise, - expected_altitudes_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, masses_cruise, expected_times_s_cruise, - expected_masses_kg_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, ranges_cruise, expected_times_s_cruise, - expected_ranges_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, velocities_cruise, expected_times_s_cruise, - expected_velocities_ms_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, thrusts_cruise, expected_times_s_cruise, - expected_thrusts_N_cruise, abs_tolerance=atol, rel_tolerance=rtol) - - # FLIGHT PATH - # DESCENT - warn_timeseries_near_equal( - times_descent, altitudes_descent, expected_times_s_descent, - expected_altitudes_m_descent, abs_tolerance=atol_altitude, - rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, masses_descent, expected_times_s_descent, - expected_masses_kg_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, ranges_descent, expected_times_s_descent, - expected_ranges_m_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, velocities_descent, expected_times_s_descent, - expected_velocities_ms_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, thrusts_descent, expected_times_s_descent, - expected_thrusts_N_descent, abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == '__main__': - z = ProblemPhaseTestCase() - z.bench_test_full_mission_large_single_aisle_2() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index c195cff92..64b84c3dd 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -18,13 +18,13 @@ from aviary.mission.flops_based.phases.build_takeoff import Takeoff from aviary.utils.functions import set_aviary_initial_values from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.utils.functions import get_path from aviary.validation_cases.validation_tests import get_flops_inputs from aviary.variable_info.functions import setup_trajectory_params from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables_in import VariablesIn +from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.subsystems.premission import CorePreMission from aviary.interface.default_phase_info.flops import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload @@ -92,8 +92,6 @@ def run_trajectory(sim=True): alt_f_climb = 35000.0*_units.foot # m mass_i_climb = 131000*_units.lb # kg mass_f_climb = 126000*_units.lb # kg - v_i_climb = 198.44*_units.knot # m/s - v_f_climb = 455.49*_units.knot # m/s # initial mach set to lower value so it can intersect with takeoff end mach # mach_i_climb = 0.3 mach_i_climb = 0.2 @@ -110,10 +108,7 @@ def run_trajectory(sim=True): alt_max_cruise = 35000*_units.foot # m mass_i_cruise = 126000*_units.lb # kg mass_f_cruise = 102000*_units.lb # kg - v_i_cruise = 455.49*_units.knot # m/s - v_f_cruise = 455.49*_units.knot # m/s - mach_min_cruise = 0.79 - mach_max_cruise = 0.79 + cruise_mach = 0.79 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 @@ -124,8 +119,6 @@ def run_trajectory(sim=True): # final altitude set to 35 to ensure landing is feasible point # alt_f_descent = 0*_units.foot alt_f_descent = 35*_units.foot - v_i_descent = 455.49*_units.knot - v_f_descent = 198.44*_units.knot mach_i_descent = 0.79 mach_f_descent = 0.3 mass_i_descent = 102000*_units.pound @@ -171,7 +164,7 @@ def run_trajectory(sim=True): num_segments=num_segments_descent, order=3, compressed=True, segment_ends=descent_seg_ends) - climb_options = Climb( + climb_options = EnergyPhase( 'test_climb', user_options=AviaryValues({ 'initial_altitude': (alt_i_climb, 'm'), @@ -179,31 +172,30 @@ def run_trajectory(sim=True): 'initial_mach': (mach_i_climb, 'unitless'), 'final_mach': (mach_f_climb, 'unitless'), 'fix_initial': (False, 'unitless'), - 'fix_range': (False, 'unitless'), 'input_initial': (True, 'unitless'), + 'use_polynomial_control': (False, 'unitless'), }), core_subsystems=default_mission_subsystems, subsystem_options={'core_aerodynamics': {'method': 'computed'}}, transcription=transcription_climb, ) - cruise_options = Cruise( + cruise_options = EnergyPhase( 'test_cruise', user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), + 'initial_altitude': (alt_min_cruise, 'm'), + 'final_altitude': (alt_max_cruise, 'm'), + 'initial_mach': (cruise_mach, 'unitless'), + 'final_mach': (cruise_mach, 'unitless'), 'required_available_climb_rate': (300, 'ft/min'), 'fix_initial': (False, 'unitless'), - 'fix_final': (False, 'unitless'), }), core_subsystems=default_mission_subsystems, subsystem_options={'core_aerodynamics': {'method': 'computed'}}, transcription=transcription_cruise, ) - descent_options = Descent( + descent_options = EnergyPhase( 'test_descent', user_options=AviaryValues({ 'final_altitude': (alt_f_descent, 'm'), @@ -211,7 +203,7 @@ def run_trajectory(sim=True): 'initial_mach': (mach_i_descent, 'unitless'), 'final_mach': (mach_f_descent, 'unitless'), 'fix_initial': (False, 'unitless'), - 'fix_range': (True, 'unitless'), + 'use_polynomial_control': (False, 'unitless'), }), core_subsystems=default_mission_subsystems, subsystem_options={'core_aerodynamics': {'method': 'computed'}}, @@ -277,78 +269,27 @@ def run_trajectory(sim=True): traj.add_phase('descent', descent) - try: - climb.timeseries_options['use_prefix'] = True - cruise.timeseries_options['use_prefix'] = True - descent.timeseries_options['use_prefix'] = True - except KeyError: - pass - prob.model.add_subsystem( 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=['mission:*']) - traj.link_phases(["climb", "cruise"], ["time", "altitude", - "velocity", "mass", "range"], connected=strong_couple) - traj.link_phases(["cruise", "descent"], ["time", "altitude", - "velocity", "mass", "range"], connected=strong_couple) + traj.link_phases(["climb", "cruise", "descent"], [ + "time", "mass", "range"], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) ################################## # Connect in Takeoff and Landing # ################################## - - prob.model.add_subsystem( - "takeoff_constraints", - om.ExecComp( - [ - "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", - "takeoff_vel_con=takeoff_vel-climb_start_vel", - "takeoff_alt_con=takeoff_alt-climb_start_alt" - ], - takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, - climb_start_mass={'units': 'lbm'}, - takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, - takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, - climb_start_vel={'units': 'm/s'}, - takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, - climb_start_alt={'units': 'ft'} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Takeoff.FINAL_MASS), - ("takeoff_range", Mission.Takeoff.GROUND_DISTANCE), - ("takeoff_vel", Mission.Takeoff.FINAL_VELOCITY), - ("takeoff_alt", Mission.Takeoff.FINAL_ALTITUDE), - ], - promotes_outputs=["takeoff_mass_con", "takeoff_range_con", - "takeoff_vel_con", "takeoff_alt_con"], - ) - - prob.model.connect('traj.climb.states:mass', - 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', - 'takeoff_constraints.climb_start_range', src_indices=[0]) - prob.model.connect('traj.climb.states:velocity', - 'takeoff_constraints.climb_start_vel', src_indices=[0]) - prob.model.connect('traj.climb.states:altitude', - 'takeoff_constraints.climb_start_alt', src_indices=[0]) - prob.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, 'traj.climb.initial_states:range') - prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, - 'traj.climb.initial_states:velocity') - prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'traj.climb.initial_states:altitude') prob.model.connect('traj.descent.states:mass', Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) # TODO: approach velocity should likely be connected - prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE, + prob.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE, src_indices=[-1]) ########################## @@ -443,60 +384,41 @@ def run_trajectory(sim=True): 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.states:altitude', climb.interp( - 'altitude', ys=[alt_i_climb, alt_f_climb]), units='m') - # prob.set_val('traj.climb.states:velocity', climb.interp('velocity', ys=[170, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:velocity', climb.interp( - 'velocity', ys=[v_i_climb, v_f_climb]), units='m/s') + prob.set_val('traj.climb.controls:altitude', climb.interp( + Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') + prob.set_val( + 'traj.climb.controls:mach', climb.interp( + Dynamic.Mission.MACH, ys=[mach_i_climb, mach_f_climb]), units='unitless') prob.set_val('traj.climb.states:mass', climb.interp( - 'mass', ys=[mass_i_climb, mass_f_climb]), units='kg') + Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:range', climb.interp( - 'range', ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp('velocity_rate', ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp('throttle', ys=[0.5, 0.5]), - units=None) + Dynamic.Mission.RANGE, 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.states:altitude', cruise.interp( - 'altitude', ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - 'velocity', ys=[v_i_cruise, v_f_cruise]), units='m/s') + prob.set_val('traj.cruise.polynomial_controls:altitude', cruise.interp( + Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') + prob.set_val( + 'traj.cruise.polynomial_controls:mach', cruise.interp( + Dynamic.Mission.MACH, ys=[cruise_mach, cruise_mach]), units='unitless') prob.set_val('traj.cruise.states:mass', cruise.interp( - 'mass', ys=[mass_i_cruise, mass_f_cruise]), units='kg') + Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:range', cruise.interp( - 'range', ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp('velocity_rate', ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp('throttle', ys=[0.5, 0.5]), - units=None) + Dynamic.Mission.RANGE, 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.states:altitude', descent.interp( - 'altitude', ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - 'velocity', ys=[v_i_descent, v_f_descent]), units='m/s') + prob.set_val('traj.descent.controls:altitude', descent.interp( + Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') + prob.set_val( + 'traj.descent.controls:mach', descent.interp( + Dynamic.Mission.MACH, ys=[mach_i_descent, mach_f_descent]), units='unitless') prob.set_val('traj.descent.states:mass', descent.interp( - 'mass', ys=[mass_i_descent, mass_f_descent]), units='kg') + Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:range', descent.interp( - 'range', ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp('velocity_rate', ys=[-0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp('throttle', ys=[0.0, 0.0]), - units=None) + Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') # Turn off solver printing so that the SNOPT output is readable. prob.set_solver_print(level=0) @@ -521,28 +443,28 @@ def bench_test_sizing_N3CC(self): times_climb = prob.get_val('traj.climb.timeseries.time', units='s') altitudes_climb = prob.get_val( - 'traj.climb.timeseries.states:altitude', units='m') - masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') + '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.range', units='m') velocities_climb = prob.get_val( - 'traj.climb.timeseries.states:velocity', units='m/s') + '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.states:altitude', units='m') - masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') + '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.range', units='m') velocities_cruise = prob.get_val( - 'traj.cruise.timeseries.states:velocity', units='m/s') + '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.states:altitude', units='m') - masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') + '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.range', units='m') velocities_descent = prob.get_val( - 'traj.descent.timeseries.states:velocity', units='m/s') + 'traj.descent.timeseries.velocity', units='m/s') thrusts_descent = prob.get_val( 'traj.descent.timeseries.thrust_net_total', units='N') From e0af92b75868645f09b5da7a2548c7a8a1ed5e91 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Tue, 9 Jan 2024 11:52:04 -0600 Subject: [PATCH 017/111] Updating docs --- aviary/api.py | 1 + .../getting_started/onboarding_level2.ipynb | 2511 ++++++++++++++++- .../getting_started/onboarding_level3.ipynb | 1328 ++++----- 3 files changed, 2958 insertions(+), 882 deletions(-) diff --git a/aviary/api.py b/aviary/api.py index a7e55c7a5..4dd11f0fb 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -86,6 +86,7 @@ # Phase builders from aviary.mission.flops_based.phases.phase_builder_base import PhaseBuilderBase # note that this is only for simplified right now +from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase as HeightEnergyPhaseBuilder from aviary.mission.flops_based.phases.build_landing import Landing as HeightEnergyLandingPhaseBuilder # note that this is only for simplified right now from aviary.mission.flops_based.phases.build_takeoff import Takeoff as HeightEnergyTakeoffPhaseBuilder diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index a0db18448..64557fd83 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -71,10 +71,770 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "fe134855", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/subsystems/propulsion/engine_deck.py:198: UserWarning: is a required option for EngineDecks, but has not been specified for EngineDeck . The default value will be used.\n", + " warnings.warn(\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/group.py:333: PromotionWarning:: Setting input defaults for input 'mission:takeoff:ascent_duration' which override previously set defaults for ['auto', 'prom', 'src_shape', 'val'].\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.speeds' : d(*)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(max_mach)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(density_ratio)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(V9)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.factors' : d(aircraft:wing:ultimate_load_factor)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.fixed_mass.params' : d(c_gear_loc)/d(aircraft:landing_gear:main_gear_location): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_useful_load)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_equipment_mass)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'groundroll': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.eoms' : d(alpha_rate)/d(('*',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.rotation': initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'rotation': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.rotation.rhs_all.eoms' : d(alpha_rate)/d(('*',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'ascent': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.accel': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'accel': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.climb1': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'climb1': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.climb2': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'climb2': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.desc1': initial_bounds, initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'desc1': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.desc2': initial_bounds, initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'desc2': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:engine:scale_factor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.accel: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.accel' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.accel.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.accel.nonlinear_solver to override.\n", + " Setting `traj.phases.accel.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.accel.linear_solver to override.\n", + " Set `traj.phases.accel.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.ascent' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.ascent.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.ascent.nonlinear_solver to override.\n", + " Setting `traj.phases.ascent.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.ascent.linear_solver to override.\n", + " Set `traj.phases.ascent.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb1: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb1' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb1.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb1.nonlinear_solver to override.\n", + " Setting `traj.phases.climb1.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb1.linear_solver to override.\n", + " Set `traj.phases.climb1.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb2: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb2' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb2.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb2.nonlinear_solver to override.\n", + " Setting `traj.phases.climb2.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb2.linear_solver to override.\n", + " Set `traj.phases.climb2.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.desc1: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.desc1' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.desc1.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.desc1.nonlinear_solver to override.\n", + " Setting `traj.phases.desc1.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.desc1.linear_solver to override.\n", + " Set `traj.phases.desc1.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.desc2: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.desc2' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.desc2.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.desc2.nonlinear_solver to override.\n", + " Setting `traj.phases.desc2.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.desc2.linear_solver to override.\n", + " Set `traj.phases.desc2.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.rotation' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.rotation.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.rotation.nonlinear_solver to override.\n", + " Setting `traj.phases.rotation.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.rotation.linear_solver to override.\n", + " Set `traj.phases.rotation.options[\"auto_solvers\"] = False` to disable this behavior.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Constraint Report [traj] ---\n", + " --- groundroll ---\n", + " None\n", + " --- rotation ---\n", + " [final] 0.0000e+00 == normal_force [lbf]\n", + " --- ascent ---\n", + " [final] 5.0000e+02 == altitude [ft]\n", + " [path] 0.0000e+00 <= load_factor <= 1.1000e+00 [unitless]\n", + " [path] 0.0000e+00 <= fuselage_pitch <= 1.5000e+01 [deg]\n", + " --- accel ---\n", + " [final] 2.5000e+02 == EAS [kn]\n", + " --- climb1 ---\n", + " [final] 1.0000e+04 == altitude [ft]\n", + " --- climb2 ---\n", + " [final] 3.7500e+04 == altitude [ft]\n", + " [final] 1.0000e-01 <= altitude_rate [ft/min]\n", + " [final] 8.0000e-01 == mach [unitless]\n", + " --- cruise ---\n", + " None\n", + " --- desc1 ---\n", + " [final] 1.0000e+04 == altitude [ft]\n", + " --- desc2 ---\n", + " [final] 1.0000e+03 == altitude [ft]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'landing.aero_app.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'landing.aero_td.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.ascent.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.rotation.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, aviary_history.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "Model viewer data has already been recorded for Driver.\n", + "\n", + "Coloring for 'event_xform' (class ExecComp)\n", + "\n", + "Jacobian shape: (2, 4) (75.00% nonzero)\n", + "FWD solves: 3 REV solves: 0\n", + "Total colors vs. total size: 3 vs 4 (25.00% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 0.0003 sec\n", + "Time to compute coloring: 0.0021 sec\n", + "Memory to compute coloring: 0.0391 MB\n", + "Full total jacobian was computed 3 times, taking 1.928283 seconds.\n", + "Total jacobian shape: (232, 203) \n", + "\n", + "\n", + "Jacobian shape: (232, 203) (7.47% nonzero)\n", + "FWD solves: 45 REV solves: 0\n", + "Total colors vs. total size: 45 vs 203 (77.83% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 1.9283 sec\n", + "Time to compute coloring: 0.1703 sec\n", + "Memory to compute coloring: 0.6680 MB\n", + "Coloring created on: 2024-01-09 11:24:16\n", + "\n", + "List of user-set options:\n", + "\n", + " Name Value used\n", + " alpha_for_y = safer-min-dual-infeas yes\n", + " file_print_level = 5 yes\n", + " hessian_approximation = limited-memory yes\n", + " linear_solver = mumps yes\n", + " max_iter = 0 yes\n", + " mu_init = 1e-05 yes\n", + " mu_strategy = monotone yes\n", + " nlp_scaling_method = gradient-based yes\n", + " output_file = reports/problem/IPOPT.out yes\n", + " print_level = 5 yes\n", + " print_user_options = yes yes\n", + " sb = yes yes\n", + " tol = 1e-06 yes\n", + "This is Ipopt version 3.14.12, running with linear solver MUMPS 5.2.1.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2343\n", + "Number of nonzeros in inequality constraint Jacobian.: 568\n", + "Number of nonzeros in Lagrangian Hessian.............: 0\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/total_jac.py:1759: DerivativesWarning:Constraints or objectives [('traj.phases.climb2.timeseries.timeseries_comp.mach', inds=[(11, 0)])] cannot be impacted by the design variables of the problem.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of variables............................: 203\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 203\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 198\n", + "Total number of inequality constraints...............: 33\n", + " inequality constraints with only lower bounds: 1\n", + " inequality constraints with lower and upper bounds: 32\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 5.2731333e+00 1.30e+01 1.75e+01 -5.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + "\n", + "Number of Iterations....: 0\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 5.2731333333333330e+00 5.2731333333333330e+00\n", + "Dual infeasibility......: 1.7500000000000000e+01 1.7500000000000000e+01\n", + "Constraint violation....: 3.4411291654724301e+00 1.2999999999999952e+01\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 7.1428571428571420e+15 7.1428571428571420e+15\n", + "Overall NLP error.......: 7.1428571428571420e+15 7.1428571428571420e+15\n", + "\n", + "\n", + "Number of objective function evaluations = 1\n", + "Number of objective gradient evaluations = 1\n", + "Number of equality constraint evaluations = 1\n", + "Number of inequality constraint evaluations = 1\n", + "Number of equality constraint Jacobian evaluations = 1\n", + "Number of inequality constraint Jacobian evaluations = 1\n", + "Number of Lagrangian Hessian evaluations = 0\n", + "Total seconds in IPOPT = 2.265\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "\n", + "\n", + "Optimization Problem -- Optimization using pyOpt_sparse\n", + "================================================================================\n", + " Objective Function: _objfunc\n", + "\n", + " Solution: \n", + "--------------------------------------------------------------------------------\n", + " Total Time: 2.2837\n", + " User Objective Time : 0.2671\n", + " User Sensitivity Time : 1.9735\n", + " Interface Time : 0.0132\n", + " Opt Solver Time: 0.0298\n", + " Calls to Objective Function : 2\n", + " Calls to Sens Function : 2\n", + "\n", + "\n", + " Objectives\n", + " Index Name Value\n", + " 0 mission:objectives:fuel 5.273133E+00\n", + "\n", + " Variables (c - continuous, i - integer, d - discrete)\n", + " Index Name Type Lower Bound Value Upper Bound Status\n", + " 0 mission:takeoff:ascent_t_initial_0 c 0.000000E+00 3.333333E-01 3.333333E+00 \n", + " 1 mission:takeoff:ascent_duration_0 c 1.000000E-01 2.500000E+00 1.000000E+02 \n", + " 2 tau_gear_0 c 1.000000E-02 2.000000E-01 1.000000E+00 \n", + " 3 tau_flaps_0 c 1.000000E-02 9.000000E-01 1.000000E+00 \n", + " 4 mission:design:gross_mass_0 c 5.714286E-05 1.002286E+00 2.285714E+00 \n", + " 5 mission:summary:gross_mass_0 c 5.714286E-05 1.002286E+00 2.285714E+00 \n", + " 6 traj.accel.t_duration_0 c 1.000000E-03 1.300000E-02 2.000000E-01 \n", + " 7 traj.accel.states:TAS_0 c 0.000000E+00 5.807832E-01 1.200000E+00 \n", + " 8 traj.accel.states:TAS_1 c 0.000000E+00 8.992168E-01 1.200000E+00 \n", + " 9 traj.accel.states:TAS_2 c 0.000000E+00 1.000000E+00 1.200000E+00 \n", + " 10 traj.accel.states:mass_0 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 11 traj.accel.states:mass_1 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 12 traj.accel.states:mass_2 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 13 traj.accel.states:distance_0 c 0.000000E+00 3.291577E-01 3.000000E+01 \n", + " 14 traj.accel.states:distance_1 c 0.000000E+00 4.460254E-01 3.000000E+01 \n", + " 15 traj.accel.states:distance_2 c 0.000000E+00 6.072791E-01 3.000000E+01 \n", + " 16 traj.accel.states:distance_3 c 0.000000E+00 6.583153E-01 3.000000E+01 \n", + " 17 traj.ascent.states:flight_path_angle_0 c -1.000000E+01 1.239362E-02 2.000000E+01 \n", + " 18 traj.ascent.states:flight_path_angle_1 c -1.000000E+01 2.949428E-02 2.000000E+01 \n", + " 19 traj.ascent.states:flight_path_angle_2 c -1.000000E+01 3.490659E-02 2.000000E+01 \n", + " 20 traj.ascent.states:flight_path_angle_3 c -1.000000E+01 4.730020E-02 2.000000E+01 \n", + " 21 traj.ascent.states:flight_path_angle_4 c -1.000000E+01 6.440087E-02 2.000000E+01 \n", + " 22 traj.ascent.states:flight_path_angle_5 c -1.000000E+01 6.981317E-02 2.000000E+01 \n", + " 23 traj.ascent.states:flight_path_angle_6 c -1.000000E+01 8.220679E-02 2.000000E+01 \n", + " 24 traj.ascent.states:flight_path_angle_7 c -1.000000E+01 9.930745E-02 2.000000E+01 \n", + " 25 traj.ascent.states:flight_path_angle_8 c -1.000000E+01 1.047198E-01 2.000000E+01 \n", + " 26 traj.ascent.states:flight_path_angle_9 c -1.000000E+01 1.171134E-01 2.000000E+01 \n", + " 27 traj.ascent.states:flight_path_angle_10 c -1.000000E+01 1.342140E-01 2.000000E+01 \n", + " 28 traj.ascent.states:flight_path_angle_11 c -1.000000E+01 1.396263E-01 2.000000E+01 \n", + " 29 traj.ascent.states:altitude_0 c 0.000000E+00 4.438138E-02 7.000000E-01 \n", + " 30 traj.ascent.states:altitude_1 c 0.000000E+00 1.056186E-01 7.000000E-01 \n", + " 31 traj.ascent.states:altitude_2 c 0.000000E+00 1.250000E-01 7.000000E-01 \n", + " 32 traj.ascent.states:altitude_3 c 0.000000E+00 1.693814E-01 7.000000E-01 \n", + " 33 traj.ascent.states:altitude_4 c 0.000000E+00 2.306186E-01 7.000000E-01 \n", + " 34 traj.ascent.states:altitude_5 c 0.000000E+00 2.500000E-01 7.000000E-01 \n", + " 35 traj.ascent.states:altitude_6 c 0.000000E+00 2.943814E-01 7.000000E-01 \n", + " 36 traj.ascent.states:altitude_7 c 0.000000E+00 3.556186E-01 7.000000E-01 \n", + " 37 traj.ascent.states:altitude_8 c 0.000000E+00 3.750000E-01 7.000000E-01 \n", + " 38 traj.ascent.states:altitude_9 c 0.000000E+00 4.193814E-01 7.000000E-01 \n", + " 39 traj.ascent.states:altitude_10 c 0.000000E+00 4.806186E-01 7.000000E-01 \n", + " 40 traj.ascent.states:altitude_11 c 0.000000E+00 5.000000E-01 7.000000E-01 \n", + " 41 traj.ascent.states:TAS_0 c 0.000000E+00 7.655335E-01 3.500000E+00 \n", + " 42 traj.ascent.states:TAS_1 c 0.000000E+00 7.869665E-01 3.500000E+00 \n", + " 43 traj.ascent.states:TAS_2 c 0.000000E+00 7.937500E-01 3.500000E+00 \n", + " 44 traj.ascent.states:TAS_3 c 0.000000E+00 8.092835E-01 3.500000E+00 \n", + " 45 traj.ascent.states:TAS_4 c 0.000000E+00 8.307165E-01 3.500000E+00 \n", + " 46 traj.ascent.states:TAS_5 c 0.000000E+00 8.375000E-01 3.500000E+00 \n", + " 47 traj.ascent.states:TAS_6 c 0.000000E+00 8.530335E-01 3.500000E+00 \n", + " 48 traj.ascent.states:TAS_7 c 0.000000E+00 8.744665E-01 3.500000E+00 \n", + " 49 traj.ascent.states:TAS_8 c 0.000000E+00 8.812500E-01 3.500000E+00 \n", + " 50 traj.ascent.states:TAS_9 c 0.000000E+00 8.967835E-01 3.500000E+00 \n", + " 51 traj.ascent.states:TAS_10 c 0.000000E+00 9.182165E-01 3.500000E+00 \n", + " 52 traj.ascent.states:TAS_11 c 0.000000E+00 9.250000E-01 3.500000E+00 \n", + " 53 traj.ascent.states:mass_0 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 54 traj.ascent.states:mass_1 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 55 traj.ascent.states:mass_2 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 56 traj.ascent.states:mass_3 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 57 traj.ascent.states:mass_4 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 58 traj.ascent.states:mass_5 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 59 traj.ascent.states:mass_6 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 60 traj.ascent.states:mass_7 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 61 traj.ascent.states:mass_8 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 62 traj.ascent.states:mass_9 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 63 traj.ascent.states:mass_10 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 64 traj.ascent.states:mass_11 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 65 traj.ascent.states:distance_0 c 0.000000E+00 4.532577E-01 1.500000E+00 \n", + " 66 traj.ascent.states:distance_1 c 0.000000E+00 5.267423E-01 1.500000E+00 \n", + " 67 traj.ascent.states:distance_2 c 0.000000E+00 5.500000E-01 1.500000E+00 \n", + " 68 traj.ascent.states:distance_3 c 0.000000E+00 6.032577E-01 1.500000E+00 \n", + " 69 traj.ascent.states:distance_4 c 0.000000E+00 6.767423E-01 1.500000E+00 \n", + " 70 traj.ascent.states:distance_5 c 0.000000E+00 7.000000E-01 1.500000E+00 \n", + " 71 traj.ascent.states:distance_6 c 0.000000E+00 7.532577E-01 1.500000E+00 \n", + " 72 traj.ascent.states:distance_7 c 0.000000E+00 8.267423E-01 1.500000E+00 \n", + " 73 traj.ascent.states:distance_8 c 0.000000E+00 8.500000E-01 1.500000E+00 \n", + " 74 traj.ascent.states:distance_9 c 0.000000E+00 9.032577E-01 1.500000E+00 \n", + " 75 traj.ascent.states:distance_10 c 0.000000E+00 9.767423E-01 1.500000E+00 \n", + " 76 traj.ascent.states:distance_11 c 0.000000E+00 1.000000E+00 1.500000E+00 \n", + " 77 traj.ascent.controls:alpha_0 c -6.000000E+00 5.000000E-01 6.000000E+00 \n", + " 78 traj.ascent.controls:alpha_1 c -6.000000E+00 4.822474E-01 6.000000E+00 \n", + " 79 traj.ascent.controls:alpha_2 c -6.000000E+00 4.577526E-01 6.000000E+00 \n", + " 80 traj.ascent.controls:alpha_3 c -6.000000E+00 4.500000E-01 6.000000E+00 \n", + " 81 traj.ascent.controls:alpha_4 c -6.000000E+00 4.322474E-01 6.000000E+00 \n", + " 82 traj.ascent.controls:alpha_5 c -6.000000E+00 4.077526E-01 6.000000E+00 \n", + " 83 traj.ascent.controls:alpha_6 c -6.000000E+00 4.000000E-01 6.000000E+00 \n", + " 84 traj.ascent.controls:alpha_7 c -6.000000E+00 3.822474E-01 6.000000E+00 \n", + " 85 traj.ascent.controls:alpha_8 c -6.000000E+00 3.577526E-01 6.000000E+00 \n", + " 86 traj.ascent.controls:alpha_9 c -6.000000E+00 3.500000E-01 6.000000E+00 \n", + " 87 traj.ascent.controls:alpha_10 c -6.000000E+00 3.322474E-01 6.000000E+00 \n", + " 88 traj.ascent.controls:alpha_11 c -6.000000E+00 3.077526E-01 6.000000E+00 \n", + " 89 traj.climb1.t_duration_0 c 3.000000E-02 1.200000E-01 3.000000E-01 \n", + " 90 traj.climb1.states:altitude_0 c 4.000000E-02 3.872985E-01 1.100000E+00 \n", + " 91 traj.climb1.states:altitude_1 c 4.000000E-02 8.527015E-01 1.100000E+00 \n", + " 92 traj.climb1.states:altitude_2 c 4.000000E-02 1.000000E+00 1.100000E+00 \n", + " 93 traj.climb1.states:mass_0 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 94 traj.climb1.states:mass_1 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 95 traj.climb1.states:mass_2 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 96 traj.climb1.states:distance_0 c 0.000000E+00 7.966287E-01 5.000000E+01 \n", + " 97 traj.climb1.states:distance_1 c 0.000000E+00 1.441643E+00 5.000000E+01 \n", + " 98 traj.climb1.states:distance_2 c 0.000000E+00 1.645788E+00 5.000000E+01 \n", + " 99 traj.climb2.t_duration_0 c 4.000000E-02 2.600000E-01 3.400000E+00 \n", + " 100 traj.climb2.states:altitude_0 c 3.000000E-01 4.418211E-01 1.333333E+00 \n", + " 101 traj.climb2.states:altitude_1 c 3.000000E-01 5.915122E-01 1.333333E+00 \n", + " 102 traj.climb2.states:altitude_2 c 3.000000E-01 6.388889E-01 1.333333E+00 \n", + " 103 traj.climb2.states:altitude_3 c 3.000000E-01 7.473767E-01 1.333333E+00 \n", + " 104 traj.climb2.states:altitude_4 c 3.000000E-01 8.970677E-01 1.333333E+00 \n", + " 105 traj.climb2.states:altitude_5 c 3.000000E-01 9.444444E-01 1.333333E+00 \n", + " 106 traj.climb2.states:altitude_6 c 3.000000E-01 1.052932E+00 1.333333E+00 \n", + " 107 traj.climb2.states:altitude_7 c 3.000000E-01 1.202623E+00 1.333333E+00 \n", + " 108 traj.climb2.states:altitude_8 c 3.000000E-01 1.250000E+00 1.333333E+00 \n", + " 109 traj.climb2.states:mass_0 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 110 traj.climb2.states:mass_1 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 111 traj.climb2.states:mass_2 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 112 traj.climb2.states:mass_3 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 113 traj.climb2.states:mass_4 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 114 traj.climb2.states:mass_5 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 115 traj.climb2.states:mass_6 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 116 traj.climb2.states:mass_7 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 117 traj.climb2.states:mass_8 c 0.000000E+00 1.146064E+00 6.666667E+15 \n", + " 118 traj.climb2.states:distance_0 c 2.000000E-02 3.681136E-02 2.000000E+00 \n", + " 119 traj.climb2.states:distance_1 c 2.000000E-02 4.218648E-02 2.000000E+00 \n", + " 120 traj.climb2.states:distance_2 c 2.000000E-02 4.388769E-02 2.000000E+00 \n", + " 121 traj.climb2.states:distance_3 c 2.000000E-02 4.778328E-02 2.000000E+00 \n", + " 122 traj.climb2.states:distance_4 c 2.000000E-02 5.315840E-02 2.000000E+00 \n", + " 123 traj.climb2.states:distance_5 c 2.000000E-02 5.485961E-02 2.000000E+00 \n", + " 124 traj.climb2.states:distance_6 c 2.000000E-02 5.875520E-02 2.000000E+00 \n", + " 125 traj.climb2.states:distance_7 c 2.000000E-02 6.413033E-02 2.000000E+00 \n", + " 126 traj.climb2.states:distance_8 c 2.000000E-02 6.583153E-02 2.000000E+00 \n", + " 127 traj.cruise.t_initial_0 c 1.000000E-01 1.714810E+00 5.000000E+00 \n", + " 128 traj.cruise.t_duration_0 c -1.000000E+00 -7.000000E-01 -2.000000E-04 \n", + " 129 traj.desc1.t_duration_0 c 3.000000E-01 5.000000E-01 9.000000E-01 \n", + " 130 traj.desc1.states:altitude_0 c 3.333333E-02 1.141512E+00 1.333333E+00 \n", + " 131 traj.desc1.states:altitude_1 c 3.333333E-02 9.918211E-01 1.333333E+00 \n", + " 132 traj.desc1.states:altitude_2 c 3.333333E-02 9.444444E-01 1.333333E+00 \n", + " 133 traj.desc1.states:altitude_3 c 3.333333E-02 8.359566E-01 1.333333E+00 \n", + " 134 traj.desc1.states:altitude_4 c 3.333333E-02 6.862656E-01 1.333333E+00 \n", + " 135 traj.desc1.states:altitude_5 c 3.333333E-02 6.388889E-01 1.333333E+00 \n", + " 136 traj.desc1.states:altitude_6 c 3.333333E-02 5.304011E-01 1.333333E+00 \n", + " 137 traj.desc1.states:altitude_7 c 3.333333E-02 3.807100E-01 1.333333E+00 \n", + " 138 traj.desc1.states:altitude_8 c 3.333333E-02 3.333333E-01 1.333333E+00 \n", + " 139 traj.desc1.states:mass_0 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 140 traj.desc1.states:mass_1 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 141 traj.desc1.states:mass_2 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 142 traj.desc1.states:mass_3 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 143 traj.desc1.states:mass_4 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 144 traj.desc1.states:mass_5 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 145 traj.desc1.states:mass_6 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 146 traj.desc1.states:mass_7 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 147 traj.desc1.states:mass_8 c 0.000000E+00 9.714286E-01 7.142857E+15 \n", + " 148 traj.desc1.states:distance_0 c 8.163265E-01 9.247340E-01 1.360544E+00 \n", + " 149 traj.desc1.states:distance_1 c 8.163265E-01 9.312660E-01 1.360544E+00 \n", + " 150 traj.desc1.states:distance_2 c 8.163265E-01 9.333333E-01 1.360544E+00 \n", + " 151 traj.desc1.states:distance_3 c 8.163265E-01 9.380673E-01 1.360544E+00 \n", + " 152 traj.desc1.states:distance_4 c 8.163265E-01 9.445993E-01 1.360544E+00 \n", + " 153 traj.desc1.states:distance_5 c 8.163265E-01 9.466667E-01 1.360544E+00 \n", + " 154 traj.desc1.states:distance_6 c 8.163265E-01 9.514007E-01 1.360544E+00 \n", + " 155 traj.desc1.states:distance_7 c 8.163265E-01 9.579327E-01 1.360544E+00 \n", + " 156 traj.desc1.states:distance_8 c 8.163265E-01 9.600000E-01 1.360544E+00 \n", + " 157 traj.desc2.t_duration_0 c 2.000000E-01 1.000000E+00 1.000000E+01 \n", + " 158 traj.desc2.states:altitude_0 c -5.555556E-02 9.269457E-01 1.111111E+00 \n", + " 159 traj.desc2.states:altitude_1 c -5.555556E-02 7.692339E-01 1.111111E+00 \n", + " 160 traj.desc2.states:altitude_2 c -5.555556E-02 5.586715E-01 1.111111E+00 \n", + " 161 traj.desc2.states:altitude_3 c -5.555556E-02 3.369847E-01 1.111111E+00 \n", + " 162 traj.desc2.states:altitude_4 c -5.555556E-02 1.480786E-01 1.111111E+00 \n", + " 163 traj.desc2.states:altitude_5 c -5.555556E-02 2.931643E-02 1.111111E+00 \n", + " 164 traj.desc2.states:altitude_6 c -5.555556E-02 0.000000E+00 1.111111E+00 \n", + " 165 traj.desc2.states:mass_0 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 166 traj.desc2.states:mass_1 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 167 traj.desc2.states:mass_2 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 168 traj.desc2.states:mass_3 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 169 traj.desc2.states:mass_4 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 170 traj.desc2.states:mass_5 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 171 traj.desc2.states:mass_6 c 0.000000E+00 9.066667E-01 6.666667E+15 \n", + " 172 traj.desc2.states:distance_0 c 0.000000E+00 1.011068E+00 1.428571E+00 \n", + " 173 traj.desc2.states:distance_1 c 0.000000E+00 1.017692E+00 1.428571E+00 \n", + " 174 traj.desc2.states:distance_2 c 0.000000E+00 1.026536E+00 1.428571E+00 \n", + " 175 traj.desc2.states:distance_3 c 0.000000E+00 1.035847E+00 1.428571E+00 \n", + " 176 traj.desc2.states:distance_4 c 0.000000E+00 1.043781E+00 1.428571E+00 \n", + " 177 traj.desc2.states:distance_5 c 0.000000E+00 1.048769E+00 1.428571E+00 \n", + " 178 traj.desc2.states:distance_6 c 0.000000E+00 1.050000E+00 1.428571E+00 \n", + " 179 traj.groundroll.t_duration_0 c 2.000000E-02 8.000000E-01 2.000000E+00 \n", + " 180 traj.groundroll.states:TAS_0 c 0.000000E+00 3.390025E-01 6.666667E+00 \n", + " 181 traj.groundroll.states:TAS_1 c 0.000000E+00 8.061495E-01 6.666667E+00 \n", + " 182 traj.groundroll.states:TAS_2 c 0.000000E+00 9.540000E-01 6.666667E+00 \n", + " 183 traj.groundroll.states:mass_0 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 184 traj.groundroll.states:mass_1 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 185 traj.groundroll.states:mass_2 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 186 traj.groundroll.states:mass_3 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 187 traj.groundroll.states:distance_0 c 0.000000E+00 1.183503E-01 3.333333E+00 \n", + " 188 traj.groundroll.states:distance_1 c 0.000000E+00 2.816497E-01 3.333333E+00 \n", + " 189 traj.groundroll.states:distance_2 c 0.000000E+00 3.333333E-01 3.333333E+00 \n", + " 190 traj.rotation.t_duration_0 c 2.000000E-02 1.000000E-01 2.000000E+00 \n", + " 191 traj.rotation.states:alpha_0 c 0.000000E+00 9.999990E-03 1.000000E+00 \n", + " 192 traj.rotation.states:alpha_1 c 0.000000E+00 9.999990E-03 1.000000E+00 \n", + " 193 traj.rotation.states:alpha_2 c 0.000000E+00 9.999990E-03 1.000000E+00 \n", + " 194 traj.rotation.states:TAS_0 c 0.000000E+00 1.454854E+00 1.000000E+01 \n", + " 195 traj.rotation.states:TAS_1 c 0.000000E+00 1.489146E+00 1.000000E+01 \n", + " 196 traj.rotation.states:TAS_2 c 0.000000E+00 1.500000E+00 1.000000E+01 \n", + " 197 traj.rotation.states:mass_0 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 198 traj.rotation.states:mass_1 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 199 traj.rotation.states:mass_2 c 0.000000E+00 1.157640E+00 6.666667E+15 \n", + " 200 traj.rotation.states:distance_0 c 0.000000E+00 7.587713E-01 2.000000E+00 \n", + " 201 traj.rotation.states:distance_1 c 0.000000E+00 7.900883E-01 2.000000E+00 \n", + " 202 traj.rotation.states:distance_2 c 0.000000E+00 8.000000E-01 2.000000E+00 \n", + "\n", + " Constraints (i - inequality, e - equality)\n", + " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", + " 0 h_fit.h_init_gear e 1.000000E+00 -1.200000E+01 1.000000E+00 E 9.00000E+100\n", + " 1 h_fit.h_init_flaps e 1.000000E+00 -6.250000E-01 1.000000E+00 E 9.00000E+100\n", + " 2 mission:constraints:range_residual e 0.000000E+00 4.547474E-14 0.000000E+00 9.00000E+100\n", + " 3 groundroll_boundary.TAS e 0.000000E+00 -2.184640E-02 0.000000E+00 E 9.00000E+100\n", + " 4 gtow_constraint.GTOW e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 5 link_taxi_groundroll.mass e 0.000000E+00 -1.545558E-01 0.000000E+00 E 9.00000E+100\n", + " 6 mission:constraints:mass_residual e 0.000000E+00 8.370367E-03 0.000000E+00 E 9.00000E+100\n", + " 7 traj.linkages.rotation:alpha_final|ascent:alpha_initial e 0.000000E+00 1.273344E-04 0.000000E+00 E 9.00000E+100\n", + " 8 traj.linkages.ascent:distance_final|accel:distance_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 9 traj.linkages.climb2:mass_final|cruise:mass_initial e 0.000000E+00 4.285400E-03 0.000000E+00 E 9.00000E+100\n", + " 10 traj.phases.accel->final_boundary_constraint->EAS e 1.000000E+00 9.927554E-01 1.000000E+00 E 9.00000E+100\n", + " 11 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 5.831548E-02 0.000000E+00 E 9.00000E+100\n", + " 12 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 5.874534E-02 0.000000E+00 E 9.00000E+100\n", + " 13 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 6.150213E-02 0.000000E+00 E 9.00000E+100\n", + " 14 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.596440E-04 0.000000E+00 E 9.00000E+100\n", + " 15 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.608753E-04 0.000000E+00 E 9.00000E+100\n", + " 16 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.626472E-04 0.000000E+00 E 9.00000E+100\n", + " 17 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 9.777328E-02 0.000000E+00 E 9.00000E+100\n", + " 18 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 8.943944E-02 0.000000E+00 E 9.00000E+100\n", + " 19 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 7.794045E-02 0.000000E+00 E 9.00000E+100\n", + " 20 traj.phases.ascent->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 21 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 3.242586E-01 0.000000E+00 E 9.00000E+100\n", + " 22 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 3.239934E-01 0.000000E+00 E 9.00000E+100\n", + " 23 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 3.153739E-01 0.000000E+00 E 9.00000E+100\n", + " 24 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 3.124580E-01 0.000000E+00 E 9.00000E+100\n", + " 25 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 3.058679E-01 0.000000E+00 E 9.00000E+100\n", + " 26 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.971450E-01 0.000000E+00 E 9.00000E+100\n", + " 27 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.944936E-01 0.000000E+00 E 9.00000E+100\n", + " 28 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.886166E-01 0.000000E+00 E 9.00000E+100\n", + " 29 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.809363E-01 0.000000E+00 E 9.00000E+100\n", + " 30 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.786055E-01 0.000000E+00 E 9.00000E+100\n", + " 31 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.734430E-01 0.000000E+00 E 9.00000E+100\n", + " 32 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.667064E-01 0.000000E+00 E 9.00000E+100\n", + " 33 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 6.250000E-02 0.000000E+00 E 9.00000E+100\n", + " 34 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 5.249183E-02 0.000000E+00 E 9.00000E+100\n", + " 35 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 3.801869E-02 0.000000E+00 E 9.00000E+100\n", + " 36 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 3.327824E-02 0.000000E+00 E 9.00000E+100\n", + " 37 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 2.213497E-02 0.000000E+00 E 9.00000E+100\n", + " 38 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 6.104057E-03 0.000000E+00 E 9.00000E+100\n", + " 39 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 8.727384E-04 0.000000E+00 E 9.00000E+100\n", + " 40 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -1.139040E-02 0.000000E+00 E 9.00000E+100\n", + " 41 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -2.895648E-02 0.000000E+00 E 9.00000E+100\n", + " 42 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -3.467113E-02 0.000000E+00 E 9.00000E+100\n", + " 43 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -4.803617E-02 0.000000E+00 E 9.00000E+100\n", + " 44 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -6.711102E-02 0.000000E+00 E 9.00000E+100\n", + " 45 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -3.782017E-02 0.000000E+00 E 9.00000E+100\n", + " 46 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -3.222433E-02 0.000000E+00 E 9.00000E+100\n", + " 47 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.621911E-02 0.000000E+00 E 9.00000E+100\n", + " 48 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.437244E-02 0.000000E+00 E 9.00000E+100\n", + " 49 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.016566E-02 0.000000E+00 E 9.00000E+100\n", + " 50 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.438596E-02 0.000000E+00 E 9.00000E+100\n", + " 51 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.256933E-02 0.000000E+00 E 9.00000E+100\n", + " 52 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -8.413797E-03 0.000000E+00 E 9.00000E+100\n", + " 53 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.689611E-03 0.000000E+00 E 9.00000E+100\n", + " 54 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -8.803422E-04 0.000000E+00 E 9.00000E+100\n", + " 55 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 3.257993E-03 0.000000E+00 E 9.00000E+100\n", + " 56 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 8.956421E-03 0.000000E+00 E 9.00000E+100\n", + " 57 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.680938E-05 0.000000E+00 E 9.00000E+100\n", + " 58 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.681276E-05 0.000000E+00 E 9.00000E+100\n", + " 59 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.680776E-05 0.000000E+00 E 9.00000E+100\n", + " 60 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.680384E-05 0.000000E+00 E 9.00000E+100\n", + " 61 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.679065E-05 0.000000E+00 E 9.00000E+100\n", + " 62 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.676870E-05 0.000000E+00 E 9.00000E+100\n", + " 63 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.676740E-05 0.000000E+00 E 9.00000E+100\n", + " 64 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.676449E-05 0.000000E+00 E 9.00000E+100\n", + " 65 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.676058E-05 0.000000E+00 E 9.00000E+100\n", + " 66 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.675938E-05 0.000000E+00 E 9.00000E+100\n", + " 67 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.675667E-05 0.000000E+00 E 9.00000E+100\n", + " 68 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 7.675305E-05 0.000000E+00 E 9.00000E+100\n", + " 69 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -4.116087E-03 0.000000E+00 E 9.00000E+100\n", + " 70 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -5.748483E-03 0.000000E+00 E 9.00000E+100\n", + " 71 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -7.979510E-03 0.000000E+00 E 9.00000E+100\n", + " 72 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -8.680185E-03 0.000000E+00 E 9.00000E+100\n", + " 73 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.027431E-02 0.000000E+00 E 9.00000E+100\n", + " 74 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.244906E-02 0.000000E+00 E 9.00000E+100\n", + " 75 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.313109E-02 0.000000E+00 E 9.00000E+100\n", + " 76 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.468101E-02 0.000000E+00 E 9.00000E+100\n", + " 77 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.679134E-02 0.000000E+00 E 9.00000E+100\n", + " 78 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.745215E-02 0.000000E+00 E 9.00000E+100\n", + " 79 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.895200E-02 0.000000E+00 E 9.00000E+100\n", + " 80 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -2.098984E-02 0.000000E+00 E 9.00000E+100\n", + " 81 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 82 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 -5.556536E-17 0.000000E+00 9.00000E+100\n", + " 83 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 84 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 1.387779E-17 0.000000E+00 9.00000E+100\n", + " 85 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 86 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 87 traj.phases.climb1->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 88 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 1.295515E-01 0.000000E+00 E 9.00000E+100\n", + " 89 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 1.349127E-01 0.000000E+00 E 9.00000E+100\n", + " 90 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 1.615414E-01 0.000000E+00 E 9.00000E+100\n", + " 91 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 1.507414E-03 0.000000E+00 E 9.00000E+100\n", + " 92 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 1.426534E-03 0.000000E+00 E 9.00000E+100\n", + " 93 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 1.317088E-03 0.000000E+00 E 9.00000E+100\n", + " 94 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 2.424766E-01 0.000000E+00 E 9.00000E+100\n", + " 95 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 2.206075E-01 0.000000E+00 E 9.00000E+100\n", + " 96 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 1.873288E-01 0.000000E+00 E 9.00000E+100\n", + " 97 traj.phases.climb2->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 98 traj.phases.climb2->final_boundary_constraint->mach e 8.000000E-01 8.000000E-01 8.000000E-01 9.00000E+100\n", + " 99 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -2.255353E-01 0.000000E+00 E 9.00000E+100\n", + " 100 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.993872E-01 0.000000E+00 E 9.00000E+100\n", + " 101 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.543238E-01 0.000000E+00 E 9.00000E+100\n", + " 102 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.414243E-01 0.000000E+00 E 9.00000E+100\n", + " 103 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.059912E-01 0.000000E+00 E 9.00000E+100\n", + " 104 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -5.304664E-02 0.000000E+00 E 9.00000E+100\n", + " 105 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -3.776842E-02 0.000000E+00 E 9.00000E+100\n", + " 106 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 9.545807E-04 0.000000E+00 E 9.00000E+100\n", + " 107 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 8.172580E-02 0.000000E+00 E 9.00000E+100\n", + " 108 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 -2.426644E-02 0.000000E+00 E 9.00000E+100\n", + " 109 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 -1.726371E-03 0.000000E+00 E 9.00000E+100\n", + " 110 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 5.430194E-03 0.000000E+00 E 9.00000E+100\n", + " 111 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 3.872597E-03 0.000000E+00 E 9.00000E+100\n", + " 112 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 3.618909E-03 0.000000E+00 E 9.00000E+100\n", + " 113 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 3.286245E-03 0.000000E+00 E 9.00000E+100\n", + " 114 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 3.191289E-03 0.000000E+00 E 9.00000E+100\n", + " 115 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.964754E-03 0.000000E+00 E 9.00000E+100\n", + " 116 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.548933E-03 0.000000E+00 E 9.00000E+100\n", + " 117 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.214629E-02 0.000000E+00 E 9.00000E+100\n", + " 118 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.418797E-02 0.000000E+00 E 9.00000E+100\n", + " 119 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.727218E-02 0.000000E+00 E 9.00000E+100\n", + " 120 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.831655E-02 0.000000E+00 E 9.00000E+100\n", + " 121 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -4.085065E-02 0.000000E+00 E 9.00000E+100\n", + " 122 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -4.470143E-02 0.000000E+00 E 9.00000E+100\n", + " 123 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -4.601426E-02 0.000000E+00 E 9.00000E+100\n", + " 124 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -4.921350E-02 0.000000E+00 E 9.00000E+100\n", + " 125 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -4.974632E-02 0.000000E+00 E 9.00000E+100\n", + " 126 traj.phases.desc1->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 127 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -4.277848E-02 0.000000E+00 E 9.00000E+100\n", + " 128 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -3.895954E-02 0.000000E+00 E 9.00000E+100\n", + " 129 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -2.787700E-02 0.000000E+00 E 9.00000E+100\n", + " 130 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -2.332833E-02 0.000000E+00 E 9.00000E+100\n", + " 131 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -1.102907E-02 0.000000E+00 E 9.00000E+100\n", + " 132 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 5.409284E-03 0.000000E+00 E 9.00000E+100\n", + " 133 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 1.272129E-03 0.000000E+00 E 9.00000E+100\n", + " 134 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -7.793018E-03 0.000000E+00 E 9.00000E+100\n", + " 135 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -1.948962E-02 0.000000E+00 E 9.00000E+100\n", + " 136 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 -8.518117E-03 0.000000E+00 E 9.00000E+100\n", + " 137 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 -1.726843E-03 0.000000E+00 E 9.00000E+100\n", + " 138 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 5.343179E-04 0.000000E+00 E 9.00000E+100\n", + " 139 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.054056E-04 0.000000E+00 E 9.00000E+100\n", + " 140 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.200624E-04 0.000000E+00 E 9.00000E+100\n", + " 141 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.416797E-04 0.000000E+00 E 9.00000E+100\n", + " 142 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.467613E-04 0.000000E+00 E 9.00000E+100\n", + " 143 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.591485E-04 0.000000E+00 E 9.00000E+100\n", + " 144 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.785953E-04 0.000000E+00 E 9.00000E+100\n", + " 145 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 -4.841115E+00 0.000000E+00 E 9.00000E+100\n", + " 146 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 -9.109513E-01 0.000000E+00 E 9.00000E+100\n", + " 147 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 3.881133E-01 0.000000E+00 E 9.00000E+100\n", + " 148 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.352695E-01 0.000000E+00 E 9.00000E+100\n", + " 149 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.337867E-01 0.000000E+00 E 9.00000E+100\n", + " 150 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.331703E-01 0.000000E+00 E 9.00000E+100\n", + " 151 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.358305E-01 0.000000E+00 E 9.00000E+100\n", + " 152 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.415815E-01 0.000000E+00 E 9.00000E+100\n", + " 153 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.488110E-01 0.000000E+00 E 9.00000E+100\n", + " 154 traj.phases.desc2->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 155 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 1.250331E-01 0.000000E+00 E 9.00000E+100\n", + " 156 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 1.172366E-01 0.000000E+00 E 9.00000E+100\n", + " 157 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 1.004951E-01 0.000000E+00 E 9.00000E+100\n", + " 158 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 7.895862E-02 0.000000E+00 E 9.00000E+100\n", + " 159 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 5.687274E-02 0.000000E+00 E 9.00000E+100\n", + " 160 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 3.869760E-02 0.000000E+00 E 9.00000E+100\n", + " 161 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 2.746677E-02 0.000000E+00 E 9.00000E+100\n", + " 162 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 4.638632E-04 0.000000E+00 E 9.00000E+100\n", + " 163 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 4.729111E-04 0.000000E+00 E 9.00000E+100\n", + " 164 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 4.941796E-04 0.000000E+00 E 9.00000E+100\n", + " 165 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 5.229304E-04 0.000000E+00 E 9.00000E+100\n", + " 166 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 5.557022E-04 0.000000E+00 E 9.00000E+100\n", + " 167 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 5.846184E-04 0.000000E+00 E 9.00000E+100\n", + " 168 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 6.038235E-04 0.000000E+00 E 9.00000E+100\n", + " 169 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.332067E-01 0.000000E+00 E 9.00000E+100\n", + " 170 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.352741E-01 0.000000E+00 E 9.00000E+100\n", + " 171 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.396321E-01 0.000000E+00 E 9.00000E+100\n", + " 172 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.452352E-01 0.000000E+00 E 9.00000E+100\n", + " 173 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.508830E-01 0.000000E+00 E 9.00000E+100\n", + " 174 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.555022E-01 0.000000E+00 E 9.00000E+100\n", + " 175 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 5.583195E-01 0.000000E+00 E 9.00000E+100\n", + " 176 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 -1.689955E-01 0.000000E+00 E 9.00000E+100\n", + " 177 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 -1.065200E-01 0.000000E+00 E 9.00000E+100\n", + " 178 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 2.199958E-03 0.000000E+00 E 9.00000E+100\n", + " 179 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 4.765410E-04 0.000000E+00 E 9.00000E+100\n", + " 180 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 4.811469E-04 0.000000E+00 E 9.00000E+100\n", + " 181 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 4.875537E-04 0.000000E+00 E 9.00000E+100\n", + " 182 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 1.659240E-01 0.000000E+00 E 9.00000E+100\n", + " 183 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 -4.055050E-01 0.000000E+00 E 9.00000E+100\n", + " 184 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 -1.193960E+00 0.000000E+00 E 9.00000E+100\n", + " 185 traj.phases.rotation->final_boundary_constraint->normal_force e 0.000000E+00 8.409179E+00 0.000000E+00 E 9.00000E+100\n", + " 186 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -4.059757E-03 0.000000E+00 E 9.00000E+100\n", + " 187 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -2.379375E-02 0.000000E+00 E 9.00000E+100\n", + " 188 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -3.032572E-02 0.000000E+00 E 9.00000E+100\n", + " 189 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -4.947590E-02 0.000000E+00 E 9.00000E+100\n", + " 190 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -4.694172E-02 0.000000E+00 E 9.00000E+100\n", + " 191 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -4.521174E-02 0.000000E+00 E 9.00000E+100\n", + " 192 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 6.132037E-05 0.000000E+00 E 9.00000E+100\n", + " 193 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 6.136432E-05 0.000000E+00 E 9.00000E+100\n", + " 194 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 6.142751E-05 0.000000E+00 E 9.00000E+100\n", + " 195 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 1.251386E+00 0.000000E+00 E 9.00000E+100\n", + " 196 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 1.914830E-01 0.000000E+00 E 9.00000E+100\n", + " 197 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 -1.615733E-01 0.000000E+00 E 9.00000E+100\n", + " 198 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.280810E-01 1.100000E+00 9.00000E+100\n", + " 199 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.127141E-01 1.100000E+00 9.00000E+100\n", + " 200 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.131475E-01 1.100000E+00 9.00000E+100\n", + " 201 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.139957E-01 1.100000E+00 9.00000E+100\n", + " 202 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.139957E-01 1.100000E+00 9.00000E+100\n", + " 203 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.161165E-01 1.100000E+00 9.00000E+100\n", + " 204 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.189456E-01 1.100000E+00 9.00000E+100\n", + " 205 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.197486E-01 1.100000E+00 9.00000E+100\n", + " 206 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.197486E-01 1.100000E+00 9.00000E+100\n", + " 207 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.214011E-01 1.100000E+00 9.00000E+100\n", + " 208 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.232370E-01 1.100000E+00 9.00000E+100\n", + " 209 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.237063E-01 1.100000E+00 9.00000E+100\n", + " 210 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.237063E-01 1.100000E+00 9.00000E+100\n", + " 211 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.245697E-01 1.100000E+00 9.00000E+100\n", + " 212 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.252587E-01 1.100000E+00 9.00000E+100\n", + " 213 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.253505E-01 1.100000E+00 9.00000E+100\n", + " 214 traj.phases.ascent->path_constraint->theta i 0.000000E+00 1.000000E+00 1.500000E+01 9.00000E+100\n", + " 215 traj.phases.ascent->path_constraint->theta i 0.000000E+00 1.621339E+00 1.500000E+01 9.00000E+100\n", + " 216 traj.phases.ascent->path_constraint->theta i 0.000000E+00 2.478661E+00 1.500000E+01 9.00000E+100\n", + " 217 traj.phases.ascent->path_constraint->theta i 0.000000E+00 2.750000E+00 1.500000E+01 9.00000E+100\n", + " 218 traj.phases.ascent->path_constraint->theta i 0.000000E+00 2.750000E+00 1.500000E+01 9.00000E+100\n", + " 219 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.371339E+00 1.500000E+01 9.00000E+100\n", + " 220 traj.phases.ascent->path_constraint->theta i 0.000000E+00 4.228661E+00 1.500000E+01 9.00000E+100\n", + " 221 traj.phases.ascent->path_constraint->theta i 0.000000E+00 4.500000E+00 1.500000E+01 9.00000E+100\n", + " 222 traj.phases.ascent->path_constraint->theta i 0.000000E+00 4.500000E+00 1.500000E+01 9.00000E+100\n", + " 223 traj.phases.ascent->path_constraint->theta i 0.000000E+00 5.121339E+00 1.500000E+01 9.00000E+100\n", + " 224 traj.phases.ascent->path_constraint->theta i 0.000000E+00 5.978661E+00 1.500000E+01 9.00000E+100\n", + " 225 traj.phases.ascent->path_constraint->theta i 0.000000E+00 6.250000E+00 1.500000E+01 9.00000E+100\n", + " 226 traj.phases.ascent->path_constraint->theta i 0.000000E+00 6.250000E+00 1.500000E+01 9.00000E+100\n", + " 227 traj.phases.ascent->path_constraint->theta i 0.000000E+00 6.871339E+00 1.500000E+01 9.00000E+100\n", + " 228 traj.phases.ascent->path_constraint->theta i 0.000000E+00 7.728661E+00 1.500000E+01 9.00000E+100\n", + " 229 traj.phases.ascent->path_constraint->theta i 0.000000E+00 8.000000E+00 1.500000E+01 9.00000E+100\n", + " 230 traj.phases.climb2->final_boundary_constraint->altitude_rate i 1.000000E-01 3.314185E+02 1.000000E+30 9.00000E+100\n", + "\n", + "\n", + " Exit Status\n", + " Inform Description\n", + " -1 Maximum Iterations Exceeded\n", + "--------------------------------------------------------------------------------\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from aviary.api import Aircraft, Mission\n", "import aviary.api as av\n", @@ -150,7 +910,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "b0baac27", "metadata": {}, "outputs": [], @@ -200,10 +960,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "8cac423c", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'aircraft:blended_wing_body_design:num_bays': (0, 'unitless'), 'aircraft:crew_and_payload:mass_per_passenger': (165.0, 'lbm'), 'aircraft:crew_and_payload:num_business_class': (0, 'unitless'), 'aircraft:crew_and_payload:num_first_class': (0, 'unitless'), 'aircraft:crew_and_payload:num_passengers': (180, 'unitless'), 'aircraft:crew_and_payload:num_tourist_class': (0, 'unitless'), 'aircraft:crew_and_payload:passenger_mass_with_bags': (200, 'lbm'), 'aircraft:design:compute_htail_volume_coeff': (False, 'unitless'), 'aircraft:design:compute_vtail_volume_coeff': (False, 'unitless'), 'aircraft:design:part25_structural_category': (3, 'unitless'), 'aircraft:design:reserves': (4998, 'unitless'), 'aircraft:design:smooth_mass_discontinuities': (False, 'unitless'), 'aircraft:design:ulf_calculated_from_maneuver': (False, 'unitless'), 'aircraft:design:use_alt_mass': (False, 'unitless'), 'aircraft:electrical:has_hybrid_system': (False, 'unitless'), 'aircraft:engine:constant_fuel_consumption': (array([0.]), 'lbm/h'), 'aircraft:engine:flight_idle_max_fraction': (array([1.]), 'unitless'), 'aircraft:engine:flight_idle_min_fraction': (array([0.08]), 'unitless'), 'aircraft:engine:flight_idle_thrust_fraction': (array([0.]), 'unitless'), 'aircraft:engine:fuel_flow_scaler_constant_term': (array([0.]), 'unitless'), 'aircraft:engine:fuel_flow_scaler_linear_term': (array([0.]), 'unitless'), 'aircraft:engine:generate_flight_idle': ([False], 'unitless'), 'aircraft:engine:geopotential_alt': ([False], 'unitless'), 'aircraft:engine:has_propellers': ([False], 'unitless'), 'aircraft:engine:ignore_negative_thrust': ([False], 'unitless'), 'aircraft:engine:interpolation_method': (['slinear'], 'unitless'), 'aircraft:engine:num_engines': (array([2]), 'unitless'), 'aircraft:engine:num_fuselage_engines': (array([0]), 'unitless'), 'aircraft:engine:num_wing_engines': (array([2]), 'unitless'), 'aircraft:engine:scale_mass': ([True], 'unitless'), 'aircraft:engine:scale_performance': ([True], 'unitless'), 'aircraft:engine:subsonic_fuel_flow_scaler': (array([1.]), 'unitless'), 'aircraft:engine:supersonic_fuel_flow_scaler': (array([1.]), 'unitless'), 'aircraft:engine:type': ([], 'unitless'), 'aircraft:fins:num_fins': (0, 'unitless'), 'aircraft:fuel:num_tanks': (7, 'unitless'), 'aircraft:fuselage:aisle_width': (24, 'inch'), 'aircraft:fuselage:military_cargo_floor': (False, 'unitless'), 'aircraft:fuselage:num_aisles': (1, 'unitless'), 'aircraft:fuselage:num_fuselages': (1, 'unitless'), 'aircraft:fuselage:num_seats_abreast': (6, 'unitless'), 'aircraft:fuselage:provide_surface_area': (True, 'unitless'), 'aircraft:fuselage:seat_pitch': (29, 'inch'), 'aircraft:fuselage:seat_width': (20.2, 'inch'), 'aircraft:landing_gear:carrier_based': (False, 'unitless'), 'aircraft:landing_gear:drag_coefficient': (0.0, 'unitless'), 'aircraft:landing_gear:fixed_gear': (False, 'unitless'), 'aircraft:strut:dimensional_location_specified': (False, 'unitless'), 'aircraft:vertical_tail:num_tails': (1, 'unitless'), 'aircraft:wing:airfoil_technology': (1.0, 'unitless'), 'aircraft:wing:choose_fold_location': (True, 'unitless'), 'aircraft:wing:detailed_wing': (False, 'unitless'), 'aircraft:wing:flap_type': (, 'unitless'), 'aircraft:wing:fold_dimensional_location_specified': (False, 'unitless'), 'aircraft:wing:has_fold': (False, 'unitless'), 'aircraft:wing:has_strut': (False, 'unitless'), 'aircraft:wing:load_distribution_control': (2.0, 'unitless'), 'aircraft:wing:loading_above_20': (True, 'unitless'), 'aircraft:wing:num_flap_segments': (2, 'unitless'), 'aircraft:wing:num_integration_stations': (50, 'unitless'), 'aircraft:wing:span_efficiency_reduction': (False, 'unitless'), 'mission:design:cruise_altitude': (37500, 'ft'), 'mission:design:rate_of_climb_at_top_of_climb': (0.0, 'ft/min'), 'mission:summary:fuel_flow_scaler': (1, 'unitless'), 'mission:takeoff:angle_of_attack_runway': (0.0, 'deg'), 'mission:takeoff:obstacle_height': (35.0, 'ft'), 'mission:takeoff:thrust_incidence': (0.0, 'deg'), 'mission:taxi:duration': (0.1677, 'h'), 'mission:taxi:mach': (0.0001, 'unitless'), 'debug_mode': (False, 'unitless'), 'INGASP.JENGSZ': (4, 'unitless'), 'test_mode': (False, 'unitless'), 'use_surrogates': (True, 'unitless'), 'mass_defect': (10000, 'lbm'), 'problem_type': (, 'unitless'), 'aircraft:controls:cockpit_control_mass_scaler': (1, 'unitless'), 'aircraft:controls:control_mass_increment': (0, 'lbm'), 'aircraft:controls:stability_augmentation_system_mass': (0, 'lbm'), 'aircraft:controls:stability_augmentation_system_mass_scaler': (1, 'unitless'), 'aircraft:crew_and_payload:cargo_mass': (10040, 'lbm'), 'aircraft:design:cg_delta': (0.25, 'unitless'), 'aircraft:design:cockpit_control_mass_coefficient': (16.5, 'unitless'), 'aircraft:design:drag_increment': (0.00175, 'unitless'), 'aircraft:design:equipment_mass_coefficients': ([928, 0.0736, 0.112, 0.14, 1959, 1.65, 551, 11192, 5, 3, 50, 7.6, 12], 'unitless'), 'aircraft:design:max_structural_speed': (402.5, 'mi/h'), 'aircraft:design:static_margin': (0.03, 'unitless'), 'aircraft:design:structural_mass_increment': (0, 'lbm'), 'aircraft:design:supercritical_drag_shift': (0.033, 'unitless'), 'aircraft:engine:additional_mass_fraction': (array([0.135]), 'unitless'), 'aircraft:engine:data_file': (['models/engines/turbofan_23k_1.deck'], 'unitless'), 'aircraft:engine:mass_scaler': (array([1]), 'unitless'), 'aircraft:engine:mass_specific': (array([0.21366]), 'lbm/lbf'), 'aircraft:engine:pod_mass_scaler': (array([1]), 'unitless'), 'aircraft:engine:pylon_factor': (array([1.25]), 'unitless'), 'aircraft:engine:reference_diameter': (array([5.8]), 'ft'), 'aircraft:engine:reference_sls_thrust': (array([28690]), 'lbf'), 'aircraft:engine:scale_factor': (array([1]), 'unitless'), 'aircraft:engine:scaled_sls_thrust': (array([28690]), 'lbf'), 'aircraft:engine:wing_locations': (array([0.35]), 'unitless'), 'aircraft:fuel:density': (6.687, 'lbm/galUS'), 'aircraft:fuel:fuel_margin': (0, 'unitless'), 'aircraft:fuel:fuel_system_mass_coefficient': (0.041, 'unitless'), 'aircraft:fuel:fuel_system_mass_scaler': (1, 'unitless'), 'aircraft:fuel:wing_fuel_fraction': (0.6, 'unitless'), 'aircraft:fuselage:delta_diameter': (4.5, 'ft'), 'aircraft:fuselage:flat_plate_area_increment': (0.25, 'ft**2'), 'aircraft:fuselage:form_factor': (1.25, 'unitless'), 'aircraft:fuselage:mass_coefficient': (128, 'unitless'), 'aircraft:fuselage:nose_fineness': (1, 'unitless'), 'aircraft:fuselage:pilot_compartment_length': (9.5, 'ft'), 'aircraft:fuselage:pressure_differential': (7.5, 'psi'), 'aircraft:fuselage:tail_fineness': (3, 'unitless'), 'aircraft:fuselage:wetted_area_factor': (4000, 'unitless'), 'aircraft:horizontal_tail:area': (0, 'ft**2'), 'aircraft:horizontal_tail:aspect_ratio': (4.75, 'unitless'), 'aircraft:horizontal_tail:form_factor': (1.25, 'unitless'), 'aircraft:horizontal_tail:mass_coefficient': (0.232, 'unitless'), 'aircraft:horizontal_tail:moment_ratio': (0.2307, 'unitless'), 'aircraft:horizontal_tail:sweep': (25, 'deg'), 'aircraft:horizontal_tail:taper_ratio': (0.352, 'unitless'), 'aircraft:horizontal_tail:thickness_to_chord': (0.12, 'unitless'), 'aircraft:horizontal_tail:vertical_tail_fraction': (0, 'unitless'), 'aircraft:horizontal_tail:volume_coefficient': (1.189, 'unitless'), 'aircraft:landing_gear:main_gear_location': (0.15, 'unitless'), 'aircraft:landing_gear:main_gear_mass_coefficient': (0.85, 'unitless'), 'aircraft:landing_gear:mass_coefficient': (0.04, 'unitless'), 'aircraft:landing_gear:tail_hook_mass_scaler': (1, 'unitless'), 'aircraft:landing_gear:total_mass_scaler': (1, 'unitless'), 'aircraft:nacelle:clearance_ratio': (array([0.2]), 'unitless'), 'aircraft:nacelle:core_diameter_ratio': (array([1.25]), 'unitless'), 'aircraft:nacelle:fineness': (array([2]), 'unitless'), 'aircraft:nacelle:form_factor': (array([1.5]), 'unitless'), 'aircraft:nacelle:mass_specific': (array([3]), 'lbm/ft**2'), 'aircraft:strut:area_ratio': (0, 'unitless'), 'aircraft:strut:attachment_location': (0, 'ft'), 'aircraft:strut:attachment_location_dimensionless': (0, 'unitless'), 'aircraft:strut:fuselage_interference_factor': (0, 'unitless'), 'aircraft:strut:mass_coefficient': (0, 'unitless'), 'aircraft:strut:thickness_to_chord': (0, 'unitless'), 'aircraft:vertical_tail:area': (0, 'ft**2'), 'aircraft:vertical_tail:aspect_ratio': (1.67, 'unitless'), 'aircraft:vertical_tail:form_factor': (1.25, 'unitless'), 'aircraft:vertical_tail:mass_coefficient': (0.289, 'unitless'), 'aircraft:vertical_tail:moment_ratio': (2.362, 'unitless'), 'aircraft:vertical_tail:sweep': (35, 'deg'), 'aircraft:vertical_tail:taper_ratio': (0.801, 'unitless'), 'aircraft:vertical_tail:thickness_to_chord': (0.12, 'unitless'), 'aircraft:vertical_tail:volume_coefficient': (0.145, 'unitless'), 'aircraft:wing:aspect_ratio': (10.13, 'unitless'), 'aircraft:wing:center_distance': (0.463, 'unitless'), 'aircraft:wing:flap_chord_ratio': (0.3, 'unitless'), 'aircraft:wing:flap_deflection_landing': (40, 'deg'), 'aircraft:wing:flap_deflection_takeoff': (10, 'deg'), 'aircraft:wing:flap_drag_increment_optimum': (0.1, 'unitless'), 'aircraft:wing:flap_lift_increment_optimum': (1.5, 'unitless'), 'aircraft:wing:flap_span_ratio': (0.65, 'unitless'), 'aircraft:wing:fold_mass_coefficient': (0, 'unitless'), 'aircraft:wing:folded_span': (0, 'ft'), 'aircraft:wing:form_factor': (1.25, 'unitless'), 'aircraft:wing:fuselage_interference_factor': (1.1, 'unitless'), 'aircraft:wing:height': (8, 'ft'), 'aircraft:wing:high_lift_mass_coefficient': (1.9, 'unitless'), 'aircraft:wing:incidence': (1.5, 'deg'), 'aircraft:wing:loading': (128, 'lbf/ft**2'), 'aircraft:wing:mass_coefficient': (102.5, 'unitless'), 'aircraft:wing:max_lift_ref': (1.15, 'unitless'), 'aircraft:wing:max_slat_deflection_landing': (10, 'deg'), 'aircraft:wing:max_slat_deflection_takeoff': (10, 'deg'), 'aircraft:wing:max_thickness_location': (0.4, 'unitless'), 'aircraft:wing:min_pressure_location': (0.3, 'unitless'), 'aircraft:wing:mounting_type': (0, 'unitless'), 'aircraft:wing:optimum_flap_deflection': (55, 'deg'), 'aircraft:wing:optimum_slat_deflection': (20, 'deg'), 'aircraft:wing:slat_chord_ratio': (0.15, 'unitless'), 'aircraft:wing:slat_lift_increment_optimum': (0.93, 'unitless'), 'aircraft:wing:surface_ctrl_mass_coefficient': (0.95, 'unitless'), 'aircraft:wing:sweep': (25, 'deg'), 'aircraft:wing:taper_ratio': (0.33, 'unitless'), 'aircraft:wing:thickness_to_chord_root': (0.15, 'unitless'), 'aircraft:wing:thickness_to_chord_tip': (0.12, 'unitless'), 'aircraft:wing:zero_lift_angle': (-1.2, 'deg'), 'mission:design:gross_mass': (175400, 'lbm'), 'mission:design:mach': (0.8, 'unitless'), 'mission:design:range': (3675, 'NM'), 'mission:landing:braking_delay': (1, 's'), 'mission:landing:glide_to_stall_ratio': (1.3, 'unitless'), 'mission:landing:maximum_flare_load_factor': (1.15, 'unitless'), 'mission:landing:maximum_sink_rate': (900, 'ft/min'), 'mission:landing:obstacle_height': (50, 'ft'), 'mission:landing:touchdown_sink_rate': (5, 'ft/s'), 'mission:takeoff:decision_speed_increment': (10, 'kn'), 'mission:takeoff:rotation_speed_increment': (5, 'kn'), 'mission:summary:cruise_mass_final': (140320.0, 'lbm'), 'mission:summary:gross_mass': (175400, 'lbm'), 'engine_models': ([], 'unitless'), 'aircraft:propulsion:total_num_engines': (2, 'unitless'), 'aircraft:propulsion:total_num_fuselage_engines': (0, 'unitless'), 'aircraft:propulsion:total_num_wing_engines': (2, 'unitless')}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "prob.load_inputs(aircraft_filename)" ] @@ -242,7 +1013,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "e3d91612", "metadata": {}, "outputs": [], @@ -262,7 +1033,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "00de09c8", "metadata": {}, "outputs": [], @@ -284,14 +1055,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "b17b6637", "metadata": { "tags": [ "hide-output" ] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "prob.add_phases()" ] @@ -308,7 +1090,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "af5ba774", "metadata": {}, "outputs": [], @@ -328,7 +1110,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "f765815b", "metadata": {}, "outputs": [], @@ -352,7 +1134,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "87e863bc", "metadata": {}, "outputs": [], @@ -380,7 +1162,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "0a408e2e", "metadata": {}, "outputs": [], @@ -427,7 +1209,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "46eee283", "metadata": {}, "outputs": [], @@ -482,10 +1264,177 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "dbfca715", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/group.py:333: PromotionWarning:: Setting input defaults for input 'mission:takeoff:ascent_duration' which override previously set defaults for ['auto', 'prom', 'src_shape', 'val'].\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.speeds' : d(*)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(max_mach)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(density_ratio)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(V9)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.factors' : d(aircraft:wing:ultimate_load_factor)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.fixed_mass.params' : d(c_gear_loc)/d(aircraft:landing_gear:main_gear_location): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_useful_load)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_equipment_mass)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'groundroll': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.eoms' : d(alpha_rate)/d(('*',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.rotation': initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'rotation': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.rotation.rhs_all.eoms' : d(alpha_rate)/d(('*',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'ascent': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.accel': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'accel': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.climb1': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'climb1': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.climb2': initial_bounds\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'climb2': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.desc1': initial_bounds, initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'desc1': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.desc2': initial_bounds, initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'desc2': lower, upper\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:engine:scale_factor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.accel: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.accel' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.accel.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.accel.nonlinear_solver to override.\n", + " Setting `traj.phases.accel.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.accel.linear_solver to override.\n", + " Set `traj.phases.accel.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.ascent' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.ascent.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.ascent.nonlinear_solver to override.\n", + " Setting `traj.phases.ascent.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.ascent.linear_solver to override.\n", + " Set `traj.phases.ascent.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb1: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb1' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb1.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb1.nonlinear_solver to override.\n", + " Setting `traj.phases.climb1.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb1.linear_solver to override.\n", + " Set `traj.phases.climb1.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb2: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb2' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb2.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb2.nonlinear_solver to override.\n", + " Setting `traj.phases.climb2.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb2.linear_solver to override.\n", + " Set `traj.phases.climb2.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.desc1: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.desc1' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.desc1.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.desc1.nonlinear_solver to override.\n", + " Setting `traj.phases.desc1.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.desc1.linear_solver to override.\n", + " Set `traj.phases.desc1.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.desc2: The following timeseries outputs were requested but not found in the ODE: aero.CD, aero.CL\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.desc2' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.desc2.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.desc2.nonlinear_solver to override.\n", + " Setting `traj.phases.desc2.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.desc2.linear_solver to override.\n", + " Set `traj.phases.desc2.options[\"auto_solvers\"] = False` to disable this behavior.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.rotation' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.rotation.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.rotation.nonlinear_solver to override.\n", + " Setting `traj.phases.rotation.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.rotation.linear_solver to override.\n", + " Set `traj.phases.rotation.options[\"auto_solvers\"] = False` to disable this behavior.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Constraint Report [traj] ---\n", + " --- groundroll ---\n", + " None\n", + " --- rotation ---\n", + " [final] 0.0000e+00 == normal_force [lbf]\n", + " --- ascent ---\n", + " [final] 5.0000e+02 == altitude [ft]\n", + " [path] 0.0000e+00 <= load_factor <= 1.1000e+00 [unitless]\n", + " [path] 0.0000e+00 <= fuselage_pitch <= 1.5000e+01 [deg]\n", + " --- accel ---\n", + " [final] 2.5000e+02 == EAS [kn]\n", + " --- climb1 ---\n", + " [final] 1.0000e+04 == altitude [ft]\n", + " --- climb2 ---\n", + " [final] 3.7500e+04 == altitude [ft]\n", + " [final] 1.0000e-01 <= altitude_rate [ft/min]\n", + " [final] 8.0000e-01 == mach [unitless]\n", + " --- cruise ---\n", + " None\n", + " --- desc1 ---\n", + " [final] 1.0000e+04 == altitude [ft]\n", + " --- desc2 ---\n", + " [final] 1.0000e+03 == altitude [ft]\n", + "\n" + ] + } + ], "source": [ "prob.setup()" ] @@ -506,7 +1455,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "afdf6203", "metadata": {}, "outputs": [], @@ -526,10 +1475,603 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "2f1a2b82", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'landing.aero_app.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'landing.aero_td.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.ascent.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.rotation.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, aviary_history.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "Model viewer data has already been recorded for Driver.\n", + "\n", + "Coloring for 'event_xform' (class ExecComp)\n", + "\n", + "Jacobian shape: (2, 4) (75.00% nonzero)\n", + "FWD solves: 3 REV solves: 0\n", + "Total colors vs. total size: 3 vs 4 (25.00% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 0.0005 sec\n", + "Time to compute coloring: 0.0009 sec\n", + "Memory to compute coloring: 0.0000 MB\n", + "Full total jacobian was computed 3 times, taking 2.002681 seconds.\n", + "Total jacobian shape: (232, 203) \n", + "\n", + "\n", + "Jacobian shape: (232, 203) (7.47% nonzero)\n", + "FWD solves: 45 REV solves: 0\n", + "Total colors vs. total size: 45 vs 203 (77.83% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 2.0027 sec\n", + "Time to compute coloring: 0.1893 sec\n", + "Memory to compute coloring: 0.0000 MB\n", + "Coloring created on: 2024-01-09 11:24:45\n", + "\n", + "List of user-set options:\n", + "\n", + " Name Value used\n", + " alpha_for_y = safer-min-dual-infeas yes\n", + " file_print_level = 5 yes\n", + " hessian_approximation = limited-memory yes\n", + " linear_solver = mumps yes\n", + " max_iter = 1 yes\n", + " mu_init = 1e-05 yes\n", + " mu_strategy = monotone yes\n", + " nlp_scaling_method = gradient-based yes\n", + " output_file = reports/problem2/IPOPT.out yes\n", + " print_level = 5 yes\n", + " print_user_options = yes yes\n", + " sb = yes yes\n", + " tol = 1e-06 yes\n", + "This is Ipopt version 3.14.12, running with linear solver MUMPS 5.2.1.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 2343\n", + "Number of nonzeros in inequality constraint Jacobian.: 568\n", + "Number of nonzeros in Lagrangian Hessian.............: 0\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/total_jac.py:1759: DerivativesWarning:Constraints or objectives [('traj.phases.climb2.timeseries.timeseries_comp.mach', inds=[(11, 0)])] cannot be impacted by the design variables of the problem.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of variables............................: 203\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 203\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 198\n", + "Total number of inequality constraints...............: 33\n", + " inequality constraints with only lower bounds: 1\n", + " inequality constraints with lower and upper bounds: 32\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 5.2731333e+00 1.30e+01 1.75e+01 -5.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 5.0168614e+00 8.67e+00 1.50e+01 -5.0 1.59e+01 - 1.17e-01 3.00e-01h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 5.0168613936496804e+00 5.0168613936496804e+00\n", + "Dual infeasibility......: 1.4970544949172231e+01 1.4970544949172231e+01\n", + "Constraint violation....: 2.4092945450656864e+00 8.6732536855893478e+00\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 1.0000016687732632e+05 1.0000016687732632e+05\n", + "Overall NLP error.......: 1.0000016687732632e+05 1.0000016687732632e+05\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 2\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 2\n", + "Number of Lagrangian Hessian evaluations = 0\n", + "Total seconds in IPOPT = 3.834\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "\n", + "\n", + "Optimization Problem -- Optimization using pyOpt_sparse\n", + "================================================================================\n", + " Objective Function: _objfunc\n", + "\n", + " Solution: \n", + "--------------------------------------------------------------------------------\n", + " Total Time: 3.8360\n", + " User Objective Time : 0.8133\n", + " User Sensitivity Time : 2.9721\n", + " Interface Time : 0.0214\n", + " Opt Solver Time: 0.0292\n", + " Calls to Objective Function : 3\n", + " Calls to Sens Function : 3\n", + "\n", + "\n", + " Objectives\n", + " Index Name Value\n", + " 0 mission:objectives:fuel 5.016861E+00\n", + "\n", + " Variables (c - continuous, i - integer, d - discrete)\n", + " Index Name Type Lower Bound Value Upper Bound Status\n", + " 0 mission:takeoff:ascent_t_initial_0 c 0.000000E+00 6.663289E-01 3.333333E+00 \n", + " 1 mission:takeoff:ascent_duration_0 c 1.000000E-01 1.903980E+00 1.000000E+02 \n", + " 2 tau_gear_0 c 1.000000E-02 1.986843E-01 1.000000E+00 \n", + " 3 tau_flaps_0 c 1.000000E-02 9.999990E-01 1.000000E+00 u\n", + " 4 mission:design:gross_mass_0 c 5.714286E-05 9.998350E-01 2.285714E+00 \n", + " 5 mission:summary:gross_mass_0 c 5.714286E-05 9.998349E-01 2.285714E+00 \n", + " 6 traj.accel.t_duration_0 c 1.000000E-03 2.212205E-02 2.000000E-01 \n", + " 7 traj.accel.states:TAS_0 c 0.000000E+00 4.861863E-01 1.200000E+00 \n", + " 8 traj.accel.states:TAS_1 c 0.000000E+00 8.822185E-01 1.200000E+00 \n", + " 9 traj.accel.states:TAS_2 c 0.000000E+00 1.005468E+00 1.200000E+00 \n", + " 10 traj.accel.states:mass_0 c 0.000000E+00 1.157434E+00 6.666667E+15 \n", + " 11 traj.accel.states:mass_1 c 0.000000E+00 1.157276E+00 6.666667E+15 \n", + " 12 traj.accel.states:mass_2 c 0.000000E+00 1.157225E+00 6.666667E+15 \n", + " 13 traj.accel.states:distance_0 c 0.000000E+00 2.927784E-01 3.000000E+01 \n", + " 14 traj.accel.states:distance_1 c 0.000000E+00 4.219190E-01 3.000000E+01 \n", + " 15 traj.accel.states:distance_2 c 0.000000E+00 6.122452E-01 3.000000E+01 \n", + " 16 traj.accel.states:distance_3 c 0.000000E+00 6.753987E-01 3.000000E+01 \n", + " 17 traj.ascent.states:flight_path_angle_0 c -1.000000E+01 2.360690E-02 2.000000E+01 \n", + " 18 traj.ascent.states:flight_path_angle_1 c -1.000000E+01 3.040127E-02 2.000000E+01 \n", + " 19 traj.ascent.states:flight_path_angle_2 c -1.000000E+01 3.345939E-02 2.000000E+01 \n", + " 20 traj.ascent.states:flight_path_angle_3 c -1.000000E+01 5.069081E-02 2.000000E+01 \n", + " 21 traj.ascent.states:flight_path_angle_4 c -1.000000E+01 8.385235E-02 2.000000E+01 \n", + " 22 traj.ascent.states:flight_path_angle_5 c -1.000000E+01 9.279566E-02 2.000000E+01 \n", + " 23 traj.ascent.states:flight_path_angle_6 c -1.000000E+01 1.061651E-01 2.000000E+01 \n", + " 24 traj.ascent.states:flight_path_angle_7 c -1.000000E+01 1.229399E-01 2.000000E+01 \n", + " 25 traj.ascent.states:flight_path_angle_8 c -1.000000E+01 1.316649E-01 2.000000E+01 \n", + " 26 traj.ascent.states:flight_path_angle_9 c -1.000000E+01 1.589271E-01 2.000000E+01 \n", + " 27 traj.ascent.states:flight_path_angle_10 c -1.000000E+01 1.719337E-01 2.000000E+01 \n", + " 28 traj.ascent.states:flight_path_angle_11 c -1.000000E+01 1.595008E-01 2.000000E+01 \n", + " 29 traj.ascent.states:altitude_0 c 0.000000E+00 3.528809E-02 7.000000E-01 \n", + " 30 traj.ascent.states:altitude_1 c 0.000000E+00 8.599337E-02 7.000000E-01 \n", + " 31 traj.ascent.states:altitude_2 c 0.000000E+00 9.915362E-02 7.000000E-01 \n", + " 32 traj.ascent.states:altitude_3 c 0.000000E+00 1.318988E-01 7.000000E-01 \n", + " 33 traj.ascent.states:altitude_4 c 0.000000E+00 1.860149E-01 7.000000E-01 \n", + " 34 traj.ascent.states:altitude_5 c 0.000000E+00 2.066068E-01 7.000000E-01 \n", + " 35 traj.ascent.states:altitude_6 c 0.000000E+00 2.541925E-01 7.000000E-01 \n", + " 36 traj.ascent.states:altitude_7 c 0.000000E+00 3.201926E-01 7.000000E-01 \n", + " 37 traj.ascent.states:altitude_8 c 0.000000E+00 3.408680E-01 7.000000E-01 \n", + " 38 traj.ascent.states:altitude_9 c 0.000000E+00 3.960025E-01 7.000000E-01 \n", + " 39 traj.ascent.states:altitude_10 c 0.000000E+00 4.769747E-01 7.000000E-01 \n", + " 40 traj.ascent.states:altitude_11 c 0.000000E+00 5.000000E-01 7.000000E-01 \n", + " 41 traj.ascent.states:TAS_0 c 0.000000E+00 7.698851E-01 3.500000E+00 \n", + " 42 traj.ascent.states:TAS_1 c 0.000000E+00 7.849464E-01 3.500000E+00 \n", + " 43 traj.ascent.states:TAS_2 c 0.000000E+00 7.908113E-01 3.500000E+00 \n", + " 44 traj.ascent.states:TAS_3 c 0.000000E+00 8.027727E-01 3.500000E+00 \n", + " 45 traj.ascent.states:TAS_4 c 0.000000E+00 8.157842E-01 3.500000E+00 \n", + " 46 traj.ascent.states:TAS_5 c 0.000000E+00 8.187634E-01 3.500000E+00 \n", + " 47 traj.ascent.states:TAS_6 c 0.000000E+00 8.257023E-01 3.500000E+00 \n", + " 48 traj.ascent.states:TAS_7 c 0.000000E+00 8.351067E-01 3.500000E+00 \n", + " 49 traj.ascent.states:TAS_8 c 0.000000E+00 8.379758E-01 3.500000E+00 \n", + " 50 traj.ascent.states:TAS_9 c 0.000000E+00 8.416706E-01 3.500000E+00 \n", + " 51 traj.ascent.states:TAS_10 c 0.000000E+00 8.458506E-01 3.500000E+00 \n", + " 52 traj.ascent.states:TAS_11 c 0.000000E+00 8.485488E-01 3.500000E+00 \n", + " 53 traj.ascent.states:mass_0 c 0.000000E+00 1.157581E+00 6.666667E+15 \n", + " 54 traj.ascent.states:mass_1 c 0.000000E+00 1.157576E+00 6.666667E+15 \n", + " 55 traj.ascent.states:mass_2 c 0.000000E+00 1.157575E+00 6.666667E+15 \n", + " 56 traj.ascent.states:mass_3 c 0.000000E+00 1.157571E+00 6.666667E+15 \n", + " 57 traj.ascent.states:mass_4 c 0.000000E+00 1.157567E+00 6.666667E+15 \n", + " 58 traj.ascent.states:mass_5 c 0.000000E+00 1.157565E+00 6.666667E+15 \n", + " 59 traj.ascent.states:mass_6 c 0.000000E+00 1.157562E+00 6.666667E+15 \n", + " 60 traj.ascent.states:mass_7 c 0.000000E+00 1.157557E+00 6.666667E+15 \n", + " 61 traj.ascent.states:mass_8 c 0.000000E+00 1.157556E+00 6.666667E+15 \n", + " 62 traj.ascent.states:mass_9 c 0.000000E+00 1.157553E+00 6.666667E+15 \n", + " 63 traj.ascent.states:mass_10 c 0.000000E+00 1.157549E+00 6.666667E+15 \n", + " 64 traj.ascent.states:mass_11 c 0.000000E+00 1.157547E+00 6.666667E+15 \n", + " 65 traj.ascent.states:distance_0 c 0.000000E+00 4.893272E-01 1.500000E+00 \n", + " 66 traj.ascent.states:distance_1 c 0.000000E+00 5.458208E-01 1.500000E+00 \n", + " 67 traj.ascent.states:distance_2 c 0.000000E+00 5.635920E-01 1.500000E+00 \n", + " 68 traj.ascent.states:distance_3 c 0.000000E+00 6.042240E-01 1.500000E+00 \n", + " 69 traj.ascent.states:distance_4 c 0.000000E+00 6.597467E-01 1.500000E+00 \n", + " 70 traj.ascent.states:distance_5 c 0.000000E+00 6.771180E-01 1.500000E+00 \n", + " 71 traj.ascent.states:distance_6 c 0.000000E+00 7.164507E-01 1.500000E+00 \n", + " 72 traj.ascent.states:distance_7 c 0.000000E+00 7.697374E-01 1.500000E+00 \n", + " 73 traj.ascent.states:distance_8 c 0.000000E+00 7.863637E-01 1.500000E+00 \n", + " 74 traj.ascent.states:distance_9 c 0.000000E+00 8.237919E-01 1.500000E+00 \n", + " 75 traj.ascent.states:distance_10 c 0.000000E+00 8.739409E-01 1.500000E+00 \n", + " 76 traj.ascent.states:distance_11 c 0.000000E+00 8.894776E-01 1.500000E+00 \n", + " 77 traj.ascent.controls:alpha_0 c -6.000000E+00 9.525205E-01 6.000000E+00 \n", + " 78 traj.ascent.controls:alpha_1 c -6.000000E+00 6.452198E-01 6.000000E+00 \n", + " 79 traj.ascent.controls:alpha_2 c -6.000000E+00 5.707324E-01 6.000000E+00 \n", + " 80 traj.ascent.controls:alpha_3 c -6.000000E+00 6.315962E-01 6.000000E+00 \n", + " 81 traj.ascent.controls:alpha_4 c -6.000000E+00 7.611327E-01 6.000000E+00 \n", + " 82 traj.ascent.controls:alpha_5 c -6.000000E+00 7.549333E-01 6.000000E+00 \n", + " 83 traj.ascent.controls:alpha_6 c -6.000000E+00 7.082950E-01 6.000000E+00 \n", + " 84 traj.ascent.controls:alpha_7 c -6.000000E+00 6.317224E-01 6.000000E+00 \n", + " 85 traj.ascent.controls:alpha_8 c -6.000000E+00 7.060758E-01 6.000000E+00 \n", + " 86 traj.ascent.controls:alpha_9 c -6.000000E+00 7.730952E-01 6.000000E+00 \n", + " 87 traj.ascent.controls:alpha_10 c -6.000000E+00 8.061957E-01 6.000000E+00 \n", + " 88 traj.ascent.controls:alpha_11 c -6.000000E+00 3.780179E-01 6.000000E+00 \n", + " 89 traj.climb1.t_duration_0 c 3.000000E-02 1.356431E-01 3.000000E-01 \n", + " 90 traj.climb1.states:altitude_0 c 4.000000E-02 3.912255E-01 1.100000E+00 \n", + " 91 traj.climb1.states:altitude_1 c 4.000000E-02 8.557734E-01 1.100000E+00 \n", + " 92 traj.climb1.states:altitude_2 c 4.000000E-02 1.000000E+00 1.100000E+00 \n", + " 93 traj.climb1.states:mass_0 c 0.000000E+00 1.156777E+00 6.666667E+15 \n", + " 94 traj.climb1.states:mass_1 c 0.000000E+00 1.156200E+00 6.666667E+15 \n", + " 95 traj.climb1.states:mass_2 c 0.000000E+00 1.156027E+00 6.666667E+15 \n", + " 96 traj.climb1.states:distance_0 c 0.000000E+00 7.954574E-01 5.000000E+01 \n", + " 97 traj.climb1.states:distance_1 c 0.000000E+00 1.438757E+00 5.000000E+01 \n", + " 98 traj.climb1.states:distance_2 c 0.000000E+00 1.645332E+00 5.000000E+01 \n", + " 99 traj.climb2.t_duration_0 c 4.000000E-02 2.490175E-01 3.400000E+00 \n", + " 100 traj.climb2.states:altitude_0 c 3.000000E-01 4.725790E-01 1.333333E+00 \n", + " 101 traj.climb2.states:altitude_1 c 3.000000E-01 6.468055E-01 1.333333E+00 \n", + " 102 traj.climb2.states:altitude_2 c 3.000000E-01 6.984855E-01 1.333333E+00 \n", + " 103 traj.climb2.states:altitude_3 c 3.000000E-01 8.110606E-01 1.333333E+00 \n", + " 104 traj.climb2.states:altitude_4 c 3.000000E-01 9.523468E-01 1.333333E+00 \n", + " 105 traj.climb2.states:altitude_5 c 3.000000E-01 9.951949E-01 1.333333E+00 \n", + " 106 traj.climb2.states:altitude_6 c 3.000000E-01 1.091361E+00 1.333333E+00 \n", + " 107 traj.climb2.states:altitude_7 c 3.000000E-01 1.213786E+00 1.333333E+00 \n", + " 108 traj.climb2.states:altitude_8 c 3.000000E-01 1.250000E+00 1.333333E+00 \n", + " 109 traj.climb2.states:mass_0 c 0.000000E+00 1.147127E+00 6.666667E+15 \n", + " 110 traj.climb2.states:mass_1 c 0.000000E+00 1.146197E+00 6.666667E+15 \n", + " 111 traj.climb2.states:mass_2 c 0.000000E+00 1.145931E+00 6.666667E+15 \n", + " 112 traj.climb2.states:mass_3 c 0.000000E+00 1.145338E+00 6.666667E+15 \n", + " 113 traj.climb2.states:mass_4 c 0.000000E+00 1.144607E+00 6.666667E+15 \n", + " 114 traj.climb2.states:mass_5 c 0.000000E+00 1.144386E+00 6.666667E+15 \n", + " 115 traj.climb2.states:mass_6 c 0.000000E+00 1.143888E+00 6.666667E+15 \n", + " 116 traj.climb2.states:mass_7 c 0.000000E+00 1.143253E+00 6.666667E+15 \n", + " 117 traj.climb2.states:mass_8 c 0.000000E+00 1.143067E+00 6.666667E+15 \n", + " 118 traj.climb2.states:distance_0 c 2.000000E-02 4.292125E-02 2.000000E+00 \n", + " 119 traj.climb2.states:distance_1 c 2.000000E-02 5.798145E-02 2.000000E+00 \n", + " 120 traj.climb2.states:distance_2 c 2.000000E-02 6.302122E-02 2.000000E+00 \n", + " 121 traj.climb2.states:distance_3 c 2.000000E-02 7.502213E-02 2.000000E+00 \n", + " 122 traj.climb2.states:distance_4 c 2.000000E-02 9.248009E-02 2.000000E+00 \n", + " 123 traj.climb2.states:distance_5 c 2.000000E-02 9.818311E-02 2.000000E+00 \n", + " 124 traj.climb2.states:distance_6 c 2.000000E-02 1.116167E-01 2.000000E+00 \n", + " 125 traj.climb2.states:distance_7 c 2.000000E-02 1.299764E-01 2.000000E+00 \n", + " 126 traj.climb2.states:distance_8 c 2.000000E-02 1.354385E-01 2.000000E+00 \n", + " 127 traj.cruise.t_initial_0 c 1.000000E-01 1.711600E+00 5.000000E+00 \n", + " 128 traj.cruise.t_duration_0 c -1.000000E+00 -6.919790E-01 -2.000000E-04 \n", + " 129 traj.desc1.t_duration_0 c 3.000000E-01 5.212906E-01 9.000000E-01 \n", + " 130 traj.desc1.states:altitude_0 c 3.333333E-02 1.147024E+00 1.333333E+00 \n", + " 131 traj.desc1.states:altitude_1 c 3.333333E-02 1.003060E+00 1.333333E+00 \n", + " 132 traj.desc1.states:altitude_2 c 3.333333E-02 9.567620E-01 1.333333E+00 \n", + " 133 traj.desc1.states:altitude_3 c 3.333333E-02 8.490486E-01 1.333333E+00 \n", + " 134 traj.desc1.states:altitude_4 c 3.333333E-02 6.947753E-01 1.333333E+00 \n", + " 135 traj.desc1.states:altitude_5 c 3.333333E-02 6.441368E-01 1.333333E+00 \n", + " 136 traj.desc1.states:altitude_6 c 3.333333E-02 5.317612E-01 1.333333E+00 \n", + " 137 traj.desc1.states:altitude_7 c 3.333333E-02 3.804288E-01 1.333333E+00 \n", + " 138 traj.desc1.states:altitude_8 c 3.333333E-02 3.333333E-01 1.333333E+00 \n", + " 139 traj.desc1.states:mass_0 c 0.000000E+00 9.730119E-01 7.142857E+15 \n", + " 140 traj.desc1.states:mass_1 c 0.000000E+00 9.729825E-01 7.142857E+15 \n", + " 141 traj.desc1.states:mass_2 c 0.000000E+00 9.729722E-01 7.142857E+15 \n", + " 142 traj.desc1.states:mass_3 c 0.000000E+00 9.729461E-01 7.142857E+15 \n", + " 143 traj.desc1.states:mass_4 c 0.000000E+00 9.729039E-01 7.142857E+15 \n", + " 144 traj.desc1.states:mass_5 c 0.000000E+00 9.728887E-01 7.142857E+15 \n", + " 145 traj.desc1.states:mass_6 c 0.000000E+00 9.728518E-01 7.142857E+15 \n", + " 146 traj.desc1.states:mass_7 c 0.000000E+00 9.727954E-01 7.142857E+15 \n", + " 147 traj.desc1.states:mass_8 c 0.000000E+00 9.727761E-01 7.142857E+15 \n", + " 148 traj.desc1.states:distance_0 c 8.163265E-01 9.393802E-01 1.360544E+00 \n", + " 149 traj.desc1.states:distance_1 c 8.163265E-01 9.449362E-01 1.360544E+00 \n", + " 150 traj.desc1.states:distance_2 c 8.163265E-01 9.466988E-01 1.360544E+00 \n", + " 151 traj.desc1.states:distance_3 c 8.163265E-01 9.507412E-01 1.360544E+00 \n", + " 152 traj.desc1.states:distance_4 c 8.163265E-01 9.563368E-01 1.360544E+00 \n", + " 153 traj.desc1.states:distance_5 c 8.163265E-01 9.581130E-01 1.360544E+00 \n", + " 154 traj.desc1.states:distance_6 c 8.163265E-01 9.621343E-01 1.360544E+00 \n", + " 155 traj.desc1.states:distance_7 c 8.163265E-01 9.676189E-01 1.360544E+00 \n", + " 156 traj.desc1.states:distance_8 c 8.163265E-01 9.693414E-01 1.360544E+00 \n", + " 157 traj.desc2.t_duration_0 c 2.000000E-01 9.590130E-01 1.000000E+01 \n", + " 158 traj.desc2.states:altitude_0 c -5.555556E-02 9.248982E-01 1.111111E+00 \n", + " 159 traj.desc2.states:altitude_1 c -5.555556E-02 7.639805E-01 1.111111E+00 \n", + " 160 traj.desc2.states:altitude_2 c -5.555556E-02 5.515687E-01 1.111111E+00 \n", + " 161 traj.desc2.states:altitude_3 c -5.555556E-02 3.307153E-01 1.111111E+00 \n", + " 162 traj.desc2.states:altitude_4 c -5.555556E-02 1.446192E-01 1.111111E+00 \n", + " 163 traj.desc2.states:altitude_5 c -5.555556E-02 2.854545E-02 1.111111E+00 \n", + " 164 traj.desc2.states:altitude_6 c -5.555556E-02 -1.444509E-12 1.111111E+00 \n", + " 165 traj.desc2.states:mass_0 c 0.000000E+00 9.079066E-01 6.666667E+15 \n", + " 166 traj.desc2.states:mass_1 c 0.000000E+00 9.078670E-01 6.666667E+15 \n", + " 167 traj.desc2.states:mass_2 c 0.000000E+00 9.078113E-01 6.666667E+15 \n", + " 168 traj.desc2.states:mass_3 c 0.000000E+00 9.077490E-01 6.666667E+15 \n", + " 169 traj.desc2.states:mass_4 c 0.000000E+00 9.076930E-01 6.666667E+15 \n", + " 170 traj.desc2.states:mass_5 c 0.000000E+00 9.076565E-01 6.666667E+15 \n", + " 171 traj.desc2.states:mass_6 c 0.000000E+00 9.076473E-01 6.666667E+15 \n", + " 172 traj.desc2.states:distance_0 c 0.000000E+00 1.020174E+00 1.428571E+00 \n", + " 173 traj.desc2.states:distance_1 c 0.000000E+00 1.025272E+00 1.428571E+00 \n", + " 174 traj.desc2.states:distance_2 c 0.000000E+00 1.032063E+00 1.428571E+00 \n", + " 175 traj.desc2.states:distance_3 c 0.000000E+00 1.039193E+00 1.428571E+00 \n", + " 176 traj.desc2.states:distance_4 c 0.000000E+00 1.045256E+00 1.428571E+00 \n", + " 177 traj.desc2.states:distance_5 c 0.000000E+00 1.049061E+00 1.428571E+00 \n", + " 178 traj.desc2.states:distance_6 c 0.000000E+00 1.050000E+00 1.428571E+00 \n", + " 179 traj.groundroll.t_duration_0 c 2.000000E-02 7.774100E-01 2.000000E+00 \n", + " 180 traj.groundroll.states:TAS_0 c 0.000000E+00 3.546835E-01 6.666667E+00 \n", + " 181 traj.groundroll.states:TAS_1 c 0.000000E+00 8.192727E-01 6.666667E+00 \n", + " 182 traj.groundroll.states:TAS_2 c 0.000000E+00 9.603467E-01 6.666667E+00 \n", + " 183 traj.groundroll.states:mass_0 c 0.000000E+00 1.157869E+00 6.666667E+15 \n", + " 184 traj.groundroll.states:mass_1 c 0.000000E+00 1.157776E+00 6.666667E+15 \n", + " 185 traj.groundroll.states:mass_2 c 0.000000E+00 1.157647E+00 6.666667E+15 \n", + " 186 traj.groundroll.states:mass_3 c 0.000000E+00 1.157606E+00 6.666667E+15 \n", + " 187 traj.groundroll.states:distance_0 c 0.000000E+00 1.489693E-01 3.333333E+00 \n", + " 188 traj.groundroll.states:distance_1 c 0.000000E+00 5.480568E-01 3.333333E+00 \n", + " 189 traj.groundroll.states:distance_2 c 0.000000E+00 7.145455E-01 3.333333E+00 \n", + " 190 traj.rotation.t_duration_0 c 2.000000E-02 8.819567E-02 2.000000E+00 \n", + " 191 traj.rotation.states:alpha_0 c 0.000000E+00 1.075149E-02 1.000000E+00 \n", + " 192 traj.rotation.states:alpha_1 c 0.000000E+00 1.592364E-02 1.000000E+00 \n", + " 193 traj.rotation.states:alpha_2 c 0.000000E+00 1.756065E-02 1.000000E+00 \n", + " 194 traj.rotation.states:TAS_0 c 0.000000E+00 1.467531E+00 1.000000E+01 \n", + " 195 traj.rotation.states:TAS_1 c 0.000000E+00 1.505432E+00 1.000000E+01 \n", + " 196 traj.rotation.states:TAS_2 c 0.000000E+00 1.517320E+00 1.000000E+01 \n", + " 197 traj.rotation.states:mass_0 c 0.000000E+00 1.157598E+00 6.666667E+15 \n", + " 198 traj.rotation.states:mass_1 c 0.000000E+00 1.157587E+00 6.666667E+15 \n", + " 199 traj.rotation.states:mass_2 c 0.000000E+00 1.157584E+00 6.666667E+15 \n", + " 200 traj.rotation.states:distance_0 c 0.000000E+00 8.364062E-01 2.000000E+00 \n", + " 201 traj.rotation.states:distance_1 c 0.000000E+00 8.816494E-01 2.000000E+00 \n", + " 202 traj.rotation.states:distance_2 c 0.000000E+00 8.961355E-01 2.000000E+00 \n", + "\n", + " Constraints (i - inequality, e - equality)\n", + " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", + " 0 h_fit.h_init_gear e 1.000000E+00 -7.673254E+00 1.000000E+00 E 9.00000E+100\n", + " 1 h_fit.h_init_flaps e 1.000000E+00 -1.910130E-01 1.000000E+00 E 9.00000E+100\n", + " 2 mission:constraints:range_residual e 0.000000E+00 9.431005E-10 0.000000E+00 9.00000E+100\n", + " 3 groundroll_boundary.TAS e 0.000000E+00 -1.529849E-02 0.000000E+00 E 9.00000E+100\n", + " 4 gtow_constraint.GTOW e 0.000000E+00 8.019436E-08 0.000000E+00 9.00000E+100\n", + " 5 link_taxi_groundroll.mass e 0.000000E+00 -1.082345E-01 0.000000E+00 E 9.00000E+100\n", + " 6 mission:constraints:mass_residual e 0.000000E+00 5.861874E-03 0.000000E+00 E 9.00000E+100\n", + " 7 traj.linkages.rotation:alpha_final|ascent:alpha_initial e 0.000000E+00 9.360302E-05 0.000000E+00 E 9.00000E+100\n", + " 8 traj.linkages.ascent:distance_final|accel:distance_initial e 0.000000E+00 -1.288790E-11 0.000000E+00 9.00000E+100\n", + " 9 traj.linkages.climb2:mass_final|cruise:mass_initial e 0.000000E+00 3.000972E-03 0.000000E+00 E 9.00000E+100\n", + " 10 traj.phases.accel->final_boundary_constraint->EAS e 1.000000E+00 9.949266E-01 1.000000E+00 E 9.00000E+100\n", + " 11 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 4.202854E-02 0.000000E+00 E 9.00000E+100\n", + " 12 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 4.105398E-02 0.000000E+00 E 9.00000E+100\n", + " 13 traj.accel.collocation_constraint.defects:TAS e 0.000000E+00 4.292782E-02 0.000000E+00 E 9.00000E+100\n", + " 14 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.112674E-04 0.000000E+00 E 9.00000E+100\n", + " 15 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.123894E-04 0.000000E+00 E 9.00000E+100\n", + " 16 traj.accel.collocation_constraint.defects:mass e 0.000000E+00 1.139086E-04 0.000000E+00 E 9.00000E+100\n", + " 17 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 7.234443E-02 0.000000E+00 E 9.00000E+100\n", + " 18 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 6.503089E-02 0.000000E+00 E 9.00000E+100\n", + " 19 traj.accel.collocation_constraint.defects:distance e 0.000000E+00 5.501194E-02 0.000000E+00 E 9.00000E+100\n", + " 20 traj.phases.ascent->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 21 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.422690E-01 0.000000E+00 E 9.00000E+100\n", + " 22 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.320765E-01 0.000000E+00 E 9.00000E+100\n", + " 23 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.238205E-01 0.000000E+00 E 9.00000E+100\n", + " 24 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.236970E-01 0.000000E+00 E 9.00000E+100\n", + " 25 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.232805E-01 0.000000E+00 E 9.00000E+100\n", + " 26 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.173854E-01 0.000000E+00 E 9.00000E+100\n", + " 27 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.140920E-01 0.000000E+00 E 9.00000E+100\n", + " 28 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.076273E-01 0.000000E+00 E 9.00000E+100\n", + " 29 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.053536E-01 0.000000E+00 E 9.00000E+100\n", + " 30 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.064095E-01 0.000000E+00 E 9.00000E+100\n", + " 31 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 2.047183E-01 0.000000E+00 E 9.00000E+100\n", + " 32 traj.ascent.collocation_constraint.defects:flight_path_angle e 0.000000E+00 1.838454E-01 0.000000E+00 E 9.00000E+100\n", + " 33 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 4.376839E-02 0.000000E+00 E 9.00000E+100\n", + " 34 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 3.889346E-02 0.000000E+00 E 9.00000E+100\n", + " 35 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 2.679024E-02 0.000000E+00 E 9.00000E+100\n", + " 36 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 2.298666E-02 0.000000E+00 E 9.00000E+100\n", + " 37 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 1.613087E-02 0.000000E+00 E 9.00000E+100\n", + " 38 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 8.330021E-03 0.000000E+00 E 9.00000E+100\n", + " 39 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 5.469934E-03 0.000000E+00 E 9.00000E+100\n", + " 40 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -2.877066E-03 0.000000E+00 E 9.00000E+100\n", + " 41 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -1.532406E-02 0.000000E+00 E 9.00000E+100\n", + " 42 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -1.851911E-02 0.000000E+00 E 9.00000E+100\n", + " 43 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -2.397713E-02 0.000000E+00 E 9.00000E+100\n", + " 44 traj.ascent.collocation_constraint.defects:altitude e 0.000000E+00 -3.855669E-02 0.000000E+00 E 9.00000E+100\n", + " 45 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.662088E-02 0.000000E+00 E 9.00000E+100\n", + " 46 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.352679E-02 0.000000E+00 E 9.00000E+100\n", + " 47 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.851361E-02 0.000000E+00 E 9.00000E+100\n", + " 48 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.709857E-02 0.000000E+00 E 9.00000E+100\n", + " 49 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.453933E-02 0.000000E+00 E 9.00000E+100\n", + " 50 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.161423E-02 0.000000E+00 E 9.00000E+100\n", + " 51 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -1.055806E-02 0.000000E+00 E 9.00000E+100\n", + " 52 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -7.629152E-03 0.000000E+00 E 9.00000E+100\n", + " 53 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -3.594065E-03 0.000000E+00 E 9.00000E+100\n", + " 54 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -2.577067E-03 0.000000E+00 E 9.00000E+100\n", + " 55 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 -7.133023E-04 0.000000E+00 E 9.00000E+100\n", + " 56 traj.ascent.collocation_constraint.defects:TAS e 0.000000E+00 4.081281E-03 0.000000E+00 E 9.00000E+100\n", + " 57 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.378800E-05 0.000000E+00 E 9.00000E+100\n", + " 58 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.382985E-05 0.000000E+00 E 9.00000E+100\n", + " 59 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.382364E-05 0.000000E+00 E 9.00000E+100\n", + " 60 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.379057E-05 0.000000E+00 E 9.00000E+100\n", + " 61 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.383271E-05 0.000000E+00 E 9.00000E+100\n", + " 62 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.382356E-05 0.000000E+00 E 9.00000E+100\n", + " 63 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.378701E-05 0.000000E+00 E 9.00000E+100\n", + " 64 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.385800E-05 0.000000E+00 E 9.00000E+100\n", + " 65 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.385324E-05 0.000000E+00 E 9.00000E+100\n", + " 66 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.381060E-05 0.000000E+00 E 9.00000E+100\n", + " 67 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.390402E-05 0.000000E+00 E 9.00000E+100\n", + " 68 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 5.390676E-05 0.000000E+00 E 9.00000E+100\n", + " 69 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -2.664678E-03 0.000000E+00 E 9.00000E+100\n", + " 70 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -3.914933E-03 0.000000E+00 E 9.00000E+100\n", + " 71 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -5.639292E-03 0.000000E+00 E 9.00000E+100\n", + " 72 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -6.151455E-03 0.000000E+00 E 9.00000E+100\n", + " 73 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -7.361568E-03 0.000000E+00 E 9.00000E+100\n", + " 74 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -9.108046E-03 0.000000E+00 E 9.00000E+100\n", + " 75 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -9.684546E-03 0.000000E+00 E 9.00000E+100\n", + " 76 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.099362E-02 0.000000E+00 E 9.00000E+100\n", + " 77 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.278417E-02 0.000000E+00 E 9.00000E+100\n", + " 78 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.335192E-02 0.000000E+00 E 9.00000E+100\n", + " 79 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.472174E-02 0.000000E+00 E 9.00000E+100\n", + " 80 traj.ascent.collocation_constraint.defects:distance e 0.000000E+00 -1.660071E-02 0.000000E+00 E 9.00000E+100\n", + " 81 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 -3.980793E-10 0.000000E+00 9.00000E+100\n", + " 82 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 2.209845E-09 0.000000E+00 9.00000E+100\n", + " 83 traj.ascent.continuity_comp.defect_control_rates:alpha_rate e 0.000000E+00 3.808057E-09 0.000000E+00 9.00000E+100\n", + " 84 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 5.753061E-09 0.000000E+00 9.00000E+100\n", + " 85 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 2.457302E-08 0.000000E+00 9.00000E+100\n", + " 86 traj.ascent.continuity_comp.defect_controls:alpha e 0.000000E+00 1.571372E-08 0.000000E+00 9.00000E+100\n", + " 87 traj.phases.climb1->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 88 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 9.071308E-02 0.000000E+00 E 9.00000E+100\n", + " 89 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 9.447156E-02 0.000000E+00 E 9.00000E+100\n", + " 90 traj.climb1.collocation_constraint.defects:altitude e 0.000000E+00 1.130860E-01 0.000000E+00 E 9.00000E+100\n", + " 91 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 1.055655E-03 0.000000E+00 E 9.00000E+100\n", + " 92 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 9.989756E-04 0.000000E+00 E 9.00000E+100\n", + " 93 traj.climb1.collocation_constraint.defects:mass e 0.000000E+00 9.223484E-04 0.000000E+00 E 9.00000E+100\n", + " 94 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 1.698051E-01 0.000000E+00 E 9.00000E+100\n", + " 95 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 1.544559E-01 0.000000E+00 E 9.00000E+100\n", + " 96 traj.climb1.collocation_constraint.defects:distance e 0.000000E+00 1.311562E-01 0.000000E+00 E 9.00000E+100\n", + " 97 traj.phases.climb2->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 98 traj.phases.climb2->final_boundary_constraint->mach e 8.000000E-01 8.000000E-01 8.000000E-01 9.00000E+100\n", + " 99 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.579133E-01 0.000000E+00 E 9.00000E+100\n", + " 100 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.401012E-01 0.000000E+00 E 9.00000E+100\n", + " 101 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -1.106180E-01 0.000000E+00 E 9.00000E+100\n", + " 102 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -9.840772E-02 0.000000E+00 E 9.00000E+100\n", + " 103 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -7.637198E-02 0.000000E+00 E 9.00000E+100\n", + " 104 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -4.132898E-02 0.000000E+00 E 9.00000E+100\n", + " 105 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 -2.638984E-02 0.000000E+00 E 9.00000E+100\n", + " 106 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 3.408285E-03 0.000000E+00 E 9.00000E+100\n", + " 107 traj.climb2.collocation_constraint.defects:altitude e 0.000000E+00 5.699044E-02 0.000000E+00 E 9.00000E+100\n", + " 108 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 -1.699362E-02 0.000000E+00 E 9.00000E+100\n", + " 109 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 -1.203943E-03 0.000000E+00 E 9.00000E+100\n", + " 110 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 3.845217E-03 0.000000E+00 E 9.00000E+100\n", + " 111 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.697633E-03 0.000000E+00 E 9.00000E+100\n", + " 112 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.554055E-03 0.000000E+00 E 9.00000E+100\n", + " 113 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.325253E-03 0.000000E+00 E 9.00000E+100\n", + " 114 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.238527E-03 0.000000E+00 E 9.00000E+100\n", + " 115 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 2.080800E-03 0.000000E+00 E 9.00000E+100\n", + " 116 traj.climb2.collocation_constraint.defects:mass e 0.000000E+00 1.786942E-03 0.000000E+00 E 9.00000E+100\n", + " 117 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -2.251188E-02 0.000000E+00 E 9.00000E+100\n", + " 118 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -2.392211E-02 0.000000E+00 E 9.00000E+100\n", + " 119 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -2.607250E-02 0.000000E+00 E 9.00000E+100\n", + " 120 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -2.680535E-02 0.000000E+00 E 9.00000E+100\n", + " 121 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -2.857679E-02 0.000000E+00 E 9.00000E+100\n", + " 122 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.127094E-02 0.000000E+00 E 9.00000E+100\n", + " 123 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.219105E-02 0.000000E+00 E 9.00000E+100\n", + " 124 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.443245E-02 0.000000E+00 E 9.00000E+100\n", + " 125 traj.climb2.collocation_constraint.defects:distance e 0.000000E+00 -3.487377E-02 0.000000E+00 E 9.00000E+100\n", + " 126 traj.phases.desc1->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 127 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -2.995787E-02 0.000000E+00 E 9.00000E+100\n", + " 128 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -2.729299E-02 0.000000E+00 E 9.00000E+100\n", + " 129 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -1.955422E-02 0.000000E+00 E 9.00000E+100\n", + " 130 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -1.637241E-02 0.000000E+00 E 9.00000E+100\n", + " 131 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -7.774740E-03 0.000000E+00 E 9.00000E+100\n", + " 132 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 3.813592E-03 0.000000E+00 E 9.00000E+100\n", + " 133 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 9.033048E-04 0.000000E+00 E 9.00000E+100\n", + " 134 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -5.459134E-03 0.000000E+00 E 9.00000E+100\n", + " 135 traj.desc1.collocation_constraint.defects:altitude e 0.000000E+00 -1.365492E-02 0.000000E+00 E 9.00000E+100\n", + " 136 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 -5.965159E-03 0.000000E+00 E 9.00000E+100\n", + " 137 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 -1.209201E-03 0.000000E+00 E 9.00000E+100\n", + " 138 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 3.742452E-04 0.000000E+00 E 9.00000E+100\n", + " 139 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 7.377422E-05 0.000000E+00 E 9.00000E+100\n", + " 140 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 8.412177E-05 0.000000E+00 E 9.00000E+100\n", + " 141 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 9.926342E-05 0.000000E+00 E 9.00000E+100\n", + " 142 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.027776E-04 0.000000E+00 E 9.00000E+100\n", + " 143 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.115648E-04 0.000000E+00 E 9.00000E+100\n", + " 144 traj.desc1.collocation_constraint.defects:mass e 0.000000E+00 1.251597E-04 0.000000E+00 E 9.00000E+100\n", + " 145 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 -3.389489E+00 0.000000E+00 E 9.00000E+100\n", + " 146 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 -6.377799E-01 0.000000E+00 E 9.00000E+100\n", + " 147 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 2.717641E-01 0.000000E+00 E 9.00000E+100\n", + " 148 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 9.473588E-02 0.000000E+00 E 9.00000E+100\n", + " 149 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 9.369777E-02 0.000000E+00 E 9.00000E+100\n", + " 150 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 9.323599E-02 0.000000E+00 E 9.00000E+100\n", + " 151 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 9.510829E-02 0.000000E+00 E 9.00000E+100\n", + " 152 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 9.914566E-02 0.000000E+00 E 9.00000E+100\n", + " 153 traj.desc1.collocation_constraint.defects:distance e 0.000000E+00 1.042120E-01 0.000000E+00 E 9.00000E+100\n", + " 154 traj.phases.desc2->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 155 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 8.756788E-02 0.000000E+00 E 9.00000E+100\n", + " 156 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 8.211682E-02 0.000000E+00 E 9.00000E+100\n", + " 157 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 7.040623E-02 0.000000E+00 E 9.00000E+100\n", + " 158 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 5.532126E-02 0.000000E+00 E 9.00000E+100\n", + " 159 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 3.985860E-02 0.000000E+00 E 9.00000E+100\n", + " 160 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 2.711817E-02 0.000000E+00 E 9.00000E+100\n", + " 161 traj.desc2.collocation_constraint.defects:altitude e 0.000000E+00 1.924199E-02 0.000000E+00 E 9.00000E+100\n", + " 162 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 3.248458E-04 0.000000E+00 E 9.00000E+100\n", + " 163 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 3.311964E-04 0.000000E+00 E 9.00000E+100\n", + " 164 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 3.460895E-04 0.000000E+00 E 9.00000E+100\n", + " 165 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 3.662714E-04 0.000000E+00 E 9.00000E+100\n", + " 166 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 3.891705E-04 0.000000E+00 E 9.00000E+100\n", + " 167 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 4.094219E-04 0.000000E+00 E 9.00000E+100\n", + " 168 traj.desc2.collocation_constraint.defects:mass e 0.000000E+00 4.228676E-04 0.000000E+00 E 9.00000E+100\n", + " 169 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.734014E-01 0.000000E+00 E 9.00000E+100\n", + " 170 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.748468E-01 0.000000E+00 E 9.00000E+100\n", + " 171 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.778952E-01 0.000000E+00 E 9.00000E+100\n", + " 172 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.818172E-01 0.000000E+00 E 9.00000E+100\n", + " 173 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.857735E-01 0.000000E+00 E 9.00000E+100\n", + " 174 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.890114E-01 0.000000E+00 E 9.00000E+100\n", + " 175 traj.desc2.collocation_constraint.defects:distance e 0.000000E+00 3.909870E-01 0.000000E+00 E 9.00000E+100\n", + " 176 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 -1.183504E-01 0.000000E+00 E 9.00000E+100\n", + " 177 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 -7.468176E-02 0.000000E+00 E 9.00000E+100\n", + " 178 traj.groundroll.collocation_constraint.defects:TAS e 0.000000E+00 1.461444E-03 0.000000E+00 E 9.00000E+100\n", + " 179 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 3.337212E-04 0.000000E+00 E 9.00000E+100\n", + " 180 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 3.369527E-04 0.000000E+00 E 9.00000E+100\n", + " 181 traj.groundroll.collocation_constraint.defects:mass e 0.000000E+00 3.414340E-04 0.000000E+00 E 9.00000E+100\n", + " 182 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 1.161956E-01 0.000000E+00 E 9.00000E+100\n", + " 183 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 -2.832254E-01 0.000000E+00 E 9.00000E+100\n", + " 184 traj.groundroll.collocation_constraint.defects:distance e 0.000000E+00 -8.354978E-01 0.000000E+00 E 9.00000E+100\n", + " 185 traj.phases.rotation->final_boundary_constraint->normal_force e 0.000000E+00 5.885612E+00 0.000000E+00 E 9.00000E+100\n", + " 186 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -2.843081E-03 0.000000E+00 E 9.00000E+100\n", + " 187 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -1.666288E-02 0.000000E+00 E 9.00000E+100\n", + " 188 traj.rotation.collocation_constraint.defects:alpha e 0.000000E+00 -2.123711E-02 0.000000E+00 E 9.00000E+100\n", + " 189 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -3.467974E-02 0.000000E+00 E 9.00000E+100\n", + " 190 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -3.291650E-02 0.000000E+00 E 9.00000E+100\n", + " 191 traj.rotation.collocation_constraint.defects:TAS e 0.000000E+00 -3.158894E-02 0.000000E+00 E 9.00000E+100\n", + " 192 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 4.294338E-05 0.000000E+00 E 9.00000E+100\n", + " 193 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 4.299013E-05 0.000000E+00 E 9.00000E+100\n", + " 194 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 4.303371E-05 0.000000E+00 E 9.00000E+100\n", + " 195 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 8.764329E-01 0.000000E+00 E 9.00000E+100\n", + " 196 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 1.342207E-01 0.000000E+00 E 9.00000E+100\n", + " 197 traj.rotation.collocation_constraint.defects:distance e 0.000000E+00 -1.129866E-01 0.000000E+00 E 9.00000E+100\n", + " 198 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.742054E-01 1.100000E+00 9.00000E+100\n", + " 199 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.669844E-01 1.100000E+00 9.00000E+100\n", + " 200 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.480818E-01 1.100000E+00 9.00000E+100\n", + " 201 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.709240E-01 1.100000E+00 9.00000E+100\n", + " 202 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.709240E-01 1.100000E+00 9.00000E+100\n", + " 203 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.213843E-01 1.100000E+00 9.00000E+100\n", + " 204 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.296702E-01 1.100000E+00 9.00000E+100\n", + " 205 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.160906E-01 1.100000E+00 9.00000E+100\n", + " 206 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.160907E-01 1.100000E+00 9.00000E+100\n", + " 207 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.946641E-01 1.100000E+00 9.00000E+100\n", + " 208 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.279602E-01 1.100000E+00 9.00000E+100\n", + " 209 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.544860E-01 1.100000E+00 9.00000E+100\n", + " 210 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.544861E-01 1.100000E+00 9.00000E+100\n", + " 211 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 3.704937E-01 1.100000E+00 9.00000E+100\n", + " 212 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 2.169131E-01 1.100000E+00 9.00000E+100\n", + " 213 traj.phases.ascent->path_constraint->load_factor i 0.000000E+00 1.256349E-01 1.100000E+00 9.00000E+100\n", + " 214 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.262602E+00 1.500000E+01 9.00000E+100\n", + " 215 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.078675E+00 1.500000E+01 9.00000E+100\n", + " 216 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.095527E+00 1.500000E+01 9.00000E+100\n", + " 217 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.575063E+00 1.500000E+01 9.00000E+100\n", + " 218 traj.phases.ascent->path_constraint->theta i 0.000000E+00 3.575063E+00 1.500000E+01 9.00000E+100\n", + " 219 traj.phases.ascent->path_constraint->theta i 0.000000E+00 5.210033E+00 1.500000E+01 9.00000E+100\n", + " 220 traj.phases.ascent->path_constraint->theta i 0.000000E+00 7.079052E+00 1.500000E+01 9.00000E+100\n", + " 221 traj.phases.ascent->path_constraint->theta i 0.000000E+00 7.358273E+00 1.500000E+01 9.00000E+100\n", + " 222 traj.phases.ascent->path_constraint->theta i 0.000000E+00 7.358275E+00 1.500000E+01 9.00000E+100\n", + " 223 traj.phases.ascent->path_constraint->theta i 0.000000E+00 7.741424E+00 1.500000E+01 9.00000E+100\n", + " 224 traj.phases.ascent->path_constraint->theta i 0.000000E+00 9.074316E+00 1.500000E+01 9.00000E+100\n", + " 225 traj.phases.ascent->path_constraint->theta i 0.000000E+00 9.909319E+00 1.500000E+01 9.00000E+100\n", + " 226 traj.phases.ascent->path_constraint->theta i 0.000000E+00 9.909320E+00 1.500000E+01 9.00000E+100\n", + " 227 traj.phases.ascent->path_constraint->theta i 0.000000E+00 1.163683E+01 1.500000E+01 9.00000E+100\n", + " 228 traj.phases.ascent->path_constraint->theta i 0.000000E+00 1.024117E+01 1.500000E+01 9.00000E+100\n", + " 229 traj.phases.ascent->path_constraint->theta i 0.000000E+00 8.278860E+00 1.500000E+01 9.00000E+100\n", + " 230 traj.phases.climb2->final_boundary_constraint->altitude_rate i 1.000000E-01 3.369349E+02 1.000000E+30 9.00000E+100\n", + "\n", + "\n", + " Exit Status\n", + " Inform Description\n", + " -1 Maximum Iterations Exceeded\n", + "--------------------------------------------------------------------------------\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "prob.run_aviary_problem()" ] @@ -546,10 +2088,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "cb152e48", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Zero Fuel Mass (lbm) [0.]\n", + "Mission.Objectives.FUEL [5.01686139]\n", + "Mission.Design.FUEL_MASS [43235.82667616]\n", + "Mission.Design.FUEL_MASS_REQUIRED [43235.82667616]\n", + "Mission.Summary.TOTAL_FUEL_MASS [43822.01406862]\n", + "Mission.Summary.GROSS_MASS (takeoff_mass) [174971.10305558]\n", + "Mission.Landing.TOUCHDOWN_MASS (final_mass) [136147.08898696]\n", + "\n", + "Groundroll Final Mass (lbm) [173640.93424536]\n", + "Rotation Final Mass (lbm) [173637.58677183]\n", + "Ascent Final Mass (lbm) [173632.10142675]\n", + "Accel Final Mass (lbm) [173583.75432292]\n", + "Climb1 Final Mass (lbm) [173404.08534669]\n", + "Climb2 Final Mass (lbm) [171460.12339658]\n", + "Cruise Final Mass (lbm) 136561.07448090267\n", + "Desc1 Final Mass (lbm) [136188.65336602]\n", + "Desc2 Final Mass (lbm) [136147.08898696]\n", + "done\n" + ] + } + ], "source": [ "print(\"Zero Fuel Mass (lbm)\",\n", " prob.get_val(Aircraft.Design.ZERO_FUEL_MASS, units='lbm'))\n", @@ -608,10 +2175,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "0da2bfee", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"/home/john/anaconda3/envs/dev/bin/aviary\", line 8, in \n", + " sys.exit(aviary_cmd())\n", + " File \"/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/interface/cmd_entry_points.py\", line 141, in aviary_cmd\n", + " options.executor(options, user_args)\n", + " File \"/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/interface/methods_for_level1.py\", line 236, in _exec_level1\n", + " prob = run_level_1(\n", + " File \"/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/interface/methods_for_level1.py\", line 158, in run_level_1\n", + " prob = run_aviary(input_deck, phase_info, mission_method=mission_method,\n", + " File \"/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/interface/methods_for_level1.py\", line 70, in run_aviary\n", + " prob = AviaryProblem(phase_info, mission_method, mass_method, analysis_scheme)\n", + " File \"/mnt/c/Users/John/Dropbox/git/om-Aviary/aviary/interface/methods_for_level2.py\", line 147, in __init__\n", + " raise NotImplementedError(\n", + "NotImplementedError: The FLOPS mission method is no longer supported in Aviary. Please use the `simple` mission method. This might require updating your `phase_info` object defintion.\n" + ] + } + ], "source": [ "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --mission_method FLOPS --mass_origin FLOPS --max_iter 0 --optimizer IPOPT" ] @@ -628,10 +2216,107 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "807902e2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:touchdown_mass\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fins:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuel:total_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:landing_gear:main_gear_oleo_length\n", + " 'aircraft:landing_gear:nose_gear_oleo_length\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:control_surface_area\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- cruise ---\n", + " [initial] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " [final] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, history.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/driver.py:469: DriverWarning:The following design variable initial conditions are out of their specified bounds:\n", + " traj.cruise.t_duration\n", + " val: [1800.]\n", + " lower: 600.0\n", + " upper: 1799.9999999999998\n", + "Set the initial value of the design variable to a valid value or set the driver option['invalid_desvar_behavior'] to 'ignore'.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Full total jacobian was computed 3 times, taking 0.041699 seconds.\n", + "Total jacobian shape: (16, 13) \n", + "\n", + "\n", + "Jacobian shape: (16, 13) (31.73% nonzero)\n", + "FWD solves: 6 REV solves: 0\n", + "Total colors vs. total size: 6 vs 13 (53.85% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 0.0417 sec\n", + "Time to compute coloring: 0.0076 sec\n", + "Memory to compute coloring: 0.0000 MB\n", + "Coloring created on: 2024-01-09 11:26:48\n", + "Iteration limit reached (Exit mode 9)\n", + " Current function value: 0.0\n", + " Iterations: 1\n", + " Function evaluations: 1\n", + " Gradient evaluations: 1\n", + "Optimization FAILED.\n", + "Iteration limit reached\n", + "-----------------------------------\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/total_jac.py:1759: DerivativesWarning:Constraints or objectives [('traj.phases.cruise.timeseries.timeseries_comp.throttle', inds=[(0, 0)])] cannot be impacted by the design variables of the problem.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "done\n" + ] + } + ], "source": [ "phase_info = {\n", " 'pre_mission': {\n", @@ -643,32 +2328,26 @@ " 'core_aerodynamics': {'method': 'computed'}\n", " },\n", " 'user_options': {\n", - " 'fix_initial': False,\n", - " 'fix_duration': True,\n", - " 'num_segments': 1,\n", + " 'optimize_mach': False,\n", + " 'optimize_altitude': False,\n", + " 'polynomial_control_order': 1,\n", + " 'num_segments': 2,\n", " 'order': 3,\n", - " 'initial_bounds': ((500., 4000.), 's'),\n", - " 'initial_ref': (1., 's'),\n", - " 'duration_ref': (24370.8, 's'),\n", - " 'duration_bounds': ((726., 48741.6), 's'),\n", - " 'min_altitude': (10.668e3, 'm'),\n", - " 'max_altitude': (10.668e3, 'm'),\n", - " 'min_mach': 0.79,\n", - " 'max_mach': 0.79,\n", - " 'fix_final': False,\n", - " 'required_available_climb_rate': (1.524, 'm/s'),\n", - " 'mass_f_cruise': (1.e4, 'lbm'),\n", - " 'range_f_cruise': (1.e6, 'm'),\n", + " 'solve_for_range': False,\n", + " 'initial_mach': (0.72, 'unitless'),\n", + " 'final_mach': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", + " 'initial_altitude': (35000.0, 'ft'),\n", + " 'final_altitude': (35000.0, 'ft'),\n", + " 'altitude_bounds': ((23000.0, 38000.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'fix_initial': True,\n", + " 'constrain_final': False,\n", + " 'fix_duration': False,\n", + " 'initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'duration_bounds': ((10., 30.), 'min'),\n", " },\n", - " 'initial_guesses': {\n", - " 'times': ([26.2, 406.18], 'min'),\n", - " 'altitude': ([35.e3, 35.e3], 'ft'),\n", - " 'velocity': ([455.49, 455.49], 'kn'),\n", - " 'mass': ([165.e3, 140.e3], 'lbm'),\n", - " 'range': ([160.3, 3243.9], 'nmi'),\n", - " 'velocity_rate': ([0., 0.], 'm/s**2'),\n", - " 'throttle': ([0.95, 0.9], 'unitless'),\n", - " }\n", + " 'initial_guesses': {'times': ([0, 30], 'min')},\n", " },\n", " 'post_mission': {\n", " 'include_landing': False,\n", @@ -677,7 +2356,7 @@ "\n", "# inputs that run_aviary() requires\n", "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_FwFm.csv\"\n", - "mission_method = \"FLOPS\"\n", + "mission_method = \"simple\"\n", "mass_method = \"FLOPS\"\n", "optimizer = \"SLSQP\"\n", "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", @@ -731,33 +2410,8 @@ "\n", "We will see more details for what users can do in [level 3](onboarding_level3.ipynb).\n", "\n", - "Level 2 is where you can integrate user-defined [external subsystems](https://github.com/OpenMDAO/Aviary/blob/main/aviary/docs/user_guide/subsystems.md), which is one of the main features of the Aviary tool. [Examples](https://github.com/OpenMDAO/Aviary/blob/main/aviary/docs/user_guide/using_external_subsystems.md) of external subsystems are: acoustics, battery modeling, etc.\n", - "Assume that you already have an external subsystem that you want to incorporate it into your model. We show how to add external subsystems via `external_subsystems` key in `phase_info`. External subsystems can be added in all phases. For example, we can have:\n", - "\n", - "```\n", - "from aviary.subsystems.test.test_dummy_subsystem import PreOnlyBuilder, PostOnlyBuilder, \\\n", - " ArrayGuessSubsystemBuilder, AdditionalArrayGuessSubsystemBuilder\n", - "\n", - "phase_info = {\n", - "\t'pre_mission': {\n", - "\t\t'include_takeoff': True,\n", - "\t\t'external_subsystems': [ArrayGuessSubsystemBuilder()],\n", - "\t\t'optimize_mass': False,\n", - "\t},\n", - "\t'cruise': {\n", - "\t\t...\n", - " 'external_subsystems': \n", - " [\n", - " ArrayGuessSubsystemBuilder(),\n", - " AdditionalArrayGuessSubsystemBuilder()\n", - " ],\n", - "\t},\n", - "\t'post_mission': {\n", - "\t\t'include_landing': False,\n", - "\t\t'external_subsystems': [PostOnlyBuilder()],\n", - "\t}\n", - "}\n", - "```\n", + "Level 2 is where you can integrate user-defined [external subsystems](../user_guide/subsystems.md), which is one of the main features of the Aviary tool. [Examples](../user_guide/using_external_subsystems.md) of external subsystems are: acoustics, battery modeling, etc.\n", + "Assume that you already have an external subsystem that you want to incorporate it into your model. We show how to add external subsystems via `external_subsystems` key in `phase_info`.\n", "\n", "We will cover external subsystems in details in [Models with External Subsystems](onboarding_ext_subsystem.ipynb) page.\n" ] @@ -782,7 +2436,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "8ad02f55", "metadata": {}, "outputs": [], @@ -805,7 +2459,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "7481beb5", "metadata": {}, "outputs": [], @@ -826,10 +2480,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "15027bcc", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'aircraft:blended_wing_body_design:num_bays': (0, 'unitless'), 'aircraft:crew_and_payload:mass_per_passenger': (165.0, 'lbm'), 'aircraft:crew_and_payload:num_business_class': (0, 'unitless'), 'aircraft:crew_and_payload:num_first_class': (0, 'unitless'), 'aircraft:crew_and_payload:num_passengers': (180, 'unitless'), 'aircraft:crew_and_payload:num_tourist_class': (0, 'unitless'), 'aircraft:crew_and_payload:passenger_mass_with_bags': (200, 'lbm'), 'aircraft:design:compute_htail_volume_coeff': (False, 'unitless'), 'aircraft:design:compute_vtail_volume_coeff': (False, 'unitless'), 'aircraft:design:part25_structural_category': (3, 'unitless'), 'aircraft:design:reserves': (4998, 'unitless'), 'aircraft:design:smooth_mass_discontinuities': (False, 'unitless'), 'aircraft:design:ulf_calculated_from_maneuver': (False, 'unitless'), 'aircraft:design:use_alt_mass': (False, 'unitless'), 'aircraft:electrical:has_hybrid_system': (False, 'unitless'), 'aircraft:engine:constant_fuel_consumption': (array([0.]), 'lbm/h'), 'aircraft:engine:flight_idle_max_fraction': (array([1.]), 'unitless'), 'aircraft:engine:flight_idle_min_fraction': (array([0.08]), 'unitless'), 'aircraft:engine:flight_idle_thrust_fraction': (array([0.]), 'unitless'), 'aircraft:engine:fuel_flow_scaler_constant_term': (array([0.]), 'unitless'), 'aircraft:engine:fuel_flow_scaler_linear_term': (array([0.]), 'unitless'), 'aircraft:engine:generate_flight_idle': ([False], 'unitless'), 'aircraft:engine:geopotential_alt': ([False], 'unitless'), 'aircraft:engine:has_propellers': ([False], 'unitless'), 'aircraft:engine:ignore_negative_thrust': ([False], 'unitless'), 'aircraft:engine:interpolation_method': (['slinear'], 'unitless'), 'aircraft:engine:num_engines': (array([2]), 'unitless'), 'aircraft:engine:num_fuselage_engines': (array([0]), 'unitless'), 'aircraft:engine:num_wing_engines': (array([2]), 'unitless'), 'aircraft:engine:scale_mass': ([True], 'unitless'), 'aircraft:engine:scale_performance': ([True], 'unitless'), 'aircraft:engine:subsonic_fuel_flow_scaler': (array([1.]), 'unitless'), 'aircraft:engine:supersonic_fuel_flow_scaler': (array([1.]), 'unitless'), 'aircraft:engine:type': ([], 'unitless'), 'aircraft:fins:num_fins': (0, 'unitless'), 'aircraft:fuel:num_tanks': (7, 'unitless'), 'aircraft:fuselage:aisle_width': (24, 'inch'), 'aircraft:fuselage:military_cargo_floor': (False, 'unitless'), 'aircraft:fuselage:num_aisles': (1, 'unitless'), 'aircraft:fuselage:num_fuselages': (1, 'unitless'), 'aircraft:fuselage:num_seats_abreast': (6, 'unitless'), 'aircraft:fuselage:provide_surface_area': (True, 'unitless'), 'aircraft:fuselage:seat_pitch': (29, 'inch'), 'aircraft:fuselage:seat_width': (20.2, 'inch'), 'aircraft:landing_gear:carrier_based': (False, 'unitless'), 'aircraft:landing_gear:drag_coefficient': (0.0, 'unitless'), 'aircraft:landing_gear:fixed_gear': (False, 'unitless'), 'aircraft:strut:dimensional_location_specified': (False, 'unitless'), 'aircraft:vertical_tail:num_tails': (1, 'unitless'), 'aircraft:wing:airfoil_technology': (1.0, 'unitless'), 'aircraft:wing:choose_fold_location': (True, 'unitless'), 'aircraft:wing:detailed_wing': (False, 'unitless'), 'aircraft:wing:flap_type': (, 'unitless'), 'aircraft:wing:fold_dimensional_location_specified': (False, 'unitless'), 'aircraft:wing:has_fold': (False, 'unitless'), 'aircraft:wing:has_strut': (False, 'unitless'), 'aircraft:wing:load_distribution_control': (2.0, 'unitless'), 'aircraft:wing:loading_above_20': (True, 'unitless'), 'aircraft:wing:num_flap_segments': (2, 'unitless'), 'aircraft:wing:num_integration_stations': (50, 'unitless'), 'aircraft:wing:span_efficiency_reduction': (False, 'unitless'), 'mission:design:cruise_altitude': (37500, 'ft'), 'mission:design:rate_of_climb_at_top_of_climb': (0.0, 'ft/min'), 'mission:summary:fuel_flow_scaler': (1, 'unitless'), 'mission:takeoff:angle_of_attack_runway': (0.0, 'deg'), 'mission:takeoff:obstacle_height': (35.0, 'ft'), 'mission:takeoff:thrust_incidence': (0.0, 'deg'), 'mission:taxi:duration': (0.1677, 'h'), 'mission:taxi:mach': (0.0001, 'unitless'), 'debug_mode': (False, 'unitless'), 'INGASP.JENGSZ': (4, 'unitless'), 'test_mode': (False, 'unitless'), 'use_surrogates': (True, 'unitless'), 'mass_defect': (10000, 'lbm'), 'problem_type': (, 'unitless'), 'aircraft:controls:cockpit_control_mass_scaler': (1, 'unitless'), 'aircraft:controls:control_mass_increment': (0, 'lbm'), 'aircraft:controls:stability_augmentation_system_mass': (0, 'lbm'), 'aircraft:controls:stability_augmentation_system_mass_scaler': (1, 'unitless'), 'aircraft:crew_and_payload:cargo_mass': (10040, 'lbm'), 'aircraft:design:cg_delta': (0.25, 'unitless'), 'aircraft:design:cockpit_control_mass_coefficient': (16.5, 'unitless'), 'aircraft:design:drag_increment': (0.00175, 'unitless'), 'aircraft:design:equipment_mass_coefficients': ([928, 0.0736, 0.112, 0.14, 1959, 1.65, 551, 11192, 5, 3, 50, 7.6, 12], 'unitless'), 'aircraft:design:max_structural_speed': (402.5, 'mi/h'), 'aircraft:design:static_margin': (0.03, 'unitless'), 'aircraft:design:structural_mass_increment': (0, 'lbm'), 'aircraft:design:supercritical_drag_shift': (0.033, 'unitless'), 'aircraft:engine:additional_mass_fraction': (array([0.135]), 'unitless'), 'aircraft:engine:data_file': (['models/engines/turbofan_23k_1.deck'], 'unitless'), 'aircraft:engine:mass_scaler': (array([1]), 'unitless'), 'aircraft:engine:mass_specific': (array([0.21366]), 'lbm/lbf'), 'aircraft:engine:pod_mass_scaler': (array([1]), 'unitless'), 'aircraft:engine:pylon_factor': (array([1.25]), 'unitless'), 'aircraft:engine:reference_diameter': (array([5.8]), 'ft'), 'aircraft:engine:reference_sls_thrust': (array([28690]), 'lbf'), 'aircraft:engine:scale_factor': (array([1]), 'unitless'), 'aircraft:engine:scaled_sls_thrust': (array([28690]), 'lbf'), 'aircraft:engine:wing_locations': (array([0.35]), 'unitless'), 'aircraft:fuel:density': (6.687, 'lbm/galUS'), 'aircraft:fuel:fuel_margin': (0, 'unitless'), 'aircraft:fuel:fuel_system_mass_coefficient': (0.041, 'unitless'), 'aircraft:fuel:fuel_system_mass_scaler': (1, 'unitless'), 'aircraft:fuel:wing_fuel_fraction': (0.6, 'unitless'), 'aircraft:fuselage:delta_diameter': (4.5, 'ft'), 'aircraft:fuselage:flat_plate_area_increment': (0.25, 'ft**2'), 'aircraft:fuselage:form_factor': (1.25, 'unitless'), 'aircraft:fuselage:mass_coefficient': (128, 'unitless'), 'aircraft:fuselage:nose_fineness': (1, 'unitless'), 'aircraft:fuselage:pilot_compartment_length': (9.5, 'ft'), 'aircraft:fuselage:pressure_differential': (7.5, 'psi'), 'aircraft:fuselage:tail_fineness': (3, 'unitless'), 'aircraft:fuselage:wetted_area_factor': (4000, 'unitless'), 'aircraft:horizontal_tail:area': (0, 'ft**2'), 'aircraft:horizontal_tail:aspect_ratio': (4.75, 'unitless'), 'aircraft:horizontal_tail:form_factor': (1.25, 'unitless'), 'aircraft:horizontal_tail:mass_coefficient': (0.232, 'unitless'), 'aircraft:horizontal_tail:moment_ratio': (0.2307, 'unitless'), 'aircraft:horizontal_tail:sweep': (25, 'deg'), 'aircraft:horizontal_tail:taper_ratio': (0.352, 'unitless'), 'aircraft:horizontal_tail:thickness_to_chord': (0.12, 'unitless'), 'aircraft:horizontal_tail:vertical_tail_fraction': (0, 'unitless'), 'aircraft:horizontal_tail:volume_coefficient': (1.189, 'unitless'), 'aircraft:landing_gear:main_gear_location': (0.15, 'unitless'), 'aircraft:landing_gear:main_gear_mass_coefficient': (0.85, 'unitless'), 'aircraft:landing_gear:mass_coefficient': (0.04, 'unitless'), 'aircraft:landing_gear:tail_hook_mass_scaler': (1, 'unitless'), 'aircraft:landing_gear:total_mass_scaler': (1, 'unitless'), 'aircraft:nacelle:clearance_ratio': (array([0.2]), 'unitless'), 'aircraft:nacelle:core_diameter_ratio': (array([1.25]), 'unitless'), 'aircraft:nacelle:fineness': (array([2]), 'unitless'), 'aircraft:nacelle:form_factor': (array([1.5]), 'unitless'), 'aircraft:nacelle:mass_specific': (array([3]), 'lbm/ft**2'), 'aircraft:strut:area_ratio': (0, 'unitless'), 'aircraft:strut:attachment_location': (0, 'ft'), 'aircraft:strut:attachment_location_dimensionless': (0, 'unitless'), 'aircraft:strut:fuselage_interference_factor': (0, 'unitless'), 'aircraft:strut:mass_coefficient': (0, 'unitless'), 'aircraft:strut:thickness_to_chord': (0, 'unitless'), 'aircraft:vertical_tail:area': (0, 'ft**2'), 'aircraft:vertical_tail:aspect_ratio': (1.67, 'unitless'), 'aircraft:vertical_tail:form_factor': (1.25, 'unitless'), 'aircraft:vertical_tail:mass_coefficient': (0.289, 'unitless'), 'aircraft:vertical_tail:moment_ratio': (2.362, 'unitless'), 'aircraft:vertical_tail:sweep': (35, 'deg'), 'aircraft:vertical_tail:taper_ratio': (0.801, 'unitless'), 'aircraft:vertical_tail:thickness_to_chord': (0.12, 'unitless'), 'aircraft:vertical_tail:volume_coefficient': (0.145, 'unitless'), 'aircraft:wing:aspect_ratio': (10.13, 'unitless'), 'aircraft:wing:center_distance': (0.463, 'unitless'), 'aircraft:wing:flap_chord_ratio': (0.3, 'unitless'), 'aircraft:wing:flap_deflection_landing': (40, 'deg'), 'aircraft:wing:flap_deflection_takeoff': (10, 'deg'), 'aircraft:wing:flap_drag_increment_optimum': (0.1, 'unitless'), 'aircraft:wing:flap_lift_increment_optimum': (1.5, 'unitless'), 'aircraft:wing:flap_span_ratio': (0.65, 'unitless'), 'aircraft:wing:fold_mass_coefficient': (0, 'unitless'), 'aircraft:wing:folded_span': (0, 'ft'), 'aircraft:wing:form_factor': (1.25, 'unitless'), 'aircraft:wing:fuselage_interference_factor': (1.1, 'unitless'), 'aircraft:wing:height': (8, 'ft'), 'aircraft:wing:high_lift_mass_coefficient': (1.9, 'unitless'), 'aircraft:wing:incidence': (1.5, 'deg'), 'aircraft:wing:loading': (128, 'lbf/ft**2'), 'aircraft:wing:mass_coefficient': (102.5, 'unitless'), 'aircraft:wing:max_lift_ref': (1.15, 'unitless'), 'aircraft:wing:max_slat_deflection_landing': (10, 'deg'), 'aircraft:wing:max_slat_deflection_takeoff': (10, 'deg'), 'aircraft:wing:max_thickness_location': (0.4, 'unitless'), 'aircraft:wing:min_pressure_location': (0.3, 'unitless'), 'aircraft:wing:mounting_type': (0, 'unitless'), 'aircraft:wing:optimum_flap_deflection': (55, 'deg'), 'aircraft:wing:optimum_slat_deflection': (20, 'deg'), 'aircraft:wing:slat_chord_ratio': (0.15, 'unitless'), 'aircraft:wing:slat_lift_increment_optimum': (0.93, 'unitless'), 'aircraft:wing:surface_ctrl_mass_coefficient': (0.95, 'unitless'), 'aircraft:wing:sweep': (25, 'deg'), 'aircraft:wing:taper_ratio': (0.33, 'unitless'), 'aircraft:wing:thickness_to_chord_root': (0.15, 'unitless'), 'aircraft:wing:thickness_to_chord_tip': (0.12, 'unitless'), 'aircraft:wing:zero_lift_angle': (-1.2, 'deg'), 'mission:design:gross_mass': (175400, 'lbm'), 'mission:design:mach': (0.8, 'unitless'), 'mission:design:range': (3675, 'NM'), 'mission:landing:braking_delay': (1, 's'), 'mission:landing:glide_to_stall_ratio': (1.3, 'unitless'), 'mission:landing:maximum_flare_load_factor': (1.15, 'unitless'), 'mission:landing:maximum_sink_rate': (900, 'ft/min'), 'mission:landing:obstacle_height': (50, 'ft'), 'mission:landing:touchdown_sink_rate': (5, 'ft/s'), 'mission:takeoff:decision_speed_increment': (10, 'kn'), 'mission:takeoff:rotation_speed_increment': (5, 'kn'), 'engine_models': ([], 'unitless'), 'aircraft:propulsion:total_num_engines': (2, 'unitless'), 'aircraft:propulsion:total_num_fuselage_engines': (0, 'unitless'), 'aircraft:propulsion:total_num_wing_engines': (2, 'unitless')}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Build problem\n", "prob = av.AviaryProblem(av.default_solved_phase_info, mission_method, mass_method, analysis_scheme)\n", @@ -849,7 +2514,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "id": "5036d584", "metadata": {}, "outputs": [], @@ -869,10 +2534,686 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "id": "502d1eda", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.speeds' : d(*)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(max_mach)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(density_ratio)/d(max_airspeed): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.params' : d(V9)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.design_load.factors' : d(aircraft:wing:ultimate_load_factor)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.fixed_mass.params' : d(c_gear_loc)/d(aircraft:landing_gear:main_gear_location): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_useful_load)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'pre_mission.core_subsystems.core_mass.equip_and_useful_mass' : d(aircraft:design:fixed_equipment_mass)/d(*): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2185: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.groundroll': initial_ref\n", + " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.eoms' : d(alpha_rate)/d(('*',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:engine:scale_factor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.ascent: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb_at_constant_EAS: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb_at_constant_EAS_to_mach: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb_at_constant_TAS: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.climb_at_constant_mach: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.cruise: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.descent: The following timeseries outputs were requested but not found in the ODE: flap_factor, gear_factor\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/pseudospectral/components/state_independents.py:80: OpenMDAOWarning:: State mass has bounds but they are not enforced when using `solve_segments.` Apply a path constraint to mass to enforce bounds.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/pseudospectral/components/state_independents.py:80: OpenMDAOWarning:: State range has bounds but they are not enforced when using `solve_segments.` Apply a path constraint to range to enforce bounds.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/utils/introspection.py:924: OpenMDAOWarning:traj.phases.groundroll: The following timeseries outputs were requested but not found in the ODE: altitude, thrust_req\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.groundroll' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: True\n", + " input initial: False\n", + " Setting `traj.phases.groundroll.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.groundroll.nonlinear_solver to override.\n", + " Setting `traj.phases.groundroll.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.groundroll.linear_solver to override.\n", + " Set `traj.phases.groundroll.options[\"auto_solvers\"] = False` to disable this behavior.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Constraint Report [traj] ---\n", + " --- groundroll ---\n", + " None\n", + " --- rotation ---\n", + " [final] TAS <= 2.0000e+02 [kn]\n", + " [final] 0.0000e+00 == normal_force [lbf]\n", + " [path] fuselage_pitch <= 1.5000e+01 [deg]\n", + " --- ascent_to_gear_retract ---\n", + " [path] fuselage_pitch <= 1.5000e+01 [deg]\n", + " [path] 0.0000e+00 <= load_factor <= 1.1000e+00 [unitless]\n", + " --- ascent_to_flap_retract ---\n", + " [path] 0.0000e+00 <= load_factor <= 1.1000e+00 [unitless]\n", + " --- ascent ---\n", + " [path] EAS <= 2.5000e+02 [kn]\n", + " --- climb_at_constant_TAS ---\n", + " [final] 2.5000e+02 == EAS [kn]\n", + " --- climb_at_constant_EAS ---\n", + " None\n", + " --- climb_at_constant_EAS_to_mach ---\n", + " [final] 8.0000e-01 == mach [unitless]\n", + " --- climb_at_constant_mach ---\n", + " None\n", + " --- cruise ---\n", + " None\n", + " --- descent ---\n", + " [final] 2.0000e+03 == range [NM]\n", + " [final] 1.0000e+04 == altitude [ft]\n", + " [final] 2.5000e+02 == TAS [kn]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.ascent_to_flap_retract.rhs_all.control_iter_group.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.ascent_to_gear_retract.rhs_all.control_iter_group.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.groundroll.rhs_all.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/component.py:1151: OMDeprecationWarning:'traj.phases.rotation.rhs_all.control_iter_group.core_aerodynamics.lift_coef' : d(CL_base)/d(('CL_max_flaps',)): Partial was declared to be exactly zero. This is inefficient and the declaration should be removed. In a future version of OpenMDAO this behavior will raise an error.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, aviary_history.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/driver.py:469: DriverWarning:The following design variable initial conditions are out of their specified bounds:\n", + " traj.descent.t_duration\n", + " val: [200000.]\n", + " lower: 150000.0\n", + " upper: 199999.99999999997\n", + "Set the initial value of the design variable to a valid value or set the driver option['invalid_desvar_behavior'] to 'ignore'.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "Full total jacobian was computed 3 times, taking 2.734579 seconds.\n", + "Total jacobian shape: (232, 205) \n", + "\n", + "\n", + "Jacobian shape: (232, 205) (2.59% nonzero)\n", + "FWD solves: 12 REV solves: 0\n", + "Total colors vs. total size: 12 vs 205 (94.15% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 2.7346 sec\n", + "Time to compute coloring: 0.0898 sec\n", + "Memory to compute coloring: 0.0000 MB\n", + "Coloring created on: 2024-01-09 11:27:17\n", + "\n", + "List of user-set options:\n", + "\n", + " Name Value used\n", + " alpha_for_y = safer-min-dual-infeas yes\n", + " file_print_level = 5 yes\n", + " hessian_approximation = limited-memory yes\n", + " linear_solver = mumps yes\n", + " max_iter = 1 yes\n", + " mu_init = 1e-05 yes\n", + " mu_strategy = monotone yes\n", + " nlp_scaling_method = gradient-based yes\n", + " output_file = reports/problem5/IPOPT.out yes\n", + " print_level = 5 yes\n", + " print_user_options = yes yes\n", + " sb = yes yes\n", + " tol = 1e-06 yes\n", + "This is Ipopt version 3.14.12, running with linear solver MUMPS 5.2.1.\n", + "\n", + "Number of nonzeros in equality constraint Jacobian...: 1053\n", + "Number of nonzeros in inequality constraint Jacobian.: 175\n", + "Number of nonzeros in Lagrangian Hessian.............: 0\n", + "\n", + "Total number of variables............................: 205\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 149\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 190\n", + "Total number of inequality constraints...............: 41\n", + " inequality constraints with only lower bounds: 0\n", + " inequality constraints with lower and upper bounds: 16\n", + " inequality constraints with only upper bounds: 25\n", + "\n", + "iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls\n", + " 0 -5.0098936e-03 2.25e+00 1.00e+00 -5.0 0.00e+00 - 0.00e+00 0.00e+00 0\n", + " 1 4.9419858e-02 5.00e-02 8.41e-01 -5.0 4.65e-01 - 5.70e-01 1.00e+00h 1\n", + "\n", + "Number of Iterations....: 1\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 4.9419858298412112e-02 4.9419858298412112e-02\n", + "Dual infeasibility......: 8.4107122267553258e-01 8.4107122267553258e-01\n", + "Constraint violation....: 4.9974004887564878e-02 4.9974004887564878e-02\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 1.0000007358127383e+05 1.0000007358127383e+05\n", + "Overall NLP error.......: 1.0000007358127383e+05 1.0000007358127383e+05\n", + "\n", + "\n", + "Number of objective function evaluations = 2\n", + "Number of objective gradient evaluations = 2\n", + "Number of equality constraint evaluations = 2\n", + "Number of inequality constraint evaluations = 2\n", + "Number of equality constraint Jacobian evaluations = 2\n", + "Number of inequality constraint Jacobian evaluations = 2\n", + "Number of Lagrangian Hessian evaluations = 0\n", + "Total seconds in IPOPT = 3.946\n", + "\n", + "EXIT: Maximum Number of Iterations Exceeded.\n", + "\n", + "\n", + "Optimization Problem -- Optimization using pyOpt_sparse\n", + "================================================================================\n", + " Objective Function: _objfunc\n", + "\n", + " Solution: \n", + "--------------------------------------------------------------------------------\n", + " Total Time: 3.9479\n", + " User Objective Time : 1.7465\n", + " User Sensitivity Time : 2.1768\n", + " Interface Time : 0.0177\n", + " Opt Solver Time: 0.0070\n", + " Calls to Objective Function : 3\n", + " Calls to Sens Function : 3\n", + "\n", + "\n", + " Objectives\n", + " Index Name Value\n", + " 0 obj_comp.obj 4.941986E-02\n", + "\n", + " Variables (c - continuous, i - integer, d - discrete)\n", + " Index Name Type Lower Bound Value Upper Bound Status\n", + " 0 traj.ascent.t_initial_0 c 1.000000E-02 2.459292E+00 2.000000E+02 \n", + " 1 traj.ascent.t_duration_0 c 5.000000E-01 1.007184E+00 1.000000E+01 \n", + " 2 traj.ascent.states:time_0 c -1.000000E+19 4.317144E-01 1.000000E+19 \n", + " 3 traj.ascent.states:time_1 c -1.000000E+19 4.488850E-01 1.000000E+19 \n", + " 4 traj.ascent.states:time_2 c -1.000000E+19 4.719806E-01 1.000000E+19 \n", + " 5 traj.ascent.states:time_3 c -1.000000E+19 4.791523E-01 1.000000E+19 \n", + " 6 traj.ascent.states:time_4 c -1.000000E+19 4.953339E-01 1.000000E+19 \n", + " 7 traj.ascent.states:time_5 c -1.000000E+19 5.171307E-01 1.000000E+19 \n", + " 8 traj.ascent.states:time_6 c -1.000000E+19 5.239064E-01 1.000000E+19 \n", + " 9 traj.ascent.states:mass_0 c 5.882353E-02 1.030757E+00 5.882353E+15 \n", + " 10 traj.ascent.states:mass_1 c 5.882353E-02 1.030717E+00 5.882353E+15 \n", + " 11 traj.ascent.states:mass_2 c 5.882353E-02 1.030664E+00 5.882353E+15 \n", + " 12 traj.ascent.states:mass_3 c 5.882353E-02 1.030647E+00 5.882353E+15 \n", + " 13 traj.ascent.states:mass_4 c 5.882353E-02 1.030609E+00 5.882353E+15 \n", + " 14 traj.ascent.states:mass_5 c 5.882353E-02 1.030560E+00 5.882353E+15 \n", + " 15 traj.ascent.states:mass_6 c 5.882353E-02 1.030544E+00 5.882353E+15 \n", + " 16 traj.ascent.polynomial_controls:TAS_0 c 4.000000E-03 8.012488E-01 2.000000E+00 \n", + " 17 traj.ascent.polynomial_controls:TAS_1 c 4.000000E-03 9.002717E-01 2.000000E+00 \n", + " 18 traj.ascent_to_flap_retract.t_initial_0 c 1.000000E-02 1.948640E+00 2.000000E+02 \n", + " 19 traj.ascent_to_flap_retract.t_duration_0 c 5.000000E-01 5.106520E-01 1.000000E+01 \n", + " 20 traj.ascent_to_flap_retract.states:time_0 c -1.000000E+19 3.812183E-01 1.000000E+19 \n", + " 21 traj.ascent_to_flap_retract.states:time_1 c -1.000000E+19 3.901652E-01 1.000000E+19 \n", + " 22 traj.ascent_to_flap_retract.states:time_2 c -1.000000E+19 4.025219E-01 1.000000E+19 \n", + " 23 traj.ascent_to_flap_retract.states:time_3 c -1.000000E+19 4.064361E-01 1.000000E+19 \n", + " 24 traj.ascent_to_flap_retract.states:time_4 c -1.000000E+19 4.154045E-01 1.000000E+19 \n", + " 25 traj.ascent_to_flap_retract.states:time_5 c -1.000000E+19 4.277909E-01 1.000000E+19 \n", + " 26 traj.ascent_to_flap_retract.states:time_6 c -1.000000E+19 4.317144E-01 1.000000E+19 \n", + " 27 traj.ascent_to_flap_retract.states:mass_0 c 5.882353E-02 1.030865E+00 5.882353E+15 \n", + " 28 traj.ascent_to_flap_retract.states:mass_1 c 5.882353E-02 1.030845E+00 5.882353E+15 \n", + " 29 traj.ascent_to_flap_retract.states:mass_2 c 5.882353E-02 1.030820E+00 5.882353E+15 \n", + " 30 traj.ascent_to_flap_retract.states:mass_3 c 5.882353E-02 1.030811E+00 5.882353E+15 \n", + " 31 traj.ascent_to_flap_retract.states:mass_4 c 5.882353E-02 1.030791E+00 5.882353E+15 \n", + " 32 traj.ascent_to_flap_retract.states:mass_5 c 5.882353E-02 1.030766E+00 5.882353E+15 \n", + " 33 traj.ascent_to_flap_retract.states:mass_6 c 5.882353E-02 1.030757E+00 5.882353E+15 \n", + " 34 traj.ascent_to_flap_retract.polynomial_controls:TAS_0 c 4.000000E-03 8.050453E-01 2.000000E+00 \n", + " 35 traj.ascent_to_flap_retract.polynomial_controls:TAS_1 c 4.000000E-03 8.012488E-01 2.000000E+00 \n", + " 36 traj.ascent_to_gear_retract.t_initial_0 c 1.000000E-02 1.437182E+00 2.000000E+00 \n", + " 37 traj.ascent_to_gear_retract.t_duration_0 c 5.000000E-01 5.114581E-01 1.000000E+01 \n", + " 38 traj.ascent_to_gear_retract.states:time_0 c -1.000000E+19 3.312175E-01 1.000000E+19 \n", + " 39 traj.ascent_to_gear_retract.states:time_1 c -1.000000E+19 3.401805E-01 1.000000E+19 \n", + " 40 traj.ascent_to_gear_retract.states:time_2 c -1.000000E+19 3.524854E-01 1.000000E+19 \n", + " 41 traj.ascent_to_gear_retract.states:time_3 c -1.000000E+19 3.563656E-01 1.000000E+19 \n", + " 42 traj.ascent_to_gear_retract.states:time_4 c -1.000000E+19 3.652237E-01 1.000000E+19 \n", + " 43 traj.ascent_to_gear_retract.states:time_5 c -1.000000E+19 3.773840E-01 1.000000E+19 \n", + " 44 traj.ascent_to_gear_retract.states:time_6 c -1.000000E+19 3.812183E-01 1.000000E+19 \n", + " 45 traj.ascent_to_gear_retract.states:mass_0 c 5.882353E-02 1.030972E+00 5.882353E+15 \n", + " 46 traj.ascent_to_gear_retract.states:mass_1 c 5.882353E-02 1.030952E+00 5.882353E+15 \n", + " 47 traj.ascent_to_gear_retract.states:mass_2 c 5.882353E-02 1.030927E+00 5.882353E+15 \n", + " 48 traj.ascent_to_gear_retract.states:mass_3 c 5.882353E-02 1.030918E+00 5.882353E+15 \n", + " 49 traj.ascent_to_gear_retract.states:mass_4 c 5.882353E-02 1.030898E+00 5.882353E+15 \n", + " 50 traj.ascent_to_gear_retract.states:mass_5 c 5.882353E-02 1.030874E+00 5.882353E+15 \n", + " 51 traj.ascent_to_gear_retract.states:mass_6 c 5.882353E-02 1.030865E+00 5.882353E+15 \n", + " 52 traj.ascent_to_gear_retract.polynomial_controls:TAS_0 c 4.000000E-03 7.859530E-01 2.000000E+00 \n", + " 53 traj.ascent_to_gear_retract.polynomial_controls:TAS_1 c 4.000000E-03 8.050453E-01 2.000000E+00 \n", + " 54 traj.climb_at_constant_EAS.t_initial_0 c 1.000000E-03 4.464615E-02 1.000000E+02 \n", + " 55 traj.climb_at_constant_EAS.t_duration_0 c 1.000000E-01 2.425742E-01 5.000000E-01 \n", + " 56 traj.climb_at_constant_EAS.states:time_0 c -1.000000E+19 6.053591E-01 1.000000E+19 \n", + " 57 traj.climb_at_constant_EAS.states:time_1 c -1.000000E+19 9.359677E-01 1.000000E+19 \n", + " 58 traj.climb_at_constant_EAS.states:time_2 c -1.000000E+19 1.378734E+00 1.000000E+19 \n", + " 59 traj.climb_at_constant_EAS.states:time_3 c -1.000000E+19 1.515670E+00 1.000000E+19 \n", + " 60 traj.climb_at_constant_EAS.states:time_4 c -1.000000E+19 1.823518E+00 1.000000E+19 \n", + " 61 traj.climb_at_constant_EAS.states:time_5 c -1.000000E+19 2.235380E+00 1.000000E+19 \n", + " 62 traj.climb_at_constant_EAS.states:time_6 c -1.000000E+19 2.362656E+00 1.000000E+19 \n", + " 63 traj.climb_at_constant_EAS.states:mass_0 c 5.882353E-02 1.030356E+00 5.882353E+15 \n", + " 64 traj.climb_at_constant_EAS.states:mass_1 c 5.882353E-02 1.029637E+00 5.882353E+15 \n", + " 65 traj.climb_at_constant_EAS.states:mass_2 c 5.882353E-02 1.028707E+00 5.882353E+15 \n", + " 66 traj.climb_at_constant_EAS.states:mass_3 c 5.882353E-02 1.028426E+00 5.882353E+15 \n", + " 67 traj.climb_at_constant_EAS.states:mass_4 c 5.882353E-02 1.027808E+00 5.882353E+15 \n", + " 68 traj.climb_at_constant_EAS.states:mass_5 c 5.882353E-02 1.027012E+00 5.882353E+15 \n", + " 69 traj.climb_at_constant_EAS.states:mass_6 c 5.882353E-02 1.026771E+00 5.882353E+15 \n", + " 70 traj.climb_at_constant_EAS_to_mach.t_initial_0 c 1.000000E-03 2.872203E-01 1.000000E+02 \n", + " 71 traj.climb_at_constant_EAS_to_mach.t_duration_0 c 1.000000E-01 2.670316E+00 1.000000E+01 \n", + " 72 traj.climb_at_constant_EAS_to_mach.states:time_0 c -1.000000E+19 2.362656E+00 1.000000E+19 \n", + " 73 traj.climb_at_constant_EAS_to_mach.states:time_1 c -1.000000E+19 5.204204E+00 1.000000E+19 \n", + " 74 traj.climb_at_constant_EAS_to_mach.states:time_2 c -1.000000E+19 8.829514E+00 1.000000E+19 \n", + " 75 traj.climb_at_constant_EAS_to_mach.states:time_3 c -1.000000E+19 9.907883E+00 1.000000E+19 \n", + " 76 traj.climb_at_constant_EAS_to_mach.states:time_4 c -1.000000E+19 1.225643E+01 1.000000E+19 \n", + " 77 traj.climb_at_constant_EAS_to_mach.states:time_5 c -1.000000E+19 1.523042E+01 1.000000E+19 \n", + " 78 traj.climb_at_constant_EAS_to_mach.states:time_6 c -1.000000E+19 1.610961E+01 1.000000E+19 \n", + " 79 traj.climb_at_constant_EAS_to_mach.states:mass_0 c 5.882353E-02 1.026771E+00 5.882353E+15 \n", + " 80 traj.climb_at_constant_EAS_to_mach.states:mass_1 c 5.882353E-02 1.021586E+00 5.882353E+15 \n", + " 81 traj.climb_at_constant_EAS_to_mach.states:mass_2 c 5.882353E-02 1.015594E+00 5.882353E+15 \n", + " 82 traj.climb_at_constant_EAS_to_mach.states:mass_3 c 5.882353E-02 1.013935E+00 5.882353E+15 \n", + " 83 traj.climb_at_constant_EAS_to_mach.states:mass_4 c 5.882353E-02 1.010543E+00 5.882353E+15 \n", + " 84 traj.climb_at_constant_EAS_to_mach.states:mass_5 c 5.882353E-02 1.006673E+00 5.882353E+15 \n", + " 85 traj.climb_at_constant_EAS_to_mach.states:mass_6 c 5.882353E-02 1.005622E+00 5.882353E+15 \n", + " 86 traj.climb_at_constant_EAS_to_mach.polynomial_controls:altitude_0 c -3.333333E-05 3.333333E-01 1.333333E+00 \n", + " 87 traj.climb_at_constant_EAS_to_mach.polynomial_controls:altitude_1 c -3.333333E-05 1.095259E+00 1.333333E+00 \n", + " 88 traj.climb_at_constant_TAS.t_initial_0 c 1.000000E-02 3.466476E+00 2.000000E+02 \n", + " 89 traj.climb_at_constant_TAS.t_duration_0 c 5.000000E-01 9.981389E-01 1.000000E+01 \n", + " 90 traj.climb_at_constant_TAS.states:time_0 c -1.000000E+19 5.239064E-01 1.000000E+19 \n", + " 91 traj.climb_at_constant_TAS.states:time_1 c -1.000000E+19 5.390506E-01 1.000000E+19 \n", + " 92 traj.climb_at_constant_TAS.states:time_2 c -1.000000E+19 5.594399E-01 1.000000E+19 \n", + " 93 traj.climb_at_constant_TAS.states:time_3 c -1.000000E+19 5.657757E-01 1.000000E+19 \n", + " 94 traj.climb_at_constant_TAS.states:time_4 c -1.000000E+19 5.800786E-01 1.000000E+19 \n", + " 95 traj.climb_at_constant_TAS.states:time_5 c -1.000000E+19 5.993613E-01 1.000000E+19 \n", + " 96 traj.climb_at_constant_TAS.states:time_6 c -1.000000E+19 6.053591E-01 1.000000E+19 \n", + " 97 traj.climb_at_constant_TAS.states:mass_0 c 5.882353E-02 1.030544E+00 5.882353E+15 \n", + " 98 traj.climb_at_constant_TAS.states:mass_1 c 5.882353E-02 1.030508E+00 5.882353E+15 \n", + " 99 traj.climb_at_constant_TAS.states:mass_2 c 5.882353E-02 1.030462E+00 5.882353E+15 \n", + " 100 traj.climb_at_constant_TAS.states:mass_3 c 5.882353E-02 1.030447E+00 5.882353E+15 \n", + " 101 traj.climb_at_constant_TAS.states:mass_4 c 5.882353E-02 1.030413E+00 5.882353E+15 \n", + " 102 traj.climb_at_constant_TAS.states:mass_5 c 5.882353E-02 1.030370E+00 5.882353E+15 \n", + " 103 traj.climb_at_constant_TAS.states:mass_6 c 5.882353E-02 1.030356E+00 5.882353E+15 \n", + " 104 traj.climb_at_constant_TAS.polynomial_controls:TAS_0 c 4.000000E-03 9.002717E-01 2.000000E+00 \n", + " 105 traj.climb_at_constant_TAS.polynomial_controls:TAS_1 c 4.000000E-03 1.007296E+00 2.000000E+00 \n", + " 106 traj.climb_at_constant_mach.t_initial_0 c 1.000000E-03 2.957537E+00 1.000000E+02 \n", + " 107 traj.climb_at_constant_mach.t_duration_0 c 1.000000E-01 3.063195E+00 1.000000E+01 \n", + " 108 traj.climb_at_constant_mach.states:time_0 c -1.000000E+19 1.610961E+01 1.000000E+19 \n", + " 109 traj.climb_at_constant_mach.states:time_1 c -1.000000E+19 1.838422E+01 1.000000E+19 \n", + " 110 traj.climb_at_constant_mach.states:time_2 c -1.000000E+19 2.153654E+01 1.000000E+19 \n", + " 111 traj.climb_at_constant_mach.states:time_3 c -1.000000E+19 2.253761E+01 1.000000E+19 \n", + " 112 traj.climb_at_constant_mach.states:time_4 c -1.000000E+19 2.483670E+01 1.000000E+19 \n", + " 113 traj.climb_at_constant_mach.states:time_5 c -1.000000E+19 2.801624E+01 1.000000E+19 \n", + " 114 traj.climb_at_constant_mach.states:time_6 c -1.000000E+19 2.902182E+01 1.000000E+19 \n", + " 115 traj.climb_at_constant_mach.states:mass_0 c 5.882353E-02 1.005622E+00 5.882353E+15 \n", + " 116 traj.climb_at_constant_mach.states:mass_1 c 5.882353E-02 1.003000E+00 5.882353E+15 \n", + " 117 traj.climb_at_constant_mach.states:mass_2 c 5.882353E-02 9.994947E-01 5.882353E+15 \n", + " 118 traj.climb_at_constant_mach.states:mass_3 c 5.882353E-02 9.984115E-01 5.882353E+15 \n", + " 119 traj.climb_at_constant_mach.states:mass_4 c 5.882353E-02 9.959787E-01 5.882353E+15 \n", + " 120 traj.climb_at_constant_mach.states:mass_5 c 5.882353E-02 9.927654E-01 5.882353E+15 \n", + " 121 traj.climb_at_constant_mach.states:mass_6 c 5.882353E-02 9.917915E-01 5.882353E+15 \n", + " 122 traj.climb_at_constant_mach.polynomial_controls:altitude_0 c -3.333333E-05 1.095259E+00 1.333333E+00 \n", + " 123 traj.climb_at_constant_mach.polynomial_controls:altitude_1 c -3.333333E-05 1.250000E+00 1.333333E+00 \n", + " 124 traj.cruise.t_initial_0 c 1.000000E-02 6.020731E-01 2.000000E+01 \n", + " 125 traj.cruise.t_duration_0 c 2.000000E-01 5.804812E-01 6.000000E+00 \n", + " 126 traj.cruise.states:time_0 c -1.000000E+17 2.902182E-01 1.000000E+17 \n", + " 127 traj.cruise.states:time_1 c -1.000000E+17 3.775248E-01 1.000000E+17 \n", + " 128 traj.cruise.states:time_2 c -1.000000E+17 4.979868E-01 1.000000E+17 \n", + " 129 traj.cruise.states:time_3 c -1.000000E+17 5.361142E-01 1.000000E+17 \n", + " 130 traj.cruise.states:time_4 c -1.000000E+17 6.234210E-01 1.000000E+17 \n", + " 131 traj.cruise.states:time_5 c -1.000000E+17 7.438832E-01 1.000000E+17 \n", + " 132 traj.cruise.states:time_6 c -1.000000E+17 7.820106E-01 1.000000E+17 \n", + " 133 traj.cruise.states:time_7 c -1.000000E+17 8.693176E-01 1.000000E+17 \n", + " 134 traj.cruise.states:time_8 c -1.000000E+17 9.897804E-01 1.000000E+17 \n", + " 135 traj.cruise.states:time_9 c -1.000000E+17 1.027908E+00 1.000000E+17 \n", + " 136 traj.cruise.states:time_10 c -1.000000E+17 1.115215E+00 1.000000E+17 \n", + " 137 traj.cruise.states:time_11 c -1.000000E+17 1.235679E+00 1.000000E+17 \n", + " 138 traj.cruise.states:time_12 c -1.000000E+17 1.273807E+00 1.000000E+17 \n", + " 139 traj.cruise.states:time_13 c -1.000000E+17 1.361114E+00 1.000000E+17 \n", + " 140 traj.cruise.states:time_14 c -1.000000E+17 1.481579E+00 1.000000E+17 \n", + " 141 traj.cruise.states:time_15 c -1.000000E+17 1.519707E+00 1.000000E+17 \n", + " 142 traj.cruise.states:mass_0 c 5.882353E-02 9.917915E-01 5.882353E+15 \n", + " 143 traj.cruise.states:mass_1 c 5.882353E-02 9.841493E-01 5.882353E+15 \n", + " 144 traj.cruise.states:mass_2 c 5.882353E-02 9.736073E-01 5.882353E+15 \n", + " 145 traj.cruise.states:mass_3 c 5.882353E-02 9.702696E-01 5.882353E+15 \n", + " 146 traj.cruise.states:mass_4 c 5.882353E-02 9.626275E-01 5.882353E+15 \n", + " 147 traj.cruise.states:mass_5 c 5.882353E-02 9.520856E-01 5.882353E+15 \n", + " 148 traj.cruise.states:mass_6 c 5.882353E-02 9.487480E-01 5.882353E+15 \n", + " 149 traj.cruise.states:mass_7 c 5.882353E-02 9.411059E-01 5.882353E+15 \n", + " 150 traj.cruise.states:mass_8 c 5.882353E-02 9.305640E-01 5.882353E+15 \n", + " 151 traj.cruise.states:mass_9 c 5.882353E-02 9.272264E-01 5.882353E+15 \n", + " 152 traj.cruise.states:mass_10 c 5.882353E-02 9.195842E-01 5.882353E+15 \n", + " 153 traj.cruise.states:mass_11 c 5.882353E-02 9.090421E-01 5.882353E+15 \n", + " 154 traj.cruise.states:mass_12 c 5.882353E-02 9.057044E-01 5.882353E+15 \n", + " 155 traj.cruise.states:mass_13 c 5.882353E-02 8.980620E-01 5.882353E+15 \n", + " 156 traj.cruise.states:mass_14 c 5.882353E-02 8.875195E-01 5.882353E+15 \n", + " 157 traj.cruise.states:mass_15 c 5.882353E-02 8.841817E-01 5.882353E+15 \n", + " 158 traj.descent.t_initial_0 c 1.000000E-04 3.504479E+00 1.000000E+01 \n", + " 159 traj.descent.t_duration_0 c 1.500000E+00 1.995209E+00 2.000000E+00 \n", + " 160 traj.descent.states:time_0 c -1.000000E+17 1.519707E+00 1.000000E+17 \n", + " 161 traj.descent.states:time_1 c -1.000000E+17 1.529487E+00 1.000000E+17 \n", + " 162 traj.descent.states:time_2 c -1.000000E+17 1.544005E+00 1.000000E+17 \n", + " 163 traj.descent.states:time_3 c -1.000000E+17 1.548876E+00 1.000000E+17 \n", + " 164 traj.descent.states:time_4 c -1.000000E+17 1.560601E+00 1.000000E+17 \n", + " 165 traj.descent.states:time_5 c -1.000000E+17 1.578276E+00 1.000000E+17 \n", + " 166 traj.descent.states:time_6 c -1.000000E+17 1.584282E+00 1.000000E+17 \n", + " 167 traj.descent.states:time_7 c -1.000000E+17 1.598916E+00 1.000000E+17 \n", + " 168 traj.descent.states:time_8 c -1.000000E+17 1.621505E+00 1.000000E+17 \n", + " 169 traj.descent.states:time_9 c -1.000000E+17 1.629335E+00 1.000000E+17 \n", + " 170 traj.descent.states:mass_0 c 5.882353E-02 8.841817E-01 5.882353E+15 \n", + " 171 traj.descent.states:mass_1 c 5.882353E-02 8.841099E-01 5.882353E+15 \n", + " 172 traj.descent.states:mass_2 c 5.882353E-02 8.839917E-01 5.882353E+15 \n", + " 173 traj.descent.states:mass_3 c 5.882353E-02 8.839476E-01 5.882353E+15 \n", + " 174 traj.descent.states:mass_4 c 5.882353E-02 8.838342E-01 5.882353E+15 \n", + " 175 traj.descent.states:mass_5 c 5.882353E-02 8.836446E-01 5.882353E+15 \n", + " 176 traj.descent.states:mass_6 c 5.882353E-02 8.835735E-01 5.882353E+15 \n", + " 177 traj.descent.states:mass_7 c 5.882353E-02 8.833886E-01 5.882353E+15 \n", + " 178 traj.descent.states:mass_8 c 5.882353E-02 8.830703E-01 5.882353E+15 \n", + " 179 traj.descent.states:mass_9 c 5.882353E-02 8.829497E-01 5.882353E+15 \n", + " 180 traj.descent.polynomial_controls:TAS_0 c 4.000000E-03 1.933931E+00 2.000000E+00 \n", + " 181 traj.descent.polynomial_controls:TAS_1 c 4.000000E-03 1.000000E+00 2.000000E+00 \n", + " 182 traj.descent.polynomial_controls:altitude_0 c -3.333333E-05 1.250000E+00 1.333333E+00 \n", + " 183 traj.descent.polynomial_controls:altitude_1 c -3.333333E-05 3.333333E-01 1.333333E+00 \n", + " 184 traj.groundroll.t_duration_0 c 5.000000E-01 1.275084E+00 1.000000E+01 \n", + " 185 traj.rotation.t_initial_0 c 5.000000E-02 8.501371E-01 5.000000E+00 \n", + " 186 traj.rotation.t_duration_0 c 5.000000E-02 5.870445E-01 2.000000E+00 \n", + " 187 traj.rotation.states:time_0 c -1.000000E+19 2.610672E-01 1.000000E+19 \n", + " 188 traj.rotation.states:time_1 c -1.000000E+19 2.756966E-01 1.000000E+19 \n", + " 189 traj.rotation.states:time_2 c -1.000000E+19 2.941133E-01 1.000000E+19 \n", + " 190 traj.rotation.states:time_3 c -1.000000E+19 2.995725E-01 1.000000E+19 \n", + " 191 traj.rotation.states:time_4 c -1.000000E+19 3.114718E-01 1.000000E+19 \n", + " 192 traj.rotation.states:time_5 c -1.000000E+19 3.266686E-01 1.000000E+19 \n", + " 193 traj.rotation.states:time_6 c -1.000000E+19 3.312175E-01 1.000000E+19 \n", + " 194 traj.rotation.states:mass_0 c 5.882353E-02 1.031122E+00 5.882353E+15 \n", + " 195 traj.rotation.states:mass_1 c 5.882353E-02 1.031089E+00 5.882353E+15 \n", + " 196 traj.rotation.states:mass_2 c 5.882353E-02 1.031051E+00 5.882353E+15 \n", + " 197 traj.rotation.states:mass_3 c 5.882353E-02 1.031039E+00 5.882353E+15 \n", + " 198 traj.rotation.states:mass_4 c 5.882353E-02 1.031013E+00 5.882353E+15 \n", + " 199 traj.rotation.states:mass_5 c 5.882353E-02 1.030982E+00 5.882353E+15 \n", + " 200 traj.rotation.states:mass_6 c 5.882353E-02 1.030972E+00 5.882353E+15 \n", + " 201 traj.rotation.polynomial_controls:TAS_0 c 4.000000E-03 5.100334E-01 2.000000E+00 \n", + " 202 traj.rotation.polynomial_controls:TAS_1 c 4.000000E-03 7.859530E-01 2.000000E+00 \n", + " 203 traj.rotation.polynomial_controls:alpha_0 c -4.000000E-01 1.012082E-02 1.500000E+00 \n", + " 204 traj.rotation.polynomial_controls:alpha_1 c -4.000000E-01 4.131361E-01 1.500000E+00 \n", + "\n", + " Constraints (i - inequality, e - equality)\n", + " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", + " 0 traj.linkages.ascent_to_gear_retract:time_final|ascent_to_flap_retract:time_initial e 0.000000E+00 2.612882E-10 0.000000E+00 9.00000E+100\n", + " 1 traj.linkages.ascent_to_gear_retract:mass_final|ascent_to_flap_retract:mass_initial e 0.000000E+00 -3.708701E-11 0.000000E+00 9.00000E+100\n", + " 2 traj.linkages.ascent_to_gear_retract:range_final|ascent_to_flap_retract:range_initial e 0.000000E+00 -1.016768E-09 0.000000E+00 9.00000E+100\n", + " 3 traj.linkages.ascent_to_gear_retract:TAS_final|ascent_to_flap_retract:TAS_initial e 0.000000E+00 9.981704E-13 0.000000E+00 9.00000E+100\n", + " 4 traj.linkages.ascent_to_flap_retract:time_final|ascent:time_initial e 0.000000E+00 1.838906E-10 0.000000E+00 9.00000E+100\n", + " 5 traj.linkages.ascent_to_flap_retract:mass_final|ascent:mass_initial e 0.000000E+00 -3.737514E-11 0.000000E+00 9.00000E+100\n", + " 6 traj.linkages.ascent_to_flap_retract:range_final|ascent:range_initial e 0.000000E+00 -5.813266E-10 0.000000E+00 9.00000E+100\n", + " 7 traj.linkages.ascent_to_flap_retract:TAS_final|ascent:TAS_initial e 0.000000E+00 3.759482E-12 0.000000E+00 9.00000E+100\n", + " 8 traj.linkages.climb_at_constant_EAS:altitude_final|climb_at_constant_EAS_to_mach:altitude_initial e 0.000000E+00 -2.229988E-10 0.000000E+00 9.00000E+100\n", + " 9 traj.linkages.climb_at_constant_EAS:time_final|climb_at_constant_EAS_to_mach:time_initial e 0.000000E+00 3.076860E-10 0.000000E+00 9.00000E+100\n", + " 10 traj.linkages.climb_at_constant_EAS:mass_final|climb_at_constant_EAS_to_mach:mass_initial e 0.000000E+00 -3.959867E-11 0.000000E+00 9.00000E+100\n", + " 11 traj.linkages.climb_at_constant_EAS:range_final|climb_at_constant_EAS_to_mach:range_initial e 0.000000E+00 -1.529515E-11 0.000000E+00 9.00000E+100\n", + " 12 traj.linkages.climb_at_constant_EAS_to_mach:altitude_final|climb_at_constant_mach:altitude_initial e 0.000000E+00 -1.644003E-11 0.000000E+00 9.00000E+100\n", + " 13 traj.linkages.climb_at_constant_EAS_to_mach:time_final|climb_at_constant_mach:time_initial e 0.000000E+00 -2.818933E-10 0.000000E+00 9.00000E+100\n", + " 14 traj.linkages.climb_at_constant_EAS_to_mach:mass_final|climb_at_constant_mach:mass_initial e 0.000000E+00 -4.168542E-11 0.000000E+00 9.00000E+100\n", + " 15 traj.linkages.climb_at_constant_EAS_to_mach:range_final|climb_at_constant_mach:range_initial e 0.000000E+00 -7.654307E-12 0.000000E+00 9.00000E+100\n", + " 16 traj.linkages.climb_at_constant_mach:altitude_final|cruise:altitude_initial e 0.000000E+00 -3.365130E-12 0.000000E+00 9.00000E+100\n", + " 17 traj.linkages.climb_at_constant_mach:time_final|cruise:time_initial e 0.000000E+00 1.073658E-11 0.000000E+00 9.00000E+100\n", + " 18 traj.linkages.climb_at_constant_mach:mass_final|cruise:mass_initial e 0.000000E+00 -4.561734E-11 0.000000E+00 9.00000E+100\n", + " 19 traj.linkages.climb_at_constant_mach:range_final|cruise:range_initial e 0.000000E+00 -4.435424E-12 0.000000E+00 9.00000E+100\n", + " 20 traj.linkages.cruise:altitude_final|descent:altitude_initial e 0.000000E+00 -6.111804E-14 0.000000E+00 9.00000E+100\n", + " 21 traj.linkages.cruise:time_final|descent:time_initial e 0.000000E+00 7.203198E-12 0.000000E+00 9.00000E+100\n", + " 22 traj.linkages.cruise:mass_final|descent:mass_initial e 0.000000E+00 -4.171452E-11 0.000000E+00 9.00000E+100\n", + " 23 traj.linkages.cruise:range_final|descent:range_initial e 0.000000E+00 -1.118518E-10 0.000000E+00 9.00000E+100\n", + " 24 traj.linkages.groundroll:time_final|rotation:time_initial e 0.000000E+00 2.400125E-03 0.000000E+00 E 9.00000E+100\n", + " 25 traj.linkages.groundroll:mass_final|rotation:mass_initial e 0.000000E+00 -1.127567E-04 0.000000E+00 E 9.00000E+100\n", + " 26 traj.linkages.groundroll:range_final|rotation:range_initial e 0.000000E+00 1.134792E-02 0.000000E+00 E 9.00000E+100\n", + " 27 traj.linkages.groundroll:TAS_final|rotation:TAS_initial e 0.000000E+00 -1.505480E-10 0.000000E+00 9.00000E+100\n", + " 28 traj.linkages.rotation:time_final|ascent_to_gear_retract:time_initial e 0.000000E+00 3.321197E-10 0.000000E+00 9.00000E+100\n", + " 29 traj.linkages.rotation:mass_final|ascent_to_gear_retract:mass_initial e 0.000000E+00 -3.536406E-11 0.000000E+00 9.00000E+100\n", + " 30 traj.linkages.rotation:range_final|ascent_to_gear_retract:range_initial e 0.000000E+00 -2.313537E-09 0.000000E+00 9.00000E+100\n", + " 31 traj.linkages.rotation:TAS_final|ascent_to_gear_retract:TAS_initial e 0.000000E+00 -8.480143E-11 0.000000E+00 9.00000E+100\n", + " 32 traj.linkages.ascent:time_final|climb_at_constant_TAS:time_initial e 0.000000E+00 9.804999E-11 0.000000E+00 9.00000E+100\n", + " 33 traj.linkages.ascent:mass_final|climb_at_constant_TAS:mass_initial e 0.000000E+00 -3.781461E-11 0.000000E+00 9.00000E+100\n", + " 34 traj.linkages.ascent:range_final|climb_at_constant_TAS:range_initial e 0.000000E+00 -2.592907E-10 0.000000E+00 9.00000E+100\n", + " 35 traj.linkages.ascent:TAS_final|climb_at_constant_TAS:TAS_initial e 0.000000E+00 -2.165734E-12 0.000000E+00 9.00000E+100\n", + " 36 traj.linkages.climb_at_constant_TAS:time_final|climb_at_constant_EAS:time_initial e 0.000000E+00 1.108418E-11 0.000000E+00 9.00000E+100\n", + " 37 traj.linkages.climb_at_constant_TAS:mass_final|climb_at_constant_EAS:mass_initial e 0.000000E+00 -3.816385E-11 0.000000E+00 9.00000E+100\n", + " 38 traj.linkages.climb_at_constant_TAS:range_final|climb_at_constant_EAS:range_initial e 0.000000E+00 -1.578019E-11 0.000000E+00 9.00000E+100\n", + " 39 traj.linkages.climb_at_constant_TAS:TAS_final|climb_at_constant_EAS:TAS_initial e 0.000000E+00 -1.763567E-12 0.000000E+00 9.00000E+100\n", + " 40 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -1.747681E-09 0.000000E+00 9.00000E+100\n", + " 41 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -1.528990E-08 0.000000E+00 9.00000E+100\n", + " 42 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -1.010842E-08 0.000000E+00 9.00000E+100\n", + " 43 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -1.767186E-09 0.000000E+00 9.00000E+100\n", + " 44 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -1.228403E-08 0.000000E+00 9.00000E+100\n", + " 45 traj.ascent.collocation_constraint.defects:time e 0.000000E+00 -8.116669E-09 0.000000E+00 9.00000E+100\n", + " 46 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 1.413781E-08 0.000000E+00 9.00000E+100\n", + " 47 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 6.530079E-08 0.000000E+00 9.00000E+100\n", + " 48 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 4.805608E-08 0.000000E+00 9.00000E+100\n", + " 49 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 1.421405E-08 0.000000E+00 9.00000E+100\n", + " 50 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 6.563756E-08 0.000000E+00 9.00000E+100\n", + " 51 traj.ascent.collocation_constraint.defects:mass e 0.000000E+00 4.829367E-08 0.000000E+00 9.00000E+100\n", + " 52 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -9.646602E-09 0.000000E+00 9.00000E+100\n", + " 53 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -2.814928E-08 0.000000E+00 9.00000E+100\n", + " 54 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -1.928297E-08 0.000000E+00 9.00000E+100\n", + " 55 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -6.235639E-09 0.000000E+00 9.00000E+100\n", + " 56 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -2.259348E-08 0.000000E+00 9.00000E+100\n", + " 57 traj.ascent_to_flap_retract.collocation_constraint.defects:time e 0.000000E+00 -1.526477E-08 0.000000E+00 9.00000E+100\n", + " 58 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 1.402417E-08 0.000000E+00 9.00000E+100\n", + " 59 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 6.465865E-08 0.000000E+00 9.00000E+100\n", + " 60 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 4.752926E-08 0.000000E+00 9.00000E+100\n", + " 61 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 1.405129E-08 0.000000E+00 9.00000E+100\n", + " 62 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 6.484071E-08 0.000000E+00 9.00000E+100\n", + " 63 traj.ascent_to_flap_retract.collocation_constraint.defects:mass e 0.000000E+00 4.770808E-08 0.000000E+00 9.00000E+100\n", + " 64 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -5.243622E-08 0.000000E+00 9.00000E+100\n", + " 65 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -5.969421E-08 0.000000E+00 9.00000E+100\n", + " 66 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -3.275561E-08 0.000000E+00 9.00000E+100\n", + " 67 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -1.248545E-08 0.000000E+00 9.00000E+100\n", + " 68 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -3.024618E-08 0.000000E+00 9.00000E+100\n", + " 69 traj.ascent_to_gear_retract.collocation_constraint.defects:time e 0.000000E+00 -2.167643E-08 0.000000E+00 9.00000E+100\n", + " 70 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 1.369197E-08 0.000000E+00 9.00000E+100\n", + " 71 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 6.347131E-08 0.000000E+00 9.00000E+100\n", + " 72 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 4.722671E-08 0.000000E+00 9.00000E+100\n", + " 73 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 1.416163E-08 0.000000E+00 9.00000E+100\n", + " 74 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 6.548642E-08 0.000000E+00 9.00000E+100\n", + " 75 traj.ascent_to_gear_retract.collocation_constraint.defects:mass e 0.000000E+00 4.796910E-08 0.000000E+00 9.00000E+100\n", + " 76 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.554809E-07 0.000000E+00 9.00000E+100\n", + " 77 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.437427E-07 0.000000E+00 9.00000E+100\n", + " 78 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.296671E-07 0.000000E+00 9.00000E+100\n", + " 79 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.253305E-07 0.000000E+00 9.00000E+100\n", + " 80 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.205060E-07 0.000000E+00 9.00000E+100\n", + " 81 traj.climb_at_constant_EAS.collocation_constraint.defects:time e 0.000000E+00 -4.105684E-07 0.000000E+00 9.00000E+100\n", + " 82 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 1.544382E-08 0.000000E+00 9.00000E+100\n", + " 83 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 6.758758E-08 0.000000E+00 9.00000E+100\n", + " 84 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 5.002537E-08 0.000000E+00 9.00000E+100\n", + " 85 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 1.546570E-08 0.000000E+00 9.00000E+100\n", + " 86 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 6.835801E-08 0.000000E+00 9.00000E+100\n", + " 87 traj.climb_at_constant_EAS.collocation_constraint.defects:mass e 0.000000E+00 5.079527E-08 0.000000E+00 9.00000E+100\n", + " 88 traj.phases.climb_at_constant_EAS_to_mach->final_boundary_constraint->mach e 8.000000E-01 8.000000E-01 8.000000E-01 9.00000E+100\n", + " 89 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 -9.175639E-09 0.000000E+00 9.00000E+100\n", + " 90 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 -3.986398E-08 0.000000E+00 9.00000E+100\n", + " 91 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 -1.315770E-08 0.000000E+00 9.00000E+100\n", + " 92 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 1.985971E-09 0.000000E+00 9.00000E+100\n", + " 93 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 3.315513E-08 0.000000E+00 9.00000E+100\n", + " 94 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:time e 0.000000E+00 3.034072E-08 0.000000E+00 9.00000E+100\n", + " 95 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 1.507579E-08 0.000000E+00 9.00000E+100\n", + " 96 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 6.984450E-08 0.000000E+00 9.00000E+100\n", + " 97 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 5.165021E-08 0.000000E+00 9.00000E+100\n", + " 98 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 1.536210E-08 0.000000E+00 9.00000E+100\n", + " 99 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 7.105449E-08 0.000000E+00 9.00000E+100\n", + " 100 traj.climb_at_constant_EAS_to_mach.collocation_constraint.defects:mass e 0.000000E+00 5.264093E-08 0.000000E+00 9.00000E+100\n", + " 101 traj.phases.climb_at_constant_TAS->final_boundary_constraint->EAS e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 102 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -2.094251E-09 0.000000E+00 9.00000E+100\n", + " 103 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -8.757735E-09 0.000000E+00 9.00000E+100\n", + " 104 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -6.167356E-09 0.000000E+00 9.00000E+100\n", + " 105 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -2.540299E-09 0.000000E+00 9.00000E+100\n", + " 106 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -6.377448E-09 0.000000E+00 9.00000E+100\n", + " 107 traj.climb_at_constant_TAS.collocation_constraint.defects:time e 0.000000E+00 -5.088869E-09 0.000000E+00 9.00000E+100\n", + " 108 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 1.430483E-08 0.000000E+00 9.00000E+100\n", + " 109 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 6.603719E-08 0.000000E+00 9.00000E+100\n", + " 110 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 4.857910E-08 0.000000E+00 9.00000E+100\n", + " 111 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 1.436652E-08 0.000000E+00 9.00000E+100\n", + " 112 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 6.630470E-08 0.000000E+00 9.00000E+100\n", + " 113 traj.climb_at_constant_TAS.collocation_constraint.defects:mass e 0.000000E+00 4.876806E-08 0.000000E+00 9.00000E+100\n", + " 114 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 1.617965E-09 0.000000E+00 9.00000E+100\n", + " 115 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 9.057018E-09 0.000000E+00 9.00000E+100\n", + " 116 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 -3.724665E-10 0.000000E+00 9.00000E+100\n", + " 117 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 -2.501975E-09 0.000000E+00 9.00000E+100\n", + " 118 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 -9.323672E-09 0.000000E+00 9.00000E+100\n", + " 119 traj.climb_at_constant_mach.collocation_constraint.defects:time e 0.000000E+00 -5.594376E-09 0.000000E+00 9.00000E+100\n", + " 120 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 1.585982E-08 0.000000E+00 9.00000E+100\n", + " 121 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 7.364000E-08 0.000000E+00 9.00000E+100\n", + " 122 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 5.478994E-08 0.000000E+00 9.00000E+100\n", + " 123 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 1.642883E-08 0.000000E+00 9.00000E+100\n", + " 124 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 7.638733E-08 0.000000E+00 9.00000E+100\n", + " 125 traj.climb_at_constant_mach.collocation_constraint.defects:mass e 0.000000E+00 5.705677E-08 0.000000E+00 9.00000E+100\n", + " 126 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -2.383472E-08 0.000000E+00 9.00000E+100\n", + " 127 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -1.098661E-07 0.000000E+00 9.00000E+100\n", + " 128 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -8.019704E-08 0.000000E+00 9.00000E+100\n", + " 129 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -2.342182E-08 0.000000E+00 9.00000E+100\n", + " 130 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -1.074414E-07 0.000000E+00 9.00000E+100\n", + " 131 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -7.769977E-08 0.000000E+00 9.00000E+100\n", + " 132 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -2.244684E-08 0.000000E+00 9.00000E+100\n", + " 133 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -1.024242E-07 0.000000E+00 9.00000E+100\n", + " 134 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -7.329834E-08 0.000000E+00 9.00000E+100\n", + " 135 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -2.090975E-08 0.000000E+00 9.00000E+100\n", + " 136 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -9.481425E-08 0.000000E+00 9.00000E+100\n", + " 137 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -6.699262E-08 0.000000E+00 9.00000E+100\n", + " 138 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -1.881051E-08 0.000000E+00 9.00000E+100\n", + " 139 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -8.461144E-08 0.000000E+00 9.00000E+100\n", + " 140 traj.cruise.collocation_constraint.defects:time e 0.000000E+00 -5.878244E-08 0.000000E+00 9.00000E+100\n", + " 141 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 1.745807E-08 0.000000E+00 9.00000E+100\n", + " 142 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 8.125911E-08 0.000000E+00 9.00000E+100\n", + " 143 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 6.039479E-08 0.000000E+00 9.00000E+100\n", + " 144 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 1.799912E-08 0.000000E+00 9.00000E+100\n", + " 145 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 8.336510E-08 0.000000E+00 9.00000E+100\n", + " 146 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 6.139961E-08 0.000000E+00 9.00000E+100\n", + " 147 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 1.811460E-08 0.000000E+00 9.00000E+100\n", + " 148 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 8.350098E-08 0.000000E+00 9.00000E+100\n", + " 149 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 6.094711E-08 0.000000E+00 9.00000E+100\n", + " 150 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 1.779639E-08 0.000000E+00 9.00000E+100\n", + " 151 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 8.162881E-08 0.000000E+00 9.00000E+100\n", + " 152 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 5.900883E-08 0.000000E+00 9.00000E+100\n", + " 153 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 1.703587E-08 0.000000E+00 9.00000E+100\n", + " 154 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 7.770845E-08 0.000000E+00 9.00000E+100\n", + " 155 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 5.555462E-08 0.000000E+00 9.00000E+100\n", + " 156 traj.phases.descent->final_boundary_constraint->range e 2.000000E+00 2.000000E+00 2.000000E+00 9.00000E+100\n", + " 157 traj.phases.descent->final_boundary_constraint->altitude e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 158 traj.phases.descent->final_boundary_constraint->TAS e 1.000000E+00 1.000000E+00 1.000000E+00 9.00000E+100\n", + " 159 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -1.533251E-08 0.000000E+00 9.00000E+100\n", + " 160 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -6.768821E-08 0.000000E+00 9.00000E+100\n", + " 161 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -4.631342E-08 0.000000E+00 9.00000E+100\n", + " 162 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -1.262178E-08 0.000000E+00 9.00000E+100\n", + " 163 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -5.550315E-08 0.000000E+00 9.00000E+100\n", + " 164 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -3.745740E-08 0.000000E+00 9.00000E+100\n", + " 165 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -9.966721E-09 0.000000E+00 9.00000E+100\n", + " 166 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -4.342516E-08 0.000000E+00 9.00000E+100\n", + " 167 traj.descent.collocation_constraint.defects:time e 0.000000E+00 -2.829954E-08 0.000000E+00 9.00000E+100\n", + " 168 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.538186E-08 0.000000E+00 9.00000E+100\n", + " 169 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 6.970283E-08 0.000000E+00 9.00000E+100\n", + " 170 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.960815E-08 0.000000E+00 9.00000E+100\n", + " 171 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.414450E-08 0.000000E+00 9.00000E+100\n", + " 172 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 6.415823E-08 0.000000E+00 9.00000E+100\n", + " 173 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.575235E-08 0.000000E+00 9.00000E+100\n", + " 174 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.307599E-08 0.000000E+00 9.00000E+100\n", + " 175 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.938336E-08 0.000000E+00 9.00000E+100\n", + " 176 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.244121E-08 0.000000E+00 9.00000E+100\n", + " 177 traj.phases.rotation->final_boundary_constraint->normal_force e 0.000000E+00 -4.997400E-02 0.000000E+00 E 9.00000E+100\n", + " 178 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -9.267154E-06 0.000000E+00 E 9.00000E+100\n", + " 179 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -6.200230E-06 0.000000E+00 E 9.00000E+100\n", + " 180 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -3.421241E-06 0.000000E+00 E 9.00000E+100\n", + " 181 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -2.775903E-06 0.000000E+00 E 9.00000E+100\n", + " 182 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -1.690882E-06 0.000000E+00 E 9.00000E+100\n", + " 183 traj.rotation.collocation_constraint.defects:time e 0.000000E+00 -6.704024E-07 0.000000E+00 9.00000E+100\n", + " 184 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 4.061554E-08 0.000000E+00 9.00000E+100\n", + " 185 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 9.950411E-08 0.000000E+00 9.00000E+100\n", + " 186 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 7.041146E-08 0.000000E+00 9.00000E+100\n", + " 187 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 2.500647E-08 0.000000E+00 9.00000E+100\n", + " 188 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 8.886661E-08 0.000000E+00 9.00000E+100\n", + " 189 traj.rotation.collocation_constraint.defects:mass e 0.000000E+00 6.393324E-08 0.000000E+00 9.00000E+100\n", + " 190 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 7.966136E-01 1.000000E+00 9.00000E+100\n", + " 191 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.138790E-01 1.000000E+00 9.00000E+100\n", + " 192 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.376868E-01 1.000000E+00 9.00000E+100\n", + " 193 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.452183E-01 1.000000E+00 9.00000E+100\n", + " 194 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.452183E-01 1.000000E+00 9.00000E+100\n", + " 195 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.624581E-01 1.000000E+00 9.00000E+100\n", + " 196 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.862307E-01 1.000000E+00 9.00000E+100\n", + " 197 traj.phases.ascent->path_constraint->EAS i -1.000000E+30 8.937510E-01 1.000000E+00 9.00000E+100\n", + " 198 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 199 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 200 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 201 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 202 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 203 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 204 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 205 traj.phases.ascent_to_flap_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 206 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.855732E-01 1.000000E+00 9.00000E+100\n", + " 207 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.907166E-01 1.000000E+00 9.00000E+100\n", + " 208 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.902838E-01 1.000000E+00 9.00000E+100\n", + " 209 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.895349E-01 1.000000E+00 9.00000E+100\n", + " 210 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.895349E-01 1.000000E+00 9.00000E+100\n", + " 211 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.870513E-01 1.000000E+00 9.00000E+100\n", + " 212 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.823625E-01 1.000000E+00 9.00000E+100\n", + " 213 traj.phases.ascent_to_gear_retract->path_constraint->fuselage_pitch i -1.000000E+30 3.806637E-01 1.000000E+00 9.00000E+100\n", + " 214 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 215 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 216 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 217 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 218 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 219 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 220 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 221 traj.phases.ascent_to_gear_retract->path_constraint->load_factor i 0.000000E+00 1.000000E+00 1.100000E+00 9.00000E+100\n", + " 222 traj.phases.rotation->final_boundary_constraint->TAS i -1.000000E+30 9.824412E-01 1.000000E+00 9.00000E+100\n", + " 223 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 6.747216E-03 1.000000E+00 9.00000E+100\n", + " 224 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 5.444421E-02 1.000000E+00 9.00000E+100\n", + " 225 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 1.202563E-01 1.000000E+00 9.00000E+100\n", + " 226 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 1.410856E-01 1.000000E+00 9.00000E+100\n", + " 227 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 1.410856E-01 1.000000E+00 9.00000E+100\n", + " 228 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 1.887826E-01 1.000000E+00 9.00000E+100\n", + " 229 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 2.545947E-01 1.000000E+00 9.00000E+100\n", + " 230 traj.phases.rotation->path_constraint->fuselage_pitch i -1.000000E+30 2.754241E-01 1.000000E+00 9.00000E+100\n", + "\n", + "\n", + " Exit Status\n", + " Inform Description\n", + " -1 Maximum Iterations Exceeded\n", + "--------------------------------------------------------------------------------\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -939,7 +3280,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.18" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index 0f4bb0fbe..d0309aabe 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -57,10 +57,374 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "42c6704a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_deck.py:198: UserWarning: is a required option for EngineDecks, but has not been specified for EngineDeck . The default value will be used.\n", + " warnings.warn(\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'climb': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'climb': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'descent': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'descent': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:aspect_ratio', promoted using 'aircraft:canard:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:aspect_ratio', promoted using 'aircraft:horizontal_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:aspect_ratio', promoted using 'aircraft:vertical_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb.nonlinear_solver to override.\n", + " Setting `traj.phases.climb.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb.linear_solver to override.\n", + " Set `traj.phases.climb.options[\"auto_solvers\"] = False` to disable this behavior.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:landing_to_takeoff_mass_ratio\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:nacelle:total_wetted_area\n", + " 'aircraft:nacelle:wetted_area\n", + " 'aircraft:propulsion:total_engine_controls_mass\n", + " 'aircraft:propulsion:total_starter_mass\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- climb ---\n", + " None\n", + " --- cruise ---\n", + " [path] 3.0000e+02 <= altitude_rate_max [ft/min]\n", + " --- descent ---\n", + " None\n", + "\n", + "Model viewer data has already been recorded for Driver.\n", + "\n", + "List of user-set options:\n", + "\n", + " Name Value used\n", + " file_print_level = 5 yes\n", + " hessian_approximation = limited-memory yes\n", + " linear_solver = mumps yes\n", + " max_iter = 100 yes\n", + " nlp_scaling_method = user-scaling yes\n", + " output_file = reports/problem/IPOPT.out yes\n", + " print_level = 4 yes\n", + " print_user_options = yes yes\n", + " sb = yes yes\n", + " tol = 0.001 yes\n", + "Total number of variables............................: 82\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 82\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 79\n", + "Total number of inequality constraints...............: 4\n", + " inequality constraints with only lower bounds: 4\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "\n", + "Number of Iterations....: 25\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 9.4146770609913695e+00 9.4146770609913695e+00\n", + "Dual infeasibility......: 1.0999629934911812e-08 1.0999629934911812e-08\n", + "Constraint violation....: 3.2276147976517677e-08 3.2276147976517677e-08\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 1.2325706634551805e-06 1.2325706634551805e-06\n", + "Overall NLP error.......: 1.2325706634551805e-06 1.2325706634551805e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 28\n", + "Number of objective gradient evaluations = 26\n", + "Number of equality constraint evaluations = 28\n", + "Number of inequality constraint evaluations = 28\n", + "Number of equality constraint Jacobian evaluations = 26\n", + "Number of inequality constraint Jacobian evaluations = 26\n", + "Number of Lagrangian Hessian evaluations = 0\n", + "Total seconds in IPOPT = 13.391\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "\n", + "Optimization Problem -- Optimization using pyOpt_sparse\n", + "================================================================================\n", + " Objective Function: _objfunc\n", + "\n", + " Solution: \n", + "--------------------------------------------------------------------------------\n", + " Total Time: 13.3939\n", + " User Objective Time : 9.6485\n", + " User Sensitivity Time : 3.6103\n", + " Interface Time : 0.0666\n", + " Opt Solver Time: 0.0686\n", + " Calls to Objective Function : 28\n", + " Calls to Sens Function : 26\n", + "\n", + "\n", + " Objectives\n", + " Index Name Value\n", + " 0 reg_objective 9.414677E+00\n", + "\n", + " Variables (c - continuous, i - integer, d - discrete)\n", + " Index Name Type Lower Bound Value Upper Bound Status\n", + " 0 mission:design:gross_mass_0 c 7.407407E-01 8.607091E-01 1.481481E+00 \n", + " 1 traj.climb.t_duration_0 c 5.000000E-01 5.000003E-01 2.000000E+00 l\n", + " 2 traj.climb.states:mass_0 c 0.000000E+00 5.241266E+00 1.000000E+17 \n", + " 3 traj.climb.states:mass_1 c 0.000000E+00 5.237291E+00 1.000000E+17 \n", + " 4 traj.climb.states:mass_2 c 0.000000E+00 5.236091E+00 1.000000E+17 \n", + " 5 traj.climb.states:mass_3 c 0.000000E+00 5.230548E+00 1.000000E+17 \n", + " 6 traj.climb.states:mass_4 c 0.000000E+00 5.223489E+00 1.000000E+17 \n", + " 7 traj.climb.states:mass_5 c 0.000000E+00 5.221338E+00 1.000000E+17 \n", + " 8 traj.climb.states:mass_6 c 0.000000E+00 5.215137E+00 1.000000E+17 \n", + " 9 traj.climb.states:mass_7 c 0.000000E+00 5.206956E+00 1.000000E+17 \n", + " 10 traj.climb.states:mass_8 c 0.000000E+00 5.204440E+00 1.000000E+17 \n", + " 11 traj.climb.states:mass_9 c 0.000000E+00 5.198692E+00 1.000000E+17 \n", + " 12 traj.climb.states:mass_10 c 0.000000E+00 5.190826E+00 1.000000E+17 \n", + " 13 traj.climb.states:mass_11 c 0.000000E+00 5.188345E+00 1.000000E+17 \n", + " 14 traj.climb.states:mass_12 c 0.000000E+00 5.183981E+00 1.000000E+17 \n", + " 15 traj.climb.states:mass_13 c 0.000000E+00 5.177987E+00 1.000000E+17 \n", + " 16 traj.climb.states:mass_14 c 0.000000E+00 5.176097E+00 1.000000E+17 \n", + " 17 traj.climb.states:mass_15 c 0.000000E+00 5.174062E+00 1.000000E+17 \n", + " 18 traj.climb.states:mass_16 c 0.000000E+00 5.171248E+00 1.000000E+17 \n", + " 19 traj.climb.states:mass_17 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", + " 20 traj.climb.states:range_0 c 0.000000E+00 2.764851E-03 1.000000E+15 \n", + " 21 traj.climb.states:range_1 c 0.000000E+00 5.071419E-03 1.000000E+15 \n", + " 22 traj.climb.states:range_2 c 0.000000E+00 5.851859E-03 1.000000E+15 \n", + " 23 traj.climb.states:range_3 c 0.000000E+00 9.998326E-03 1.000000E+15 \n", + " 24 traj.climb.states:range_4 c 0.000000E+00 1.663641E-02 1.000000E+15 \n", + " 25 traj.climb.states:range_5 c 0.000000E+00 1.895456E-02 1.000000E+15 \n", + " 26 traj.climb.states:range_6 c 0.000000E+00 2.644512E-02 1.000000E+15 \n", + " 27 traj.climb.states:range_7 c 0.000000E+00 3.822814E-02 1.000000E+15 \n", + " 28 traj.climb.states:range_8 c 0.000000E+00 4.229839E-02 1.000000E+15 \n", + " 29 traj.climb.states:range_9 c 0.000000E+00 5.222057E-02 1.000000E+15 \n", + " 30 traj.climb.states:range_10 c 0.000000E+00 6.724973E-02 1.000000E+15 \n", + " 31 traj.climb.states:range_11 c 0.000000E+00 7.232091E-02 1.000000E+15 \n", + " 32 traj.climb.states:range_12 c 0.000000E+00 8.163066E-02 1.000000E+15 \n", + " 33 traj.climb.states:range_13 c 0.000000E+00 9.521093E-02 1.000000E+15 \n", + " 34 traj.climb.states:range_14 c 0.000000E+00 9.968231E-02 1.000000E+15 \n", + " 35 traj.climb.states:range_15 c 0.000000E+00 1.045838E-01 1.000000E+15 \n", + " 36 traj.climb.states:range_16 c 0.000000E+00 1.114998E-01 1.000000E+15 \n", + " 37 traj.climb.states:range_17 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", + " 38 traj.cruise.t_initial_0 c 7.260000E+02 8.460004E+02 2.904000E+03 \n", + " 39 traj.cruise.t_duration_0 c 5.000000E-01 5.000000E-01 2.000000E+00 l\n", + " 40 traj.cruise.states:mass_0 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", + " 41 traj.cruise.states:mass_1 c 0.000000E+00 5.005025E+00 1.000000E+17 \n", + " 42 traj.cruise.states:mass_2 c 0.000000E+00 4.780360E+00 1.000000E+17 \n", + " 43 traj.cruise.states:mass_3 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", + " 44 traj.cruise.states:range_0 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", + " 45 traj.cruise.states:range_1 c 0.000000E+00 1.127228E+00 1.000000E+15 \n", + " 46 traj.cruise.states:range_2 c 0.000000E+00 2.525655E+00 1.000000E+15 \n", + " 47 traj.cruise.states:range_3 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", + " 48 traj.descent.t_initial_0 c 1.291140E+04 1.303140E+04 5.164560E+04 \n", + " 49 traj.descent.t_duration_0 c 5.000000E-01 5.000011E-01 2.000000E+00 \n", + " 50 traj.descent.states:mass_0 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", + " 51 traj.descent.states:mass_1 c 0.000000E+00 4.710502E+00 1.000000E+17 \n", + " 52 traj.descent.states:mass_2 c 0.000000E+00 4.711242E+00 1.000000E+17 \n", + " 53 traj.descent.states:mass_3 c 0.000000E+00 4.711494E+00 1.000000E+17 \n", + " 54 traj.descent.states:mass_4 c 0.000000E+00 4.712779E+00 1.000000E+17 \n", + " 55 traj.descent.states:mass_5 c 0.000000E+00 4.714841E+00 1.000000E+17 \n", + " 56 traj.descent.states:mass_6 c 0.000000E+00 4.715567E+00 1.000000E+17 \n", + " 57 traj.descent.states:mass_7 c 0.000000E+00 4.717767E+00 1.000000E+17 \n", + " 58 traj.descent.states:mass_8 c 0.000000E+00 4.721139E+00 1.000000E+17 \n", + " 59 traj.descent.states:mass_9 c 0.000000E+00 4.722228E+00 1.000000E+17 \n", + " 60 traj.descent.states:mass_10 c 0.000000E+00 4.723686E+00 1.000000E+17 \n", + " 61 traj.descent.states:mass_11 c 0.000000E+00 4.725431E+00 1.000000E+17 \n", + " 62 traj.descent.states:mass_12 c 0.000000E+00 4.726157E+00 1.000000E+17 \n", + " 63 traj.descent.states:mass_13 c 0.000000E+00 4.726963E+00 1.000000E+17 \n", + " 64 traj.descent.states:mass_14 c 0.000000E+00 4.728154E+00 1.000000E+17 \n", + " 65 traj.descent.states:mass_15 c 0.000000E+00 4.728551E+00 1.000000E+17 \n", + " 66 traj.descent.states:range_0 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", + " 67 traj.descent.states:range_1 c 0.000000E+00 2.976728E+00 1.000000E+15 \n", + " 68 traj.descent.states:range_2 c 0.000000E+00 2.988146E+00 1.000000E+15 \n", + " 69 traj.descent.states:range_3 c 0.000000E+00 2.991691E+00 1.000000E+15 \n", + " 70 traj.descent.states:range_4 c 0.000000E+00 3.007825E+00 1.000000E+15 \n", + " 71 traj.descent.states:range_5 c 0.000000E+00 3.028841E+00 1.000000E+15 \n", + " 72 traj.descent.states:range_6 c 0.000000E+00 3.035182E+00 1.000000E+15 \n", + " 73 traj.descent.states:range_7 c 0.000000E+00 3.051662E+00 1.000000E+15 \n", + " 74 traj.descent.states:range_8 c 0.000000E+00 3.072458E+00 1.000000E+15 \n", + " 75 traj.descent.states:range_9 c 0.000000E+00 3.078555E+00 1.000000E+15 \n", + " 76 traj.descent.states:range_10 c 0.000000E+00 3.089619E+00 1.000000E+15 \n", + " 77 traj.descent.states:range_11 c 0.000000E+00 3.103383E+00 1.000000E+15 \n", + " 78 traj.descent.states:range_12 c 0.000000E+00 3.107367E+00 1.000000E+15 \n", + " 79 traj.descent.states:range_13 c 0.000000E+00 3.111617E+00 1.000000E+15 \n", + " 80 traj.descent.states:range_14 c 0.000000E+00 3.117100E+00 1.000000E+15 \n", + " 81 traj.descent.states:range_15 c 0.000000E+00 3.118742E+00 1.000000E+15 \n", + "\n", + " Constraints (i - inequality, e - equality)\n", + " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", + " 0 mass_resid e 0.000000E+00 -3.227615E-08 0.000000E+00 9.00000E+100\n", + " 1 traj.linkages.climb:time_final|cruise:time_initial e 0.000000E+00 1.136868E-13 0.000000E+00 9.00000E+100\n", + " 2 traj.linkages.climb:mass_final|cruise:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 3 traj.linkages.climb:range_final|cruise:range_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 4 traj.linkages.cruise:time_final|descent:time_initial e 0.000000E+00 -1.818989E-12 0.000000E+00 9.00000E+100\n", + " 5 traj.linkages.cruise:mass_final|descent:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 6 traj.linkages.cruise:range_final|descent:range_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 7 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.025097E-14 0.000000E+00 9.00000E+100\n", + " 8 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.860766E-14 0.000000E+00 9.00000E+100\n", + " 9 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.699134E-14 0.000000E+00 9.00000E+100\n", + " 10 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.485284E-14 0.000000E+00 9.00000E+100\n", + " 11 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.003003E-14 0.000000E+00 9.00000E+100\n", + " 12 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.531926E-14 0.000000E+00 9.00000E+100\n", + " 13 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.113611E-14 0.000000E+00 9.00000E+100\n", + " 14 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.886567E-14 0.000000E+00 9.00000E+100\n", + " 15 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.598810E-14 0.000000E+00 9.00000E+100\n", + " 16 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.408043E-14 0.000000E+00 9.00000E+100\n", + " 17 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.173824E-14 0.000000E+00 9.00000E+100\n", + " 18 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.099713E-14 0.000000E+00 9.00000E+100\n", + " 19 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.608025E-14 0.000000E+00 9.00000E+100\n", + " 20 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.587637E-14 0.000000E+00 9.00000E+100\n", + " 21 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.558807E-14 0.000000E+00 9.00000E+100\n", + " 22 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.279583E-15 0.000000E+00 9.00000E+100\n", + " 23 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.206002E-15 0.000000E+00 9.00000E+100\n", + " 24 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.240740E-15 0.000000E+00 9.00000E+100\n", + " 25 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.162790E-14 0.000000E+00 9.00000E+100\n", + " 26 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.105201E-14 0.000000E+00 9.00000E+100\n", + " 27 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.002517E-14 0.000000E+00 9.00000E+100\n", + " 28 traj.climb.collocation_constraint.defects:range e 0.000000E+00 2.058287E-14 0.000000E+00 9.00000E+100\n", + " 29 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.782458E-14 0.000000E+00 9.00000E+100\n", + " 30 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.511325E-14 0.000000E+00 9.00000E+100\n", + " 31 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.872588E-14 0.000000E+00 9.00000E+100\n", + " 32 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.655588E-14 0.000000E+00 9.00000E+100\n", + " 33 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.434107E-14 0.000000E+00 9.00000E+100\n", + " 34 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.377297E-14 0.000000E+00 9.00000E+100\n", + " 35 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.265000E-14 0.000000E+00 9.00000E+100\n", + " 36 traj.climb.collocation_constraint.defects:range e 0.000000E+00 1.141126E-14 0.000000E+00 9.00000E+100\n", + " 37 traj.climb.collocation_constraint.defects:range e 0.000000E+00 8.538640E-15 0.000000E+00 9.00000E+100\n", + " 38 traj.climb.collocation_constraint.defects:range e 0.000000E+00 8.126975E-15 0.000000E+00 9.00000E+100\n", + " 39 traj.climb.collocation_constraint.defects:range e 0.000000E+00 7.635711E-15 0.000000E+00 9.00000E+100\n", + " 40 traj.climb.collocation_constraint.defects:range e 0.000000E+00 3.521029E-15 0.000000E+00 9.00000E+100\n", + " 41 traj.climb.collocation_constraint.defects:range e 0.000000E+00 3.453567E-15 0.000000E+00 9.00000E+100\n", + " 42 traj.climb.collocation_constraint.defects:range e 0.000000E+00 3.366714E-15 0.000000E+00 9.00000E+100\n", + " 43 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 5.312109E-13 0.000000E+00 9.00000E+100\n", + " 44 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 4.063769E-13 0.000000E+00 9.00000E+100\n", + " 45 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 2.575362E-13 0.000000E+00 9.00000E+100\n", + " 46 traj.cruise.collocation_constraint.defects:range e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", + " 47 traj.cruise.collocation_constraint.defects:range e 0.000000E+00 3.463299E-18 0.000000E+00 9.00000E+100\n", + " 48 traj.cruise.collocation_constraint.defects:range e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", + " 49 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.910022E-14 0.000000E+00 9.00000E+100\n", + " 50 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.529124E-14 0.000000E+00 9.00000E+100\n", + " 51 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.342543E-14 0.000000E+00 9.00000E+100\n", + " 52 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 6.585307E-14 0.000000E+00 9.00000E+100\n", + " 53 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.552915E-14 0.000000E+00 9.00000E+100\n", + " 54 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.341976E-14 0.000000E+00 9.00000E+100\n", + " 55 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.791654E-14 0.000000E+00 9.00000E+100\n", + " 56 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.929329E-14 0.000000E+00 9.00000E+100\n", + " 57 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.075605E-14 0.000000E+00 9.00000E+100\n", + " 58 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 2.145444E-14 0.000000E+00 9.00000E+100\n", + " 59 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.435837E-14 0.000000E+00 9.00000E+100\n", + " 60 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 9.991150E-15 0.000000E+00 9.00000E+100\n", + " 61 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.078937E-15 0.000000E+00 9.00000E+100\n", + " 62 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.142482E-15 0.000000E+00 9.00000E+100\n", + " 63 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.257099E-15 0.000000E+00 9.00000E+100\n", + " 64 traj.descent.collocation_constraint.defects:range e 0.000000E+00 6.438287E-14 0.000000E+00 9.00000E+100\n", + " 65 traj.descent.collocation_constraint.defects:range e 0.000000E+00 6.567239E-14 0.000000E+00 9.00000E+100\n", + " 66 traj.descent.collocation_constraint.defects:range e 0.000000E+00 6.757017E-14 0.000000E+00 9.00000E+100\n", + " 67 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.393325E-13 0.000000E+00 9.00000E+100\n", + " 68 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.459218E-13 0.000000E+00 9.00000E+100\n", + " 69 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.566014E-13 0.000000E+00 9.00000E+100\n", + " 70 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.907169E-13 0.000000E+00 9.00000E+100\n", + " 71 traj.descent.collocation_constraint.defects:range e 0.000000E+00 2.047396E-13 0.000000E+00 9.00000E+100\n", + " 72 traj.descent.collocation_constraint.defects:range e 0.000000E+00 2.289513E-13 0.000000E+00 9.00000E+100\n", + " 73 traj.descent.collocation_constraint.defects:range e 0.000000E+00 2.003578E-13 0.000000E+00 9.00000E+100\n", + " 74 traj.descent.collocation_constraint.defects:range e 0.000000E+00 2.175539E-13 0.000000E+00 9.00000E+100\n", + " 75 traj.descent.collocation_constraint.defects:range e 0.000000E+00 2.479632E-13 0.000000E+00 9.00000E+100\n", + " 76 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.271784E-13 0.000000E+00 9.00000E+100\n", + " 77 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.344334E-13 0.000000E+00 9.00000E+100\n", + " 78 traj.descent.collocation_constraint.defects:range e 0.000000E+00 1.461002E-13 0.000000E+00 9.00000E+100\n", + " 79 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.127272E+02 1.000000E+30 9.00000E+100\n", + " 80 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.752630E+02 1.000000E+30 9.00000E+100\n", + " 81 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.643321E+02 1.000000E+30 9.00000E+100\n", + " 82 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.932716E+02 1.000000E+30 9.00000E+100\n", + "\n", + "\n", + " Exit Status\n", + " Inform Description\n", + " 0 Solve Succeeded\n", + "--------------------------------------------------------------------------------\n", + "\n", + "-------------------------------\n", + "times_climb: [846.00038137] (s)\n", + "altitudes_climb: [10668.] (m)\n", + "masses_climb: [51703.54384226] (kg)\n", + "ranges_climb: [113725.11889636] (m)\n", + "velocities_climb: [234.25795132] (m/s)\n", + "thrusts_climb: [71713.80312354] (N)\n", + "times_cruise: [13031.40073487] (s)\n", + "altitudes_cruise: [10668.] (m)\n", + "masses_cruise: [47100.44512976] (kg)\n", + "ranges_cruise: [2968252.0417268] (m)\n", + "velocities_cruise: [234.25795132] (m/s)\n", + "thrusts_cruise: [26338.70498784] (N)\n", + "times_descent: [13908.60273889] (s)\n", + "altitudes_descent: [10.668] (m)\n", + "masses_descent: [47285.51458051] (kg)\n", + "ranges_descent: [3118741.8185247] (m)\n", + "velocities_descent: [102.07377559] (m/s)\n", + "thrusts_descent: [-43173.10618655] (N)\n", + "-------------------------------\n" + ] + } + ], "source": [ "'''\n", "NOTES:\n", @@ -69,28 +433,18 @@ "Computed Aero\n", "N3CC data\n", "'''\n", - "import warnings\n", "\n", "import dymos as dm\n", "import openmdao.api as om\n", "import scipy.constants as _units\n", - "from packaging import version\n", "\n", - "from aviary.api import Aircraft, Mission, Dynamic\n", "import aviary.api as av\n", "\n", - "use_new_dymos_syntax = version.parse(dm.__version__) > version.parse(\"1.8.0\")\n", - "\n", - "# benchmark based on N3CC (fixed cruise alt) FLOPS model\n", "\n", - "\n", - "##########################################\n", - "# init problem #\n", - "##########################################\n", "prob = om.Problem(model=om.Group())\n", - "\n", - "prob.driver = driver = om.pyOptSparseDriver(optimizer='IPOPT')\n", - "driver.opt_settings[\"max_iter\"] = 0\n", + "driver = prob.driver = om.pyOptSparseDriver()\n", + "driver.options[\"optimizer\"] = \"IPOPT\"\n", + "driver.opt_settings[\"max_iter\"] = 100\n", "driver.opt_settings[\"tol\"] = 1e-3\n", "driver.opt_settings['print_level'] = 4\n", "\n", @@ -100,42 +454,35 @@ "\n", "aviary_inputs = av.get_flops_inputs('N3CC')\n", "\n", + "aviary_inputs.set_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX,\n", + " 2.4, units=\"unitless\")\n", + "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_COEFFICIENT_MAX,\n", + " 2.0, units=\"unitless\")\n", "aviary_inputs.set_val(\n", - " Mission.Landing.LIFT_COEFFICIENT_MAX, 2.4, units='unitless')\n", - "aviary_inputs.set_val(\n", - " Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, units='unitless')\n", - "aviary_inputs.set_val(\n", - " Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=.0175,\n", - " units='unitless')\n", - "\n", - "takeoff_fuel_burned = 577 # lbm\n", - "takeoff_thrust_per_eng = 24555.5 # lbf\n", - "takeoff_L_over_D = 17.35\n", + " av.Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT,\n", + " val=.0175, units=\"unitless\")\n", "\n", - "aviary_inputs.set_val(\n", - " Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm')\n", - "aviary_inputs.set_val(\n", - " Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless')\n", - "aviary_inputs.set_val(\n", - " Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf')\n", + "takeoff_fuel_burned = 577 # lbm TODO: where should this get connected from?\n", + "takeoff_thrust_per_eng = 24555.5 # lbf TODO: where should this get connected from?\n", + "takeoff_L_over_D = 17.35 # TODO: should this come from aero?\n", "\n", - "##########################################\n", - "# Phase Info #\n", - "##########################################\n", + "aviary_inputs.set_val(av.Mission.Takeoff.FUEL_SIMPLE,\n", + " takeoff_fuel_burned, units='lbm')\n", + "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_OVER_DRAG,\n", + " takeoff_L_over_D, units=\"unitless\")\n", + "aviary_inputs.set_val(av.Mission.Design.THRUST_TAKEOFF_PER_ENG,\n", + " takeoff_thrust_per_eng, units='lbf')\n", "\n", "alt_airport = 0 # ft\n", - "cruise_mach = .785\n", "\n", "alt_i_climb = 0*_units.foot # m\n", "alt_f_climb = 35000.0*_units.foot # m\n", "mass_i_climb = 131000*_units.lb # kg\n", "mass_f_climb = 126000*_units.lb # kg\n", - "v_i_climb = 198.44*_units.knot # m/s\n", - "v_f_climb = 455.49*_units.knot # m/s\n", "# initial mach set to lower value so it can intersect with takeoff end mach\n", "# mach_i_climb = 0.3\n", "mach_i_climb = 0.2\n", - "mach_f_climb = cruise_mach\n", + "mach_f_climb = 0.79\n", "range_i_climb = 0*_units.nautical_mile # m\n", "range_f_climb = 160.3*_units.nautical_mile # m\n", "t_i_climb = 2 * _units.minute # sec\n", @@ -148,10 +495,7 @@ "alt_max_cruise = 35000*_units.foot # m\n", "mass_i_cruise = 126000*_units.lb # kg\n", "mass_f_cruise = 102000*_units.lb # kg\n", - "v_i_cruise = 455.49*_units.knot # m/s\n", - "v_f_cruise = 455.49*_units.knot # m/s\n", - "mach_min_cruise = cruise_mach\n", - "mach_max_cruise = cruise_mach\n", + "cruise_mach = 0.79\n", "range_i_cruise = 160.3*_units.nautical_mile # m\n", "range_f_cruise = 3243.9*_units.nautical_mile # m\n", "t_i_cruise = 26.20*_units.minute # sec\n", @@ -162,9 +506,7 @@ "# final altitude set to 35 to ensure landing is feasible point\n", "# alt_f_descent = 0*_units.foot\n", "alt_f_descent = 35*_units.foot\n", - "v_i_descent = 455.49*_units.knot\n", - "v_f_descent = 198.44*_units.knot\n", - "mach_i_descent = cruise_mach\n", + "mach_i_descent = 0.79\n", "mach_f_descent = 0.3\n", "mass_i_descent = 102000*_units.pound\n", "mass_f_descent = 101000*_units.pound\n", @@ -174,10 +516,25 @@ "t_f_descent = 461.62*_units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", "\n", + "##########################\n", + "# Design Variables #\n", + "##########################\n", + "\n", + "# Nudge it a bit off the correct answer to verify that the optimize takes us there.\n", + "aviary_inputs.set_val(av.Mission.Design.GROSS_MASS, 135000.0, units='lbm')\n", + "\n", + "prob.model.add_design_var(av.Mission.Design.GROSS_MASS, units='lbm',\n", + " lower=100000.0, upper=200000.0, ref=135000)\n", + "\n", + "takeoff_options = av.HeightEnergyTakeoffPhaseBuilder(\n", + " airport_altitude=alt_airport, # ft\n", + " # no units\n", + " num_engines=aviary_inputs.get_val(av.Aircraft.Engine.NUM_ENGINES)\n", + ")\n", + "\n", "##################\n", "# Define Phases #\n", "##################\n", - "\n", "num_segments_climb = 6\n", "num_segments_cruise = 1\n", "num_segments_descent = 5\n", @@ -194,12 +551,7 @@ " num_segments=num_segments_descent, order=3, compressed=True,\n", " segment_ends=descent_seg_ends)\n", "\n", - "takeoff_options = av.HeightEnergyTakeoffPhaseBuilder(\n", - " airport_altitude=alt_airport, # ft\n", - " num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES)\n", - ")\n", - "\n", - "climb_options = av.HeightEnergyClimbPhaseBuilder(\n", + "climb_options = av.HeightEnergyPhaseBuilder(\n", " 'test_climb',\n", " user_options=av.AviaryValues({\n", " 'initial_altitude': (alt_i_climb, 'm'),\n", @@ -207,31 +559,30 @@ " 'initial_mach': (mach_i_climb, 'unitless'),\n", " 'final_mach': (mach_f_climb, 'unitless'),\n", " 'fix_initial': (False, 'unitless'),\n", - " 'fix_range': (False, 'unitless'),\n", " 'input_initial': (True, 'unitless'),\n", + " 'use_polynomial_control': (False, 'unitless'),\n", " }),\n", " core_subsystems=av.default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_climb,\n", ")\n", "\n", - "cruise_options = av.HeightEnergyCruisePhaseBuilder(\n", + "cruise_options = av.HeightEnergyPhaseBuilder(\n", " 'test_cruise',\n", " user_options=av.AviaryValues({\n", - " 'min_altitude': (alt_min_cruise, 'm'),\n", - " 'max_altitude': (alt_max_cruise, 'm'),\n", - " 'min_mach': (mach_min_cruise, 'unitless'),\n", - " 'max_mach': (mach_max_cruise, 'unitless'),\n", + " 'initial_altitude': (alt_min_cruise, 'm'),\n", + " 'final_altitude': (alt_max_cruise, 'm'),\n", + " 'initial_mach': (cruise_mach, 'unitless'),\n", + " 'final_mach': (cruise_mach, 'unitless'),\n", " 'required_available_climb_rate': (300, 'ft/min'),\n", " 'fix_initial': (False, 'unitless'),\n", - " 'fix_final': (False, 'unitless'),\n", " }),\n", " core_subsystems=av.default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_cruise,\n", ")\n", "\n", - "descent_options = av.HeightEnergyDescentPhaseBuilder(\n", + "descent_options = av.HeightEnergyPhaseBuilder(\n", " 'test_descent',\n", " user_options=av.AviaryValues({\n", " 'final_altitude': (alt_f_descent, 'm'),\n", @@ -239,7 +590,7 @@ " 'initial_mach': (mach_i_descent, 'unitless'),\n", " 'final_mach': (mach_f_descent, 'unitless'),\n", " 'fix_initial': (False, 'unitless'),\n", - " 'fix_range': (True, 'unitless'),\n", + " 'use_polynomial_control': (False, 'unitless'),\n", " }),\n", " core_subsystems=av.default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", @@ -247,16 +598,13 @@ ")\n", "\n", "landing_options = av.HeightEnergyLandingPhaseBuilder(\n", - " ref_wing_area=aviary_inputs.get_val(Aircraft.Wing.AREA, 'ft**2'),\n", - " Cl_max_ldg=aviary_inputs.get_val(Mission.Landing.LIFT_COEFFICIENT_MAX)\n", + " ref_wing_area=aviary_inputs.get_val(av.Aircraft.Wing.AREA, units='ft**2'),\n", + " Cl_max_ldg=aviary_inputs.get_val(\n", + " av.Mission.Landing.LIFT_COEFFICIENT_MAX) # no units\n", ")\n", "\n", "av.preprocess_crewpayload(aviary_inputs)\n", "\n", - "##########################################\n", - "# add pre mission systems #\n", - "##########################################\n", - "\n", "# Upstream static analysis for aero\n", "prob.model.add_subsystem(\n", " 'pre_mission',\n", @@ -265,10 +613,6 @@ " promotes_inputs=['aircraft:*', 'mission:*'],\n", " promotes_outputs=['aircraft:*', 'mission:*'])\n", "\n", - "##########################################\n", - "# add phases #\n", - "##########################################\n", - "\n", "# directly connect phases (strong_couple = True), or use linkage constraints (weak\n", "# coupling / strong_couple=False)\n", "strong_couple = False\n", @@ -291,15 +635,20 @@ "\n", "# if fix_initial is false, can we always set input_initial to be true for\n", "# necessary states, and then ignore if we use a linkage?\n", - "climb.set_time_options(\n", - " fix_initial=True, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_climb*2), duration_ref=t_duration_climb)\n", - "cruise.set_time_options(\n", - " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise)\n", + "climb.set_time_options(fix_initial=True, fix_duration=False, units='s',\n", + " duration_bounds=(t_duration_climb*0.5, t_duration_climb*2),\n", + " duration_ref=t_duration_climb)\n", + "cruise.set_time_options(fix_initial=False, fix_duration=False, units='s',\n", + " duration_bounds=(t_duration_cruise*0.5, t_duration_cruise*2),\n", + " duration_ref=t_duration_cruise,\n", + " initial_bounds=(t_duration_climb*0.5, t_duration_climb*2))\n", "descent.set_time_options(\n", " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_descent*2), duration_ref=t_duration_descent)\n", + " duration_bounds=(t_duration_descent*0.5, t_duration_descent*2),\n", + " duration_ref=t_duration_descent,\n", + " initial_bounds=(\n", + " (t_duration_cruise + t_duration_climb)*0.5,\n", + " (t_duration_cruise + t_duration_climb)*2))\n", "\n", "traj.add_phase('climb', climb)\n", "\n", @@ -307,108 +656,105 @@ "\n", "traj.add_phase('descent', descent)\n", "\n", - "if use_new_dymos_syntax:\n", - " climb.timeseries_options['use_prefix'] = True\n", - " cruise.timeseries_options['use_prefix'] = True\n", - " descent.timeseries_options['use_prefix'] = True\n", - "\n", - "##########################################\n", - "# add post mission system #\n", - "##########################################\n", - "\n", "prob.model.add_subsystem(\n", " 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'],\n", " promotes_outputs=['mission:*'])\n", "\n", - "##########################################\n", - "# link phases #\n", - "##########################################\n", - "\n", - "traj.link_phases([\"climb\", \"cruise\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", - "traj.link_phases([\"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + "traj.link_phases([\"climb\", \"cruise\", \"descent\"], [\n", + " \"time\", \"mass\", \"range\"], connected=strong_couple)\n", "\n", "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", "\n", "##################################\n", "# Connect in Takeoff and Landing #\n", "##################################\n", - "\n", - "prob.model.add_subsystem(\n", - " \"takeoff_constraints\",\n", - " om.ExecComp(\n", - " [\n", - " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_range_con=takeoff_range-climb_start_range\",\n", - " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", - " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", - " ],\n", - " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", - " climb_start_mass={'units': 'lbm'},\n", - " takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", - " climb_start_range={'units': 'ft'},\n", - " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", - " climb_start_vel={'units': 'm/s'},\n", - " takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'},\n", - " climb_start_alt={'units': 'ft'}\n", - " ),\n", - " promotes_inputs=[\n", - " (\"takeoff_mass\", Mission.Takeoff.FINAL_MASS),\n", - " (\"takeoff_range\", Mission.Takeoff.GROUND_DISTANCE),\n", - " (\"takeoff_vel\", Mission.Takeoff.FINAL_VELOCITY),\n", - " (\"takeoff_alt\", Mission.Takeoff.FINAL_ALTITUDE),\n", - " ],\n", - " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_range_con\",\n", - " \"takeoff_vel_con\", \"takeoff_alt_con\"],\n", - ")\n", - "\n", - "prob.model.connect('traj.climb.states:mass',\n", - " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", - "prob.model.connect('traj.climb.states:range',\n", - " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", - "prob.model.connect('traj.climb.states:velocity',\n", - " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", - "prob.model.connect('traj.climb.states:altitude',\n", - " 'takeoff_constraints.climb_start_alt', src_indices=[0])\n", - "\n", - "prob.model.connect(Mission.Takeoff.FINAL_MASS,\n", + "prob.model.connect(av.Mission.Takeoff.FINAL_MASS,\n", " 'traj.climb.initial_states:mass')\n", - "prob.model.connect(Mission.Takeoff.GROUND_DISTANCE,\n", + "prob.model.connect(av.Mission.Takeoff.GROUND_DISTANCE,\n", " 'traj.climb.initial_states:range')\n", - "prob.model.connect(Mission.Takeoff.FINAL_VELOCITY,\n", - " 'traj.climb.initial_states:velocity')\n", - "prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE,\n", - " 'traj.climb.initial_states:altitude')\n", "\n", "prob.model.connect('traj.descent.states:mass',\n", - " Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])\n", - "prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE,\n", + " av.Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])\n", + "# TODO: approach velocity should likely be connected\n", + "prob.model.connect('traj.descent.control_values:altitude', av.Mission.Landing.INITIAL_ALTITUDE,\n", " src_indices=[-1])\n", "\n", "##########################\n", + "# Constraints #\n", + "##########################\n", + "\n", + "ecomp = om.ExecComp('fuel_burned = initial_mass - descent_mass_final',\n", + " initial_mass={'units': 'lbm', 'shape': 1},\n", + " descent_mass_final={'units': 'lbm', 'shape': 1},\n", + " fuel_burned={'units': 'lbm', 'shape': 1})\n", + "\n", + "prob.model.add_subsystem('fuel_burn', ecomp,\n", + " promotes_inputs=[\n", + " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", + " promotes_outputs=['fuel_burned'])\n", + "\n", + "prob.model.connect(\"traj.descent.states:mass\",\n", + " \"fuel_burn.descent_mass_final\", src_indices=[-1])\n", + "\n", + "# TODO: need to add some sort of check that this value is less than the fuel capacity\n", + "# TODO: need to update this with actual FLOPS value, this gives unrealistic\n", + "# appearance of accuracy\n", + "# TODO: the overall_fuel variable is the burned fuel plus the reserve, but should\n", + "# also include the unused fuel, and the hierarchy variable name should be more clear\n", + "ecomp = om.ExecComp('overall_fuel = fuel_burned + fuel_reserve',\n", + " fuel_burned={'units': 'lbm', 'shape': 1},\n", + " fuel_reserve={'units': 'lbm', 'val': 2173.},\n", + " overall_fuel={'units': 'lbm'})\n", + "prob.model.add_subsystem('fuel_calc', ecomp,\n", + " promotes_inputs=['fuel_burned'],\n", + " promotes_outputs=['overall_fuel'])\n", + "\n", + "ecomp = om.ExecComp(\n", + " 'mass_resid = operating_empty_mass + overall_fuel + payload_mass '\n", + " '- initial_mass',\n", + " operating_empty_mass={'units': 'lbm'},\n", + " overall_fuel={'units': 'lbm'},\n", + " payload_mass={'units': 'lbm'},\n", + " initial_mass={'units': 'lbm'},\n", + " mass_resid={'units': 'lbm'})\n", + "\n", + "prob.model.add_subsystem(\n", + " 'mass_constraint', ecomp,\n", + " promotes_inputs=[\n", + " ('operating_empty_mass', av.Aircraft.Design.OPERATING_MASS),\n", + " 'overall_fuel',\n", + " ('payload_mass', av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS),\n", + " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", + " promotes_outputs=['mass_resid'])\n", + "\n", + "prob.model.add_constraint('mass_resid', equals=0.0, ref=1.0)\n", + "\n", + "##########################\n", "# Add Objective Function #\n", "##########################\n", "\n", "# This is an example of a overall mission objective\n", "# create a compound objective that minimizes climb time and maximizes final mass\n", "# we are maxing final mass b/c we don't have an independent value for fuel_mass yet\n", - "# we are going to normalize these (makign each of the sub-objectives approx = 1 )\n", + "# we are going to normalize these (making each of the sub-objectives approx = 1 )\n", + "# TODO: change the scaling on climb_duration\n", "prob.model.add_subsystem(\n", " \"regularization\",\n", " om.ExecComp(\n", - " \"reg_objective = - descent_mass_final/60000\",\n", + " \"reg_objective = fuel_mass/1500\",\n", " reg_objective=0.0,\n", - " descent_mass_final={\"units\": \"kg\", \"shape\": 1},\n", + " fuel_mass={\"units\": \"lbm\", \"shape\": 1},\n", " ),\n", " promotes_outputs=['reg_objective']\n", ")\n", "# connect the final mass from cruise into the objective\n", - "prob.model.connect(\"traj.descent.states:mass\",\n", - " \"regularization.descent_mass_final\", src_indices=[-1])\n", + "prob.model.connect(av.Mission.Design.FUEL_MASS, \"regularization.fuel_mass\")\n", "\n", "prob.model.add_objective('reg_objective', ref=1)\n", "\n", + "# Set initial default values for all LEAPS aircraft variables.\n", + "av.set_aviary_initial_values(prob.model, aviary_inputs)\n", + "\n", "prob.model.add_subsystem(\n", " 'input_sink',\n", " av.VariablesIn(aviary_options=aviary_inputs),\n", @@ -416,16 +762,7 @@ " promotes_outputs=['*']\n", ")\n", "\n", - "# suppress warnings:\n", - "# \"input variable '...' promoted using '*' was already promoted using 'aircraft:*'\n", - "with warnings.catch_warnings():\n", - "\n", - " # Set initial default values for all LEAPS aircraft variables.\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", - " av.set_aviary_initial_values(prob.model, aviary_inputs)\n", - "\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", - " prob.setup()\n", + "prob.setup(force_alloc_complex=True)\n", "\n", "###########################################\n", "# Intial Settings for States and Controls #\n", @@ -434,97 +771,79 @@ "prob.set_val('traj.climb.t_initial', t_i_climb, units='s')\n", "prob.set_val('traj.climb.t_duration', t_duration_climb, units='s')\n", "\n", - "prob.set_val('traj.climb.states:altitude', climb.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m')\n", - "# prob.set_val(\n", - "# 'traj.climb.states:velocity', climb.interp(Dynamic.Mission.VELOCITY, ys=[170, v_f_climb]),\n", - "# units='m/s')\n", - "prob.set_val('traj.climb.states:velocity', climb.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s')\n", + "prob.set_val('traj.climb.controls:altitude', climb.interp(\n", + " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m')\n", + "prob.set_val(\n", + " 'traj.climb.controls:mach', climb.interp(\n", + " av.Dynamic.Mission.MACH, ys=[mach_i_climb, mach_f_climb]), units='unitless')\n", "prob.set_val('traj.climb.states:mass', climb.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", + " av.Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", "prob.set_val('traj.climb.states:range', climb.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", - "\n", - "prob.set_val('traj.climb.controls:velocity_rate',\n", - " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", - " units='m/s**2')\n", - "prob.set_val('traj.climb.controls:throttle',\n", - " climb.interp(Dynamic.Mission.THROTTLE, ys=[1.0, 1.0]),\n", - " units='unitless')\n", + " av.Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m')\n", "\n", "prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", "prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", "\n", - "prob.set_val('traj.cruise.states:altitude', cruise.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m')\n", - "prob.set_val('traj.cruise.states:velocity', cruise.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s')\n", + "prob.set_val('traj.cruise.polynomial_controls:altitude', cruise.interp(\n", + " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m')\n", + "prob.set_val(\n", + " 'traj.cruise.polynomial_controls:mach', cruise.interp(\n", + " av.Dynamic.Mission.MACH, ys=[cruise_mach, cruise_mach]), units='unitless')\n", "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", + " av.Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", "prob.set_val('traj.cruise.states:range', cruise.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", - "\n", - "prob.set_val('traj.cruise.controls:velocity_rate',\n", - " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", - " units='m/s**2')\n", - "prob.set_val('traj.cruise.controls:throttle',\n", - " cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.8, 0.75]),\n", - " units='unitless')\n", + " av.Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m')\n", "\n", "prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", "prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", "\n", - "prob.set_val('traj.descent.states:altitude', descent.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m')\n", - "prob.set_val('traj.descent.states:velocity', descent.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s')\n", + "prob.set_val('traj.descent.controls:altitude', descent.interp(\n", + " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m')\n", + "prob.set_val(\n", + " 'traj.descent.controls:mach', descent.interp(\n", + " av.Dynamic.Mission.MACH, ys=[mach_i_descent, mach_f_descent]), units='unitless')\n", "prob.set_val('traj.descent.states:mass', descent.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", + " av.Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", "prob.set_val('traj.descent.states:range', descent.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", - "\n", - "prob.set_val('traj.descent.controls:velocity_rate',\n", - " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", - " units='m/s**2')\n", - "prob.set_val('traj.descent.controls:throttle',\n", - " descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]),\n", - " units='unitless')\n", + " av.Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", "\n", "# Turn off solver printing so that the SNOPT output is readable.\n", "prob.set_solver_print(level=0)\n", "\n", - "dm.run_problem(prob, make_plots=False, solution_record_file='N3CC_full_mission.db')\n", + "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", + " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9},\n", + " solution_record_file='N3CC_sizing.db')\n", "prob.record(\"final\")\n", "prob.cleanup()\n", "\n", "times_climb = prob.get_val('traj.climb.timeseries.time', units='s')\n", "altitudes_climb = prob.get_val(\n", - " 'traj.climb.timeseries.states:altitude', units='m')\n", - "masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg')\n", - "ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m')\n", + " 'traj.climb.timeseries.altitude', units='m')\n", + "masses_climb = prob.get_val('traj.climb.timeseries.mass', units='kg')\n", + "ranges_climb = prob.get_val('traj.climb.timeseries.range', units='m')\n", "velocities_climb = prob.get_val(\n", - " 'traj.climb.timeseries.states:velocity', units='m/s')\n", + " 'traj.climb.timeseries.velocity', units='m/s')\n", "thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')\n", "times_cruise = prob.get_val('traj.cruise.timeseries.time', units='s')\n", "altitudes_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.states:altitude', units='m')\n", - "masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg')\n", - "ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m')\n", + " 'traj.cruise.timeseries.altitude', units='m')\n", + "masses_cruise = prob.get_val('traj.cruise.timeseries.mass', units='kg')\n", + "ranges_cruise = prob.get_val('traj.cruise.timeseries.range', units='m')\n", "velocities_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.states:velocity', units='m/s')\n", + " 'traj.cruise.timeseries.velocity', units='m/s')\n", "thrusts_cruise = prob.get_val(\n", " 'traj.cruise.timeseries.thrust_net_total', units='N')\n", "times_descent = prob.get_val('traj.descent.timeseries.time', units='s')\n", "altitudes_descent = prob.get_val(\n", - " 'traj.descent.timeseries.states:altitude', units='m')\n", - "masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg')\n", - "ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m')\n", + " 'traj.descent.timeseries.altitude', units='m')\n", + "masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg')\n", + "ranges_descent = prob.get_val('traj.descent.timeseries.range', units='m')\n", "velocities_descent = prob.get_val(\n", - " 'traj.descent.timeseries.states:velocity', units='m/s')\n", + " 'traj.descent.timeseries.velocity', units='m/s')\n", "thrusts_descent = prob.get_val(\n", " 'traj.descent.timeseries.thrust_net_total', units='N')\n", "\n", + "\n", "print(\"-------------------------------\")\n", "print(f\"times_climb: {times_climb[-1]} (s)\")\n", "print(f\"altitudes_climb: {altitudes_climb[-1]} (m)\")\n", @@ -547,597 +866,12 @@ "print(\"-------------------------------\")\n" ] }, - { - "cell_type": "markdown", - "id": "4c0f7de8", - "metadata": {}, - "source": [ - "### Move each code block to a function\n", - "\n", - "This code is quite verbose!\n", - "\n", - "To make it easier to follow the steps mentioned above, we split this script into several functions each representing a step at the beginning of this section (except `check_inputs()` and `add_design_variables()`).\n", - "These methods also closely mirror those from `aviary/interface/methods_for_level2.py`, so you can draw parallels between Level 2 and 3.\n", - "\n", - "Here's what the new run script looks like:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1b0432f", - "metadata": {}, - "outputs": [], - "source": [ - "'''\n", - "NOTES:\n", - "Includes:\n", - "Takeoff, Climb, Cruise, Descent, Landing\n", - "Computed Aero\n", - "N3CC data\n", - "'''\n", - "import warnings\n", - "\n", - "import dymos as dm\n", - "import openmdao.api as om\n", - "import scipy.constants as _units\n", - "from packaging import version\n", - "\n", - "import aviary.api as av\n", - "\n", - "use_new_dymos_syntax = version.parse(dm.__version__) > version.parse(\"1.8.0\")\n", - "\n", - "\n", - "##########################################\n", - "# Phase Info\n", - "##########################################\n", - "\n", - "alt_airport = 0 # ft\n", - "cruise_mach = .785\n", - "\n", - "alt_i_climb = 0*_units.foot # m\n", - "alt_f_climb = 35000.0*_units.foot # m\n", - "mass_i_climb = 131000*_units.lb # kg\n", - "mass_f_climb = 126000*_units.lb # kg\n", - "v_i_climb = 198.44*_units.knot # m/s\n", - "v_f_climb = 455.49*_units.knot # m/s\n", - "# initial mach set to lower value so it can intersect with takeoff end mach\n", - "# mach_i_climb = 0.3\n", - "mach_i_climb = 0.2\n", - "mach_f_climb = cruise_mach\n", - "range_i_climb = 0*_units.nautical_mile # m\n", - "range_f_climb = 160.3*_units.nautical_mile # m\n", - "t_i_climb = 2 * _units.minute # sec\n", - "t_f_climb = 26.20*_units.minute # sec\n", - "t_duration_climb = t_f_climb - t_i_climb\n", - "\n", - "alt_i_cruise = 35000*_units.foot # m\n", - "alt_f_cruise = 35000*_units.foot # m\n", - "alt_min_cruise = 35000*_units.foot # m\n", - "alt_max_cruise = 35000*_units.foot # m\n", - "mass_i_cruise = 126000*_units.lb # kg\n", - "mass_f_cruise = 102000*_units.lb # kg\n", - "v_i_cruise = 455.49*_units.knot # m/s\n", - "v_f_cruise = 455.49*_units.knot # m/s\n", - "mach_min_cruise = cruise_mach\n", - "mach_max_cruise = cruise_mach\n", - "range_i_cruise = 160.3*_units.nautical_mile # m\n", - "range_f_cruise = 3243.9*_units.nautical_mile # m\n", - "t_i_cruise = 26.20*_units.minute # sec\n", - "t_f_cruise = 432.38*_units.minute # sec\n", - "t_duration_cruise = t_f_cruise - t_i_cruise\n", - "\n", - "alt_i_descent = 35000*_units.foot\n", - "# final altitude set to 35 to ensure landing is feasible point\n", - "# alt_f_descent = 0*_units.foot\n", - "alt_f_descent = 35*_units.foot\n", - "v_i_descent = 455.49*_units.knot\n", - "v_f_descent = 198.44*_units.knot\n", - "mach_i_descent = cruise_mach\n", - "mach_f_descent = 0.3\n", - "mass_i_descent = 102000*_units.pound\n", - "mass_f_descent = 101000*_units.pound\n", - "range_i_descent = 3243.9*_units.nautical_mile\n", - "range_f_descent = 3378.7*_units.nautical_mile\n", - "t_i_descent = 432.38*_units.minute\n", - "t_f_descent = 461.62*_units.minute\n", - "t_duration_descent = t_f_descent - t_i_descent\n", - "\n", - "def load_inputs():\n", - " aviary_inputs = av.get_flops_inputs('N3CC')\n", - "\n", - " aviary_inputs.set_val(\n", - " Mission.Landing.LIFT_COEFFICIENT_MAX, 2.4, units='unitless')\n", - " aviary_inputs.set_val(\n", - " Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, units='unitless')\n", - " aviary_inputs.set_val(\n", - " Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=.0175,\n", - " units='unitless')\n", - "\n", - " takeoff_fuel_burned = 577 # lbm\n", - " takeoff_thrust_per_eng = 24555.5 # lbf\n", - " takeoff_L_over_D = 17.35\n", - "\n", - " aviary_inputs.set_val(\n", - " Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm')\n", - " aviary_inputs.set_val(\n", - " Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless')\n", - " aviary_inputs.set_val(\n", - " Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf')\n", - "\n", - " return aviary_inputs\n", - "\n", - "\n", - "def add_pre_mission_system(aviary_inputs, prob):\n", - " takeoff_options = av.HeightEnergyTakeoffPhaseBuilder(\n", - " airport_altitude=alt_airport, # ft\n", - " num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES)\n", - " )\n", - "\n", - " av.preprocess_crewpayload(aviary_inputs)\n", - "\n", - " # Upstream static analysis for aero\n", - " prob.model.add_subsystem(\n", - " 'pre_mission',\n", - " av.CorePreMission(aviary_options=aviary_inputs,\n", - " subsystems=av.default_premission_subsystems),\n", - " promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['aircraft:*', 'mission:*'])\n", - "\n", - " takeoff = takeoff_options.build_phase(False)\n", - "\n", - " prob.model.add_subsystem(\n", - " 'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['mission:*'])\n", - "\n", - " prob.model.add_subsystem(\n", - " \"takeoff_constraints\",\n", - " om.ExecComp(\n", - " [\n", - " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_range_con=takeoff_range-climb_start_range\",\n", - " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", - " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", - " ],\n", - " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", - " climb_start_mass={'units': 'lbm'},\n", - " takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", - " climb_start_range={'units': 'ft'},\n", - " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", - " climb_start_vel={'units': 'm/s'},\n", - " takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'},\n", - " climb_start_alt={'units': 'ft'}\n", - " ),\n", - " promotes_inputs=[\n", - " (\"takeoff_mass\", Mission.Takeoff.FINAL_MASS),\n", - " (\"takeoff_range\", Mission.Takeoff.GROUND_DISTANCE),\n", - " (\"takeoff_vel\", Mission.Takeoff.FINAL_VELOCITY),\n", - " (\"takeoff_alt\", Mission.Takeoff.FINAL_ALTITUDE),\n", - " ],\n", - " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_range_con\",\n", - " \"takeoff_vel_con\", \"takeoff_alt_con\"],\n", - " )\n", - "\n", - " prob.model.connect(Mission.Takeoff.FINAL_MASS,\n", - " 'traj.climb.initial_states:mass')\n", - " prob.model.connect(Mission.Takeoff.GROUND_DISTANCE,\n", - " 'traj.climb.initial_states:range')\n", - " prob.model.connect(Mission.Takeoff.FINAL_VELOCITY,\n", - " 'traj.climb.initial_states:velocity')\n", - " prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE,\n", - " 'traj.climb.initial_states:altitude')\n", - "\n", - "\n", - "def add_post_mission_systems(aviary_inputs, prob):\n", - " landing_options = av.HeightEnergyLandingPhaseBuilder(\n", - " ref_wing_area=aviary_inputs.get_val(Aircraft.Wing.AREA, 'ft**2'),\n", - " Cl_max_ldg=aviary_inputs.get_val(Mission.Landing.LIFT_COEFFICIENT_MAX)\n", - " )\n", - "\n", - " landing = landing_options.build_phase(\n", - " False,\n", - " )\n", - "\n", - " prob.model.add_subsystem(\n", - " 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['mission:*'])\n", - "\n", - " prob.model.connect('traj.descent.states:mass',\n", - " Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])\n", - " prob.model.connect('traj.descent.states:altitude', Mission.Landing.INITIAL_ALTITUDE,\n", - " src_indices=[-1])\n", - "\n", - "\n", - "def set_initial_guesses(prob, traj):\n", - " # have to add this block to recover climb, cruise, and descent phases first\n", - " phase_items = traj._phases.items()\n", - " for idx, (_, phase) in enumerate(phase_items):\n", - " if idx == 0: climb = phase\n", - " elif idx == 1: cruise = phase\n", - " else: descent = phase\n", - "\n", - " prob.set_val('traj.climb.t_initial', t_i_climb, units='s')\n", - " prob.set_val('traj.climb.t_duration', t_duration_climb, units='s')\n", - "\n", - " prob.set_val('traj.climb.states:altitude', climb.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m')\n", - " # prob.set_val(\n", - " # 'traj.climb.states:velocity', climb.interp(Dynamic.Mission.VELOCITY, ys=[170, v_f_climb]),\n", - " # units='m/s')\n", - " prob.set_val('traj.climb.states:velocity', climb.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s')\n", - " prob.set_val('traj.climb.states:mass', climb.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - " prob.set_val('traj.climb.states:range', climb.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", - "\n", - " prob.set_val('traj.climb.controls:velocity_rate',\n", - " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", - " units='m/s**2')\n", - " prob.set_val('traj.climb.controls:throttle',\n", - " climb.interp(Dynamic.Mission.THROTTLE, ys=[1.0, 1.0]),\n", - " units='unitless')\n", - "\n", - " prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", - " prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", - "\n", - " prob.set_val('traj.cruise.states:altitude', cruise.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m')\n", - " prob.set_val('traj.cruise.states:velocity', cruise.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s')\n", - " prob.set_val('traj.cruise.states:mass', cruise.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - " prob.set_val('traj.cruise.states:range', cruise.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", - "\n", - " prob.set_val('traj.cruise.controls:velocity_rate',\n", - " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", - " units='m/s**2')\n", - " prob.set_val('traj.cruise.controls:throttle',\n", - " cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.8, 0.75]),\n", - " units='unitless')\n", - "\n", - " prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", - " prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", - "\n", - " prob.set_val('traj.descent.states:altitude', descent.interp(\n", - " Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m')\n", - " prob.set_val('traj.descent.states:velocity', descent.interp(\n", - " Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s')\n", - " prob.set_val('traj.descent.states:mass', descent.interp(\n", - " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - " prob.set_val('traj.descent.states:range', descent.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", - "\n", - " prob.set_val('traj.descent.controls:velocity_rate',\n", - " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", - " units='m/s**2')\n", - " prob.set_val('traj.descent.controls:throttle',\n", - " descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]),\n", - " units='unitless')\n", - "\n", - "\n", - "def setup(aviary_inputs, prob):\n", - " prob.model.add_subsystem(\n", - " 'input_sink',\n", - " av.VariablesIn(aviary_options=aviary_inputs),\n", - " promotes_inputs=['*'],\n", - " promotes_outputs=['*']\n", - " )\n", - "\n", - " # suppress warnings:\n", - " # \"input variable '...' promoted using '*' was already promoted using 'aircraft:*'\n", - " with warnings.catch_warnings():\n", - "\n", - " # Set initial default values for all LEAPS aircraft variables.\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", - " av.set_aviary_initial_values(prob.model, aviary_inputs)\n", - "\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", - " prob.setup()\n", - "\n", - "\n", - "def add_objective(prob):\n", - " # This is an example of a overall mission objective\n", - " # create a compound objective that minimizes climb time and maximizes final mass\n", - " # we are maxing final mass b/c we don't have an independent value for fuel_mass yet\n", - " # we are going to normalize these (makign each of the sub-objectives approx = 1 )\n", - " prob.model.add_subsystem(\n", - " \"regularization\",\n", - " om.ExecComp(\n", - " \"reg_objective = - descent_mass_final/60000\",\n", - " reg_objective=0.0,\n", - " descent_mass_final={\"units\": \"kg\", \"shape\": 1},\n", - " ),\n", - " promotes_outputs=['reg_objective']\n", - " )\n", - " # connect the final mass from descent into the objective\n", - " prob.model.connect(\"traj.descent.states:mass\",\n", - " \"regularization.descent_mass_final\", src_indices=[-1])\n", - "\n", - " prob.model.add_objective('reg_objective', ref=1)\n", - "\n", - "\n", - "def add_phases(aviary_inputs, prob):\n", - " ##################\n", - " # Define Phases #\n", - " ##################\n", - "\n", - " num_segments_climb = 6\n", - " num_segments_cruise = 1\n", - " num_segments_descent = 5\n", - "\n", - " climb_seg_ends, _ = dm.utils.lgl.lgl(num_segments_climb + 1)\n", - " descent_seg_ends, _ = dm.utils.lgl.lgl(num_segments_descent + 1)\n", - "\n", - " transcription_climb = dm.Radau(\n", - " num_segments=num_segments_climb, order=3, compressed=True,\n", - " segment_ends=climb_seg_ends)\n", - " transcription_cruise = dm.Radau(\n", - " num_segments=num_segments_cruise, order=3, compressed=True)\n", - " transcription_descent = dm.Radau(\n", - " num_segments=num_segments_descent, order=3, compressed=True,\n", - " segment_ends=descent_seg_ends)\n", - "\n", - " climb_options = av.HeightEnergyClimbPhaseBuilder(\n", - " 'test_climb',\n", - " user_options=av.AviaryValues({\n", - " 'initial_altitude': (alt_i_climb, 'm'),\n", - " 'final_altitude': (alt_f_climb, 'm'),\n", - " 'initial_mach': (mach_i_climb, 'unitless'),\n", - " 'final_mach': (mach_f_climb, 'unitless'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'fix_range': (False, 'unitless'),\n", - " 'input_initial': (True, 'unitless'),\n", - " }),\n", - " core_subsystems=av.default_mission_subsystems,\n", - " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", - " transcription=transcription_climb,\n", - " )\n", - "\n", - " cruise_options = av.HeightEnergyCruisePhaseBuilder(\n", - " 'test_cruise',\n", - " user_options=av.AviaryValues({\n", - " 'min_altitude': (alt_min_cruise, 'm'),\n", - " 'max_altitude': (alt_max_cruise, 'm'),\n", - " 'min_mach': (mach_min_cruise, 'unitless'),\n", - " 'max_mach': (mach_max_cruise, 'unitless'),\n", - " 'required_available_climb_rate': (300, 'ft/min'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'fix_final': (False, 'unitless'),\n", - " }),\n", - " core_subsystems=av.default_mission_subsystems,\n", - " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", - " transcription=transcription_cruise,\n", - " )\n", - "\n", - " descent_options = av.HeightEnergyDescentPhaseBuilder(\n", - " 'test_descent',\n", - " user_options=av.AviaryValues({\n", - " 'final_altitude': (alt_f_descent, 'm'),\n", - " 'initial_altitude': (alt_i_descent, 'm'),\n", - " 'initial_mach': (mach_i_descent, 'unitless'),\n", - " 'final_mach': (mach_f_descent, 'unitless'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'fix_range': (True, 'unitless'),\n", - " }),\n", - " core_subsystems=av.default_mission_subsystems,\n", - " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", - " transcription=transcription_descent,\n", - " )\n", - "\n", - " climb = climb_options.build_phase(aviary_options=aviary_inputs)\n", - "\n", - " cruise = cruise_options.build_phase(aviary_options=aviary_inputs)\n", - "\n", - " descent = descent_options.build_phase(aviary_options=aviary_inputs)\n", - "\n", - " traj = prob.model.add_subsystem('traj', dm.Trajectory())\n", - "\n", - " climb.set_time_options(\n", - " fix_initial=True, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_climb*2), duration_ref=t_duration_climb)\n", - " cruise.set_time_options(\n", - " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise)\n", - " descent.set_time_options(\n", - " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(1, t_duration_descent*2), duration_ref=t_duration_descent)\n", - "\n", - " traj.add_phase('climb', climb)\n", - "\n", - " traj.add_phase('cruise', cruise)\n", - "\n", - " traj.add_phase('descent', descent)\n", - "\n", - " if use_new_dymos_syntax: # needed for print_outputs()\n", - " climb.timeseries_options['use_prefix'] = True\n", - " cruise.timeseries_options['use_prefix'] = True\n", - " descent.timeseries_options['use_prefix'] = True\n", - "\n", - " return traj\n", - "\n", - "\n", - "def link_phases(aviary_inputs, prob, traj):\n", - " # directly connect phases (strong_couple = True), or use linkage constraints (weak\n", - " # coupling / strong_couple=False)\n", - " strong_couple = False\n", - "\n", - " traj.link_phases([\"climb\", \"cruise\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", - " traj.link_phases([\"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", - "\n", - " traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", - "\n", - " ##################################\n", - " # Connect in Takeoff #\n", - " ##################################\n", - "\n", - " prob.model.connect('traj.climb.states:mass',\n", - " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", - " prob.model.connect('traj.climb.states:range',\n", - " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", - " prob.model.connect('traj.climb.states:velocity',\n", - " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", - " prob.model.connect('traj.climb.states:altitude',\n", - " 'takeoff_constraints.climb_start_alt', src_indices=[0])\n", - "\n", - "\n", - "def run_aviary_problem(prob, sim):\n", - " # Turn off solver printing so that the SNOPT output is readable.\n", - " prob.set_solver_print(level=0)\n", - "\n", - " dm.run_problem(prob, simulate=sim, make_plots=True, simulate_kwargs={\n", - " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9}, \n", - " solution_record_file='N3CC_full_mission.db')\n", - " prob.record(\"final\")\n", - " prob.cleanup()\n", - "\n", - "\n", - "def run_N3CC_full_mission(sim=True):\n", - " ##########################################\n", - " # Build problem #\n", - " ##########################################\n", - " prob = om.Problem(model=om.Group())\n", - " #prob.driver = driver\n", - "\n", - " traj = None\n", - "\n", - " ##########################################\n", - " # Aircraft Input Variables and Options #\n", - " ##########################################\n", - "\n", - " aviary_inputs = load_inputs()\n", - "\n", - " ##########################################\n", - " # add pre-mission systems #\n", - " ##########################################\n", - "\n", - " add_pre_mission_system(aviary_inputs, prob)\n", - "\n", - " ##########################################\n", - " # add phases #\n", - " ##########################################\n", - "\n", - " traj = add_phases(aviary_inputs, prob)\n", - "\n", - " ##########################################\n", - " # add post mission system #\n", - " ##########################################\n", - "\n", - " add_post_mission_systems(aviary_inputs, prob)\n", - "\n", - " ##########################################\n", - " # add driver #\n", - " ##########################################\n", - "\n", - " prob.driver = add_driver()\n", - "\n", - " ##########################################\n", - " # link phases #\n", - " ##########################################\n", - "\n", - " link_phases(aviary_inputs, prob, traj)\n", - "\n", - " ##########################\n", - " # Add Objective Function #\n", - " ##########################\n", - "\n", - " add_objective(prob)\n", - "\n", - " #######\n", - " # setup\n", - " #######\n", - "\n", - " setup(aviary_inputs, prob)\n", - "\n", - " ###########################################\n", - " # Intial Settings for States and Controls #\n", - " ###########################################\n", - "\n", - " set_initial_guesses(prob, traj)\n", - "\n", - " #####################\n", - " # run aviary problem\n", - " #####################\n", - "\n", - " run_aviary_problem(prob, sim)\n", - "\n", - " print_outputs(prob)\n", - "\n", - "\n", - "def add_driver():\n", - " driver = om.ScipyOptimizeDriver()\n", - " driver.options['optimizer'] = 'SLSQP'\n", - " driver.opt_settings['maxiter'] = 0\n", - " driver.opt_settings['ftol'] = 5.0e-3\n", - " driver.opt_settings['eps'] = 1e-2\n", - "\n", - " return driver\n", - "\n", - "\n", - "def print_outputs(prob):\n", - " times_climb = prob.get_val('traj.climb.timeseries.time', units='s')\n", - " altitudes_climb = prob.get_val(\n", - " 'traj.climb.timeseries.states:altitude', units='m')\n", - " masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg')\n", - " ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m')\n", - " velocities_climb = prob.get_val(\n", - " 'traj.climb.timeseries.states:velocity', units='m/s')\n", - " thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')\n", - " times_cruise = prob.get_val('traj.cruise.timeseries.time', units='s')\n", - " altitudes_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.states:altitude', units='m')\n", - " masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg')\n", - " ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m')\n", - " velocities_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.states:velocity', units='m/s')\n", - " thrusts_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.thrust_net_total', units='N')\n", - " times_descent = prob.get_val('traj.descent.timeseries.time', units='s')\n", - " altitudes_descent = prob.get_val(\n", - " 'traj.descent.timeseries.states:altitude', units='m')\n", - " masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg')\n", - " ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m')\n", - " velocities_descent = prob.get_val(\n", - " 'traj.descent.timeseries.states:velocity', units='m/s')\n", - " thrusts_descent = prob.get_val(\n", - " 'traj.descent.timeseries.thrust_net_total', units='N')\n", - "\n", - " print(\"-------------------------------\")\n", - " print(f\"times_climb: {times_climb[-1]} (s)\")\n", - " print(f\"altitudes_climb: {altitudes_climb[-1]} (m)\")\n", - " print(f\"masses_climb: {masses_climb[-1]} (kg)\")\n", - " print(f\"ranges_climb: {ranges_climb[-1]} (m)\")\n", - " print(f\"velocities_climb: {velocities_climb[-1]} (m/s)\")\n", - " print(f\"thrusts_climb: {thrusts_climb[-1]} (N)\")\n", - " print(f\"times_cruise: {times_cruise[-1]} (s)\")\n", - " print(f\"altitudes_cruise: {altitudes_cruise[-1]} (m)\")\n", - " print(f\"masses_cruise: {masses_cruise[-1]} (kg)\")\n", - " print(f\"ranges_cruise: {ranges_cruise[-1]} (m)\")\n", - " print(f\"velocities_cruise: {velocities_cruise[-1]} (m/s)\")\n", - " print(f\"thrusts_cruise: {thrusts_cruise[-1]} (N)\")\n", - " print(f\"times_descent: {times_descent[-1]} (s)\")\n", - " print(f\"altitudes_descent: {altitudes_descent[-1]} (m)\")\n", - " print(f\"masses_descent: {masses_descent[-1]} (kg)\")\n", - " print(f\"ranges_descent: {ranges_descent[-1]} (m)\")\n", - " print(f\"velocities_descent: {velocities_descent[-1]} (m/s)\")\n", - " print(f\"thrusts_descent: {thrusts_descent[-1]} (N)\")\n", - " print(\"-------------------------------\")\n", - "\n", - "\n", - "run_N3CC_full_mission(sim=False)" - ] - }, { "cell_type": "markdown", "id": "2b43d293", "metadata": {}, "source": [ - "You see the same outputs.\n", - "\n", - "This model demonstrates the flexibility of level 3. For example, the `load_inputs` function does not load the aircraft model from a `.csv` file but from a Python file using the `get_flops_inputs()` method.\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.\n", "\n", "This function not only reads Aviary and mission variables but also builds the engine. More information can be found in `aviary/models/N3CC/N3CC_data.py`.\n", "\n", From feebdeac7ec66e48b087ba49e70a96137cd6b559 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Tue, 9 Jan 2024 12:52:55 -0500 Subject: [PATCH 018/111] write description of initial guess of reserves in input_csv_phase_info.md --- aviary/docs/getting_started/input_csv_phase_info.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index 6f3781fd3..01f0a59db 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -18,13 +18,13 @@ This section is under development. - climb_range: 0, - reserves: 0 -The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than or equal to 0. There are two variables to control the reserve fuel in the model file (`.csv`): +The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than or equal to 0. There are two Aviary variables to control the reserve fuel in the model file (`.csv`): - `Aircraft.Design.FIXED_RESERVES_FUEL`: the required fuel reserves: directly in lbm, -- `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel, +- `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel. -If the value of initial guess of `reserves` is not 0 and is within the allowed range, the initial guess of reserve fuel is determined by the parameter `reserves`: -- if `reserves > 1.0`, we set `Aircraft.Design.FIXED_RESERVES_FUEL = reserves`, -- if `0.0 <= reserves <= 1.0`, we set `Aircraft.Design.RESERVES_FRACTION = reserves`. +Users should set one of them to zero. If the value of initial guess of `reserves` (also in the model file if any) is 0, the initial guess of reserve fuel comes from the above two Aviary variables. Otherwise, it is determined by the parameter `reserves`: +- if `reserves > 10`, we assume it is the actual fuel reserves. +- if `0.0 <= reserves <= 10`, we assume it is the fraction of the mission fuel. The case when `reserves` is between 1 and 10 is non-sensical but technically valid. The initial guess of `reserves` is always converted to the actual design reserves (instead of reserve factor) and is used to update the initial guesses of `fuel_burn_per_passenger_mile` and `cruise_mass_final`. From eb1944121406c0019b51286c71879d52569d77de Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Tue, 9 Jan 2024 12:54:46 -0500 Subject: [PATCH 019/111] allow reserves fraction to be greater than 1 in methods_for_level2.py --- aviary/interface/methods_for_level2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 3667ae4e9..57680022d 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2438,7 +2438,7 @@ def _add_gasp_landing_systems(self): def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL): reserves_val = self.aviary_inputs.get_val( Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') - reserves_fac = self.aviary_inputs.get_val( + reserves_frac = self.aviary_inputs.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') if reserves_val > 0.0: self.model.add_subsystem( @@ -2449,11 +2449,11 @@ def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL) ), promotes_outputs=[("reserve_fuel", reserves_name)], ) - elif reserves_fac >= 0 and reserves_fac <= 1: + elif reserves_frac >= 0: self.model.add_subsystem( "reserves_calc", om.ExecComp( - f"reserve_fuel = {reserves_fac}*(takeoff_mass - final_mass)", + f"reserve_fuel = {reserves_frac}*(takeoff_mass - final_mass)", takeoff_mass={"units": "lbm"}, final_mass={"units": "lbm"}, reserve_fuel={"units": "lbm"} From 4867a4386e78cc8e7096e3d9acdb0d758b5c3af5 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Tue, 9 Jan 2024 12:56:20 -0500 Subject: [PATCH 020/111] describe RESERVES_FRACTION in more detail. --- aviary/variable_info/variable_meta_data.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 0c949e1c2..966c4aa18 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1206,7 +1206,10 @@ }, option=True, units="unitless", - desc='required fuel reserves: given as a proportion of mission fuel', + desc='required fuel reserves: given as a proportion of mission fuel. This value must be nonnegative.\ + If it is 0.5, the reserve fuel is half of the mission fuel (one third of the total fuel). Note\ + it can be greater than 1. If it is 2, there would be twice as much reserve fuel as mission fuel\ + (the total fuel carried would be 1/3 for the mission and 2/3 for the reserve)', default_value=0, ) From 88f37979220986a4dae9cb19177fc90544bc96d7 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Tue, 9 Jan 2024 12:58:18 -0500 Subject: [PATCH 021/111] allow initial guess of reserves fuel in model file to have a fraction greater than 1. --- aviary/utils/process_input_decks.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 7f2698895..924d79214 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -168,29 +168,25 @@ def initial_guessing(aircraft_values: AviaryValues()): if initial_guesses['reserves'] == 0: reserves = aircraft_values.get_val( Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') + reserves_option = "direct_val" if reserves == 0: reserves = aircraft_values.get_val( Aircraft.Design.RESERVES_FRACTION, units='unitless') + reserves_option = "fraction_val" else: reserves = initial_guesses['reserves'] if reserves < 0.0: raise ValueError('initial_guesses["reserves"] must be greater than 0.') - elif reserves <= 1.0: - aircraft_values.set_val( - Aircraft.Design.FIXED_RESERVES_FUEL, 0.0, units='lbm') - aircraft_values.set_val( - Aircraft.Design.RESERVES_FRACTION, reserves, units='unitless') + elif reserves > 10: + reserves_option = "direct_val" else: - aircraft_values.set_val( - Aircraft.Design.FIXED_RESERVES_FUEL, reserves, units='lbm') - aircraft_values.set_val( - Aircraft.Design.RESERVES_FRACTION, 0.0, units='unitless') + reserves_option = "fraction_val" num_pax = aircraft_values.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - if reserves <= 0: - reserves *= -(num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * - aircraft_values.get_val(Mission.Design.RANGE, units='NM')) + if reserves_option == "fraction_val": + reserves *= (num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * + aircraft_values.get_val(Mission.Design.RANGE, units='NM')) initial_guesses['reserves'] = reserves if Mission.Summary.GROSS_MASS in aircraft_values: From da3029e45c3e1b1d140643d0ce4d61a3a2c32a67 Mon Sep 17 00:00:00 2001 From: "Kenneth T. Moore" Date: Tue, 9 Jan 2024 14:53:41 -0500 Subject: [PATCH 022/111] This PR uses a feature that is only working correctly on the dev branch of OpenMDAO --- .github/workflows/test_workflow.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 3edbe2f3e..f1d6cc706 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -42,7 +42,7 @@ jobs: SCIPY: '1.6' PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - OPENMDAO: '3.27' + OPENMDAO: 'dev' DYMOS: '1.8.0' MAKE_DOCS: 0 @@ -64,7 +64,7 @@ jobs: SCIPY: 1 PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - OPENMDAO: 'latest' + OPENMDAO: 'dev' DYMOS: 'latest' MAKE_DOCS: 0 @@ -75,7 +75,7 @@ jobs: SCIPY: 1 PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - OPENMDAO: 'latest' + OPENMDAO: 'dev' DYMOS: 'latest' MAKE_DOCS: 1 From a7c5d16178a986ce61ab23b788f8a4205907a25b Mon Sep 17 00:00:00 2001 From: "Kenneth T. Moore" Date: Tue, 9 Jan 2024 15:00:44 -0500 Subject: [PATCH 023/111] This PR uses a feature that is only working correctly on the dev branch of OpenMDAO --- .github/workflows/test_workflow_no_dev_install.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index 14d2d2002..76c30870e 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -24,7 +24,7 @@ jobs: matrix: include: # latest versions of openmdao/dymos - - NAME: latest + - NAME: dev PY: 3 steps: @@ -87,4 +87,4 @@ jobs: echo "=============================================================" echo "Run Tests" echo "=============================================================" - testflo . -n 1 --show_skipped \ No newline at end of file + testflo . -n 1 --show_skipped From c55a7d451dce1802e43b0db80cc36ce6d5a180a9 Mon Sep 17 00:00:00 2001 From: "Kenneth T. Moore" Date: Tue, 9 Jan 2024 15:49:42 -0500 Subject: [PATCH 024/111] resolve conflict --- .github/workflows/test_workflow_no_dev_install.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index bc916c255..fa78fb1db 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -24,8 +24,9 @@ jobs: matrix: include: # latest versions of openmdao/dymos - - NAME: dev + - NAME: latest PY: 3 + OPENMDAO: 'dev' steps: - name: Display run details From ae3daeb2eb6298749beb66bc01343ec7759964fd Mon Sep 17 00:00:00 2001 From: "Kenneth T. Moore" Date: Tue, 9 Jan 2024 15:57:42 -0500 Subject: [PATCH 025/111] This PR uses a feature that is only working correctly on the dev branch of OpenMDAO --- .github/workflows/test_workflow_no_dev_install.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index fa78fb1db..fdc417d36 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -26,7 +26,6 @@ jobs: # latest versions of openmdao/dymos - NAME: latest PY: 3 - OPENMDAO: 'dev' steps: - name: Display run details @@ -56,6 +55,16 @@ jobs: auto-update-conda: true python-version: ${{ matrix.PY }} + - name: Install OpenMDAO Dev + shell: bash -l {0} + run: | + echo "=============================================================" + echo "THIS STEP IS TEMPORARY" + echo "Please remove after the release of OpenMDAO 3.31." + echo "Install OpenMDAO" + echo "=============================================================" + pip install git+https://github.com/OpenMDAO/OpenMDAO + - name: Checkout Aviary uses: actions/checkout@v2 From 3781c7eef0dffa97954c502c5b38159a45a5bfc7 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Thu, 11 Jan 2024 09:49:36 -0500 Subject: [PATCH 026/111] Removed comment no longer needed --- aviary/visualization/dashboard.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index 330f01fc1..aa1ebf8e2 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -556,7 +556,6 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): if __name__ == "__main__": - # so we can get the files written to the repo top directory parser = argparse.ArgumentParser() _dashboard_setup_parser(parser) args = parser.parse_args() From 3f49ee0560d1c1a5b3360fceddf0671da615976b Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Thu, 11 Jan 2024 09:55:50 -0500 Subject: [PATCH 027/111] PEP8 fix --- aviary/interface/test/test_simple_mission.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 327843fcd..78ec4902c 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -4,6 +4,7 @@ from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs import subprocess + @use_tempdirs class AircraftMissionTestSuite(unittest.TestCase): From c9f956a978fb4e254024ba12b7d8933f2b1f9e92 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 11 Jan 2024 13:58:43 -0600 Subject: [PATCH 028/111] All tests, docs, and benches pass --- aviary/api.py | 4 +- ...oupled_aircraft_mission_optimization.ipynb | 7 - .../getting_started/onboarding_level1.ipynb | 2 +- .../getting_started/onboarding_level2.ipynb | 14 +- ..._same_mission_at_different_UI_levels.ipynb | 2 +- .../docs/user_guide/features/overriding.ipynb | 2 +- .../battery/run_multiphase_mission.py | 2 +- aviary/interface/methods_for_level2.py | 7 +- aviary/interface/test/test_basic_report.py | 2 +- .../interface/test/test_check_phase_info.py | 12 +- aviary/interface/test/test_phase_info.py | 4 +- aviary/interface/test/test_reserve_support.py | 2 +- aviary/interface/utils/check_phase_info.py | 66 +--- .../flops_based/ode/test/test_landing_ode.py | 2 +- .../flops_based/ode/test/test_takeoff_ode.py | 2 +- .../test_bench_climb_large_single_aisle_1.py | 260 ------------- .../test_bench_climb_large_single_aisle_2.py | 366 ------------------ ...bench_cruise_climb_large_single_aisle_1.py | 316 --------------- .../test_bench_cruise_large_single_aisle_1.py | 253 ------------ .../test_bench_cruise_large_single_aisle_2.py | 247 ------------ ...test_bench_descent_large_single_aisle_1.py | 255 ------------ ...test_bench_descent_large_single_aisle_2.py | 256 ------------ .../phases/run_phases/run_ascent.py | 2 +- aviary/models/N3CC/N3CC_data.py | 4 +- ...N3CC_generic_low_speed_polars_FLOPSinp.csv | 2 +- .../large_single_aisle_1_FLOPS_data.py | 2 +- .../large_single_aisle_2_FLOPS_data.py | 2 +- .../large_single_aisle_2_altwt_FLOPS_data.py | 2 +- ...ge_single_aisle_2_detailwing_FLOPS_data.py | 2 +- .../test_aircraft/aircraft_for_bench_FwFm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- .../test/test_computed_aero_group.py | 2 +- .../test/test_solved_aero_group.py | 3 +- .../test/test_tabular_aero_group.py | 2 +- .../test/test_flops_based_premission.py | 2 +- aviary/utils/Fortran_to_Aviary.py | 2 +- .../benchmark_tests/test_0_iters.py | 6 +- .../test_FLOPS_balanced_field_length.py | 2 +- .../test_FLOPS_based_sizing_N3CC.py | 2 +- .../test_FLOPS_detailed_landing.py | 2 +- .../test_FLOPS_detailed_takeoff.py | 2 +- .../benchmark_tests/test_bench_FwFm.py | 3 - aviary/variable_info/enums.py | 1 - 43 files changed, 68 insertions(+), 2064 deletions(-) delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py delete mode 100644 aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py diff --git a/aviary/api.py b/aviary/api.py index 0f86edfb9..d86b1158f 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -32,7 +32,7 @@ from aviary.utils.data_interpolator_builder import build_data_interpolator from aviary.variable_info.enums import AlphaModes, AnalysisScheme, ProblemType, SpeedType, GASPEngineType, FlapType, EquationsOfMotion, LegacyCode, Verbosity from aviary.interface.default_phase_info.two_dof import phase_info as default_2DOF_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as default_height_energy_phase_info +from aviary.interface.default_phase_info.simple import phase_info as default_simple_phase_info from aviary.interface.default_phase_info.two_dof_fiti import create_2dof_based_ascent_phases, create_2dof_based_descent_phases from aviary.interface.default_phase_info.solved import phase_info as default_solved_phase_info from aviary.interface.default_phase_info.simple import phase_info as default_simple_phase_info @@ -46,7 +46,7 @@ from aviary.utils.options import list_options from aviary.constants import GRAV_METRIC_GASP, GRAV_ENGLISH_GASP, GRAV_METRIC_FLOPS, GRAV_ENGLISH_FLOPS, GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH, RHO_SEA_LEVEL_METRIC, MU_TAKEOFF, MU_LANDING, PSLS_PSF, TSLS_DEGR, RADIUS_EARTH_METRIC from aviary.subsystems.test.subsystem_tester import TestSubsystemBuilderBase, skipIfMissingDependencies -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems, default_mission_subsystems ################### # Level 3 Imports # diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index 631f5fe37..68344b92a 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -126,13 +126,6 @@ "}" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/aviary/docs/getting_started/onboarding_level1.ipynb b/aviary/docs/getting_started/onboarding_level1.ipynb index 62fff50a8..853ed37e9 100644 --- a/aviary/docs/getting_started/onboarding_level1.ipynb +++ b/aviary/docs/getting_started/onboarding_level1.ipynb @@ -253,7 +253,7 @@ " - `mission:objectives:fuel` if `mission_method` is `GASP` \n", " - `fuel_burned` if `mission_method` is `FLOPS`.\n", "\n", - "- `--phase_info`: Path to phase info file. If not provided, it is `default_phase_info/gasp.py` if Mission origin is `2DOF` and `default_phase_info/flops.py` for `height_energy`.\n", + "- `--phase_info`: Path to phase info file. If not provided, it is `default_phase_info/gasp.py` if Mission origin is `2DOF` and `default_phase_info/flops.py` for `simple`.\n", "\n", "- `--n2`: Generate an n2 diagram after the analysis. “[N2](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_basics/n2_basics.html)” diagram is an OpenMDAO helper to visualize the model (see [details](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_details/n2_details.html) too and [tutorial](https://www.youtube.com/watch?v=42VtbX6CX3A)). It is highly recommended that this option is turned on for new users.\n", "\n", diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index a4ab72b3a..30d1e1c7c 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -271,7 +271,7 @@ "source": [ "This call adds a pre-mission group (also called static analysis group) which includes pre-mission propulsion, geometry, pre-mission aerodynamics, and mass subsystems. \n", "\n", - "For `height_energy` missions, aviary currently models FLOPS' \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", + "For `simple` missions, aviary currently models FLOPS' \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", "\n", "Next is the line" ] @@ -295,7 +295,7 @@ "id": "f9f50477", "metadata": {}, "source": [ - "which adds a sequence of core mission phases. In addition, if `mission_method` is `2dof` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the TAS at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase (`_add_groundroll_eq_constraint(phase)`). If `mission_method` is `height_energy`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is `solved`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", + "which adds a sequence of core mission phases. In addition, if `mission_method` is `2dof` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the TAS at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase (`_add_groundroll_eq_constraint(phase)`). If `mission_method` is `simple`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is `solved`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", "\n", "It follows by adding post-mission subsystems:" ] @@ -315,7 +315,7 @@ "id": "0c8038df", "metadata": {}, "source": [ - "Similar to pre-mission, it adds a landing phase if `include_landing` key of `post_mission` has value of `True`. If user chooses to define a `post_mission`, it will override the default. For `2dof` missions, landing is defined in [mission/gasp_based/phases/landing_group.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/phases/landing_group.py). For `height_energy` mission, landing means a [simplified landing](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_landing.py). Note that the `solved` method currently doesn't have any post mission systems.\n", + "Similar to pre-mission, it adds a landing phase if `include_landing` key of `post_mission` has value of `True`. If user chooses to define a `post_mission`, it will override the default. For `2dof` missions, landing is defined in [mission/gasp_based/phases/landing_group.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/phases/landing_group.py). For `simple` mission, landing means a [simplified landing](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_landing.py). Note that the `solved` method currently doesn't have any post mission systems.\n", "\n", "The next line is" ] @@ -337,7 +337,7 @@ "source": [ "This is important for allowing each phase of flight to pass to the next without discontinuities in the parameters. Consider Dymos' [Aircraft Balanced Field Length Calculation](https://openmdao.github.io/dymos/examples/balanced_field/balanced_field.html) example. In that example, we see separate nonlinear boundary constraints, nonlinear path constraints, and phase continuity constraints between phases. We don't want to go deeper in this function call, but just point out that each individual link can be set via dymos function `link_phases`. See [dymos API](https://openmdao.github.io/dymos/api/trajectory_api.html) for more details.\n", "\n", - "The code blocks in this function (namely, `link_phases()`) are for `2DOF`, `height_energy`, and `solved` missions. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", + "The code blocks in this function (namely, `link_phases()`) are for `2DOF`, `simple`, and `solved` missions. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", "\n", "Now, our aircraft and the mission are fully defined. We are ready to define an optimization problem. This is achieved by adding an optimization driver, adding design variables, and an objective. \n", "\n", @@ -513,7 +513,7 @@ "id": "57986647", "metadata": {}, "source": [ - "For `height_energy` and `2DOF` missions, this method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `default_flops_phases.py` and `default_gasp_phases.py`). For `solved` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3.ipynb) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", + "For `simple` and `2DOF` missions, this method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `default_flops_phases.py` and `default_gasp_phases.py`). For `solved` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3.ipynb) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", "\n", "The last line is to run the problem we just set up:" ] @@ -900,11 +900,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", -<<<<<<< HEAD - "version": "3.8.17" -======= "version": "3.10.8" ->>>>>>> 2113a7d9123975bb9ffc0a754f7028b99da3f8d4 } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 9a20fd22f..ca898b0e2 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -32,7 +32,7 @@ "import aviary.api as av\n", "\n", "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " av.default_height_energy_phase_info,\n", + " av.default_simple_phase_info,\n", " max_iter=0, optimizer=\"SLSQP\", make_plots=False)" ] }, diff --git a/aviary/docs/user_guide/features/overriding.ipynb b/aviary/docs/user_guide/features/overriding.ipynb index e7f81401d..1b0109ff7 100644 --- a/aviary/docs/user_guide/features/overriding.ipynb +++ b/aviary/docs/user_guide/features/overriding.ipynb @@ -117,7 +117,7 @@ " return wing_group\n", "\n", "\n", - "from aviary.api import default_height_energy_phase_info as phase_info \n", + "from aviary.api import default_simple_phase_info as phase_info \n", "phase_info['pre_mission']['external_subsystems'] = [HTailWeightBuilder(name=\"tail_external\")]\n" ] }, diff --git a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py index 1cae165e9..37fd5936a 100644 --- a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py +++ b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py @@ -4,7 +4,7 @@ from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder from aviary.examples.external_subsystems.battery.battery_variables import Aircraft -from aviary.api import default_height_energy_phase_info as phase_info +from aviary.api import default_simple_phase_info as phase_info battery_builder = BatteryBuilder(include_constraints=False) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 5781675b4..1c2084bc6 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -66,7 +66,6 @@ FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM SIMPLE = EquationsOfMotion.SIMPLE SOLVED = EquationsOfMotion.SOLVED @@ -207,8 +206,6 @@ def load_inputs(self, input_filename, phase_info=None, engine_builder=None): else: if self.mission_method is TWO_DEGREES_OF_FREEDOM: from aviary.interface.default_phase_info.two_dof import phase_info - elif self.mission_method is HEIGHT_ENERGY: - from aviary.interface.default_phase_info.height_energy import phase_info elif self.mission_method is SIMPLE: from aviary.interface.default_phase_info.simple import phase_info elif self.mission_method is SOLVED: @@ -695,7 +692,7 @@ def _add_groundroll_eq_constraint(self, phase): promotes_inputs=["t_init_gear", "t_init_flaps"], ) - def _get_height_energy_phase(self, phase_name, phase_idx): + def _get_simple_phase(self, phase_name, phase_idx): base_phase_options = self.phase_info[phase_name] fix_duration = base_phase_options['user_options']['fix_duration'] @@ -1057,7 +1054,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): elif self.mission_method is SIMPLE: for phase_idx, phase_name in enumerate(phases): phase = traj.add_phase( - phase_name, self._get_height_energy_phase(phase_name, phase_idx)) + phase_name, self._get_simple_phase(phase_name, phase_idx)) add_subsystem_timeseries_outputs(phase, phase_name) # loop through phase_info and external subsystems diff --git a/aviary/interface/test/test_basic_report.py b/aviary/interface/test/test_basic_report.py index 01b166d9f..02d2ddc25 100644 --- a/aviary/interface/test/test_basic_report.py +++ b/aviary/interface/test/test_basic_report.py @@ -5,7 +5,7 @@ from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.height_energy import phase_info +from aviary.interface.default_phase_info.simple import phase_info from aviary.interface.methods_for_level1 import run_aviary from openmdao.utils.testing_utils import use_tempdirs diff --git a/aviary/interface/test/test_check_phase_info.py b/aviary/interface/test/test_check_phase_info.py index 1c0cf7fde..593d80cb5 100644 --- a/aviary/interface/test/test_check_phase_info.py +++ b/aviary/interface/test/test_check_phase_info.py @@ -2,25 +2,25 @@ import copy from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_flops +from aviary.interface.default_phase_info.simple import phase_info as phase_info_flops from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_gasp from aviary.variable_info.enums import EquationsOfMotion -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY +SIMPLE = EquationsOfMotion.SIMPLE TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM class TestCheckInputs(unittest.TestCase): - def test_correct_input_flops(self): + def test_correct_input_simple(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_flops, mission_method=HEIGHT_ENERGY)) + self.assertTrue(check_phase_info(phase_info_flops, mission_method=SIMPLE)) def test_incorrect_tuple(self): # Let's replace a tuple with a float in the 'climb' phase incorrect_tuple_phase_info = copy.deepcopy(phase_info_flops) incorrect_tuple_phase_info['climb']['user_options']['initial_altitude'] = 10.668e3 with self.assertRaises(ValueError): - check_phase_info(incorrect_tuple_phase_info, mission_method=HEIGHT_ENERGY) + check_phase_info(incorrect_tuple_phase_info, mission_method=SIMPLE) def test_incorrect_unit(self): # Let's replace a valid unit with an invalid one in the 'climb' phase @@ -29,7 +29,7 @@ def test_incorrect_unit(self): 10.668e3, 'invalid_unit') with self.assertRaisesRegex(ValueError, "Key initial_altitude in phase climb has an invalid unit invalid_unit."): - check_phase_info(incorrect_unit_phase_info, mission_method=HEIGHT_ENERGY) + check_phase_info(incorrect_unit_phase_info, mission_method=SIMPLE) def test_correct_input_gasp(self): # This should pass without any issue as it's the same valid dict as before diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index 18cf60784..ffefec9ae 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -7,8 +7,8 @@ from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp -from aviary.interface.default_phase_info.gasp import phase_info_parameterization as phase_info_parameterization_gasp +from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp +from aviary.interface.default_phase_info.two_dof import phase_info_parameterization as phase_info_parameterization_gasp from aviary.interface.methods_for_level2 import AviaryProblem from aviary.mission.flops_based.phases.phase_builder_base import \ diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 928f6217d..0b6e3e2cf 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -6,7 +6,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.interface.default_phase_info.simple import phase_info as ph_in_flops -from aviary.interface.default_phase_info.gasp import phase_info as ph_in_gasp +from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp from aviary.variable_info.variables import Aircraft, Mission diff --git a/aviary/interface/utils/check_phase_info.py b/aviary/interface/utils/check_phase_info.py index cc40add8b..ecd21875c 100644 --- a/aviary/interface/utils/check_phase_info.py +++ b/aviary/interface/utils/check_phase_info.py @@ -1,7 +1,6 @@ from openmdao.utils.units import valid_units from aviary.variable_info.enums import SpeedType, EquationsOfMotion -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM SIMPLE = EquationsOfMotion.SIMPLE SOLVED = EquationsOfMotion.SOLVED @@ -17,48 +16,25 @@ def check_phase_info(phase_info, mission_method): # Common key-values for climb, cruise, and descent common_entries = { - 'initial_ref': tuple, - 'initial_bounds': tuple, - 'duration_ref': tuple, - 'duration_bounds': tuple, - } - - # Phase-specific entries - climb_specific = { - 'input_initial': bool, - 'no_descent': bool, - 'initial_mach': float, - 'initial_altitude': tuple, - 'final_altitude': tuple, - 'final_mach': float, - 'fix_range': bool, - 'fix_initial_time': bool, - } - - cruise_specific = { - 'min_mach': float, - 'max_mach': float, - 'required_available_climb_rate': tuple, - 'mass_f_cruise': tuple, - 'range_f_cruise': tuple, - 'fix_final': bool, - } - - descent_specific = { + 'optimize_mach': bool, + 'optimize_altitude': bool, + 'solve_for_range': bool, + 'initial_mach': tuple, + 'final_mach': tuple, + 'mach_bounds': tuple, 'initial_altitude': tuple, 'final_altitude': tuple, - 'initial_mach': float, - 'final_mach': float, - 'no_climb': bool, - 'fix_range': bool, + 'altitude_bounds': tuple, + 'throttle_enforcement': str, + 'constrain_final': bool, + 'fix_duration': bool, + 'initial_bounds': tuple, + 'duration_bounds': tuple, } # Combine common and phase-specific entries - phase_keys_flops = { + phase_keys_simple = { 'pre_mission': {'include_takeoff': bool, 'optimize_mass': bool}, - 'climb': {**common_entries, **climb_specific}, - 'cruise': {**common_entries, **cruise_specific}, - 'descent': {**common_entries, **descent_specific}, 'post_mission': {'include_landing': bool} } @@ -94,7 +70,7 @@ def check_phase_info(phase_info, mission_method): 'alt_ref': tuple, } common_descent = { - 'input_initial': bool, + 'input_initial': (bool, dict), 'EAS_limit': tuple, 'mach_cruise': float, 'input_speed_type': SpeedType, @@ -209,13 +185,7 @@ def check_phase_info(phase_info, mission_method): } phase_keys = {} - if mission_method is HEIGHT_ENERGY: - for phase in phase_info: - if phase != 'pre_mission' and phase != 'post_mission': - phase_keys[phase] = {**common_keys, **phase_keys_flops[phase]} - else: - phase_keys[phase] = phase_keys_flops[phase] - elif mission_method is TWO_DEGREES_OF_FREEDOM: + if mission_method is TWO_DEGREES_OF_FREEDOM: for phase in phase_info: if phase != 'pre_mission' and phase != 'post_mission' and phase != 'cruise': phase_keys[phase] = {**common_keys, **phase_keys_gasp[phase]} @@ -224,7 +194,11 @@ def check_phase_info(phase_info, mission_method): elif mission_method is SOLVED: return elif mission_method is SIMPLE: - return + for phase in phase_info: + if phase != 'pre_mission' and phase != 'post_mission': + phase_keys[phase] = {**common_keys, **common_entries} + else: + phase_keys[phase] = phase_keys_simple[phase] else: possible_values = ["'"+e.value+"'" for e in EquationsOfMotion] possible_values[-1] = "or " + possible_values[-1] diff --git a/aviary/mission/flops_based/ode/test/test_landing_ode.py b/aviary/mission/flops_based/ode/test/test_landing_ode.py index 16e34c0f2..e3faf4747 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_ode.py +++ b/aviary/mission/flops_based/ode/test/test_landing_ode.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.height_energy import default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_mission_subsystems from aviary.mission.flops_based.ode.landing_ode import FlareODE from aviary.models.N3CC.N3CC_data import ( detailed_landing_flare, inputs, landing_subsystem_options) diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py index fd39339e5..ebcf3a092 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py @@ -3,7 +3,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.height_energy import default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_mission_subsystems from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE from aviary.models.N3CC.N3CC_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, takeoff_subsystem_options, inputs) diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py deleted file mode 100644 index 002760085..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py +++ /dev/null @@ -1,260 +0,0 @@ -''' -NOTES: -Includes: -Climb -Computed Aero -Large Single Aisle 1 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark currently hits iteration limit - problem only converges when velocity ref & ref0 in energyphase is changed to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_climb = 0*_units.foot # m - alt_f_climb = 35000.0*_units.foot # m - mass_i_climb = 180623*_units.lb # kg - mass_f_climb = 176765*_units.lb # kg - v_i_climb = 198.44*_units.knot # m/s - v_f_climb = 455.49*_units.knot # m/s - mach_i_climb = 0.3 - mach_f_climb = 0.79 - 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 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - - climb_options = Climb( - 'test_climb', - initial_altitude=alt_i_climb, - final_altitude=alt_f_climb, - no_descent=False, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - initial_mach=mach_i_climb, - final_mach=mach_f_climb, - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=6, order=3, compressed=False) - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - climb = climb_options.build_phase(MissionODE, transcription) - - traj.add_phase('climb', climb) - - climb.add_objective('time', loc='final', ref=1e3) - # climb.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - climb.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_climb*2), duration_ref=t_duration_climb) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - 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.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='climb_max.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_climb_large_single_aisle_1 currently broken') -class ClimbPhaseTestCase(unittest.TestCase): - def bench_test_climb_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') - - expected_times_s = [ - [120.], [194.07139282], [296.27479672], [328.62182461], - [328.62182461], [402.69321743], [504.89662133], [537.24364922], - [537.24364922], [611.31504204], [713.51844594], [745.86547383], - [745.86547383], [819.93686665], [922.14027055], [954.48729844], - [954.48729844], [1028.55869126], [1130.76209516], [1163.10912305], - [1163.10912305], [1237.18051587], [1339.38391977], [1371.73094766]] - expected_altitudes_m = [ - [0.], [682.4957554], [2476.9915886], [3148.23528025], - [3148.23528025], [4477.82410739], [5953.00480303], [6351.40548265], - [6351.40548265], [7144.57711953], [8022.01978103], [8258.96785373], - [8258.96785373], [8740.86702454], [9286.23944667], [9434.70712276], - [9434.70712276], [9740.61479402], [10091.17192047], [10187.1054111], - [10187.1054111], [10383.06677812], [10606.85289388], [10668.]] - expected_masses_kg = [ - [81929.21464651], [81734.3159625], [81482.28032417], [81409.67409534], - [81409.67409534], [81261.52268984], [81089.79910736], [81041.35712905], - [81041.35712905], [80939.57475401], [80815.51316484], [80779.24867668], - [80779.24867668], [80700.64682801], [80600.66210256], [80570.67210015], - [80570.67210015], [80504.18318007], [80416.95604372], [80390.28585848], - [80390.28585848], [80330.69704984], [80251.40682218], [80226.91650584]] - expected_ranges_m = [ - [0.], [11134.82482615], [33305.36225275], [40552.08037408], - [40552.08037408], [57694.75967874], [81567.92031544], [89129.68416299], - [89129.68416299], [106463.26453256], [130389.14274257], [137962.93786], - [137962.93786], [155308.03326502], [179243.7729914], [186819.85564691], - [186819.85564691], [204168.96379317], [228108.3526042], [235685.29047396], - [235685.29047396], [253035.99320713], [276976.90557005], [284554.20584747]] - expected_velocities_ms = [ - [102.08605905], [190.58935413], [228.38194188], [230.69562115], - [230.69562115], [233.30227629], [234.24467254], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132]] - expected_thrusts_N = [ - [218457.50162414], [171332.33326933], [141120.77188326], [131766.72736631], - [131766.72736631], [112828.24508393], [94178.64187388], [89529.25529378], - [89529.25529378], [80383.22196309], [71047.86501907], [68765.74648505], - [68765.74648505], [64112.90745184], [59068.27795964], [57877.0412593], - [57877.0412593], [55418.69760271], [52595.0053262], [51821.03735429], - [51821.03735429], [50238.39534494], [48428.26539664], [47933.1465328]] - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py deleted file mode 100644 index f03466f7f..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py +++ /dev/null @@ -1,366 +0,0 @@ -''' -NOTES: -Includes: -Climb -Computed Aero -Large Single Aisle 2 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs -from packaging import version -from aviary.variable_info.variables_in import VariablesIn - -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.flops_based.phases.climb_phase import Climb -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 40 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_climb = 35 * _units.foot # m - alt_f_climb = 35000.0 * _units.foot # m - mass_i_climb = 169172 * _units.lb # kg - mass_f_climb = 164160 * _units.lb # kg - v_i_climb = 198.44 * _units.knot # m/s - v_f_climb = 452.61 * _units.knot # m/s - mach_i_climb = 0.3 - mach_f_climb = 0.775 - range_i_climb = 0 * _units.nautical_mile # m - range_f_climb = 124 * _units.nautical_mile # m - t_i_climb = 0 - t_f_climb = 20.14 * _units.minute # sec - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - transcription = dm.Radau(num_segments=6, order=3, compressed=False) - climb_options = Climb( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (True, 'unitless'), - 'fix_range': (False, 'unitless'), - 'input_initial': (False, 'unitless'), - }), - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - core_subsystems=[aero, prop], - transcription=transcription, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - climb = climb_options.build_phase(aviary_options=aviary_inputs) - - traj.add_phase('climb', climb) - - climb.timeseries_options['use_prefix'] = True - - climb.add_objective('time', loc='final', ref=t_f_climb) - - climb.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(t_f_climb * 0.5, t_f_climb * 2), duration_ref=t_f_climb) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs, phases=['climb']) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - prob.set_val('traj.climb.t_initial', t_i_climb, units='s') - prob.set_val('traj.climb.t_duration', t_f_climb, units='s') - - prob.set_val('traj.climb.states:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val('traj.climb.states:velocity', climb.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi - - prob.set_val('traj.climb.controls:velocity_rate', - climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), - units='m/s**2') - prob.set_val('traj.climb.controls:throttle', - climb.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='climb_large_single_aisle_2.db') - prob.record("final") - prob.cleanup() - - return prob - - -@use_tempdirs -class ClimbPhaseTestCase(unittest.TestCase): - def bench_test_climb_large_single_aisle_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') - velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') - - expected_times_s = [[0.], - [47.24020828], - [112.42205385], - [133.05188512], - [133.05188512], - [180.2920934], - [245.47393897], - [266.10377023], - [266.10377023], - [313.34397852], - [378.52582409], - [399.15565535], - [399.15565535], - [446.39586363], - [511.5777092], - [532.20754047], - [532.20754047], - [579.44774875], - [644.62959432], - [665.25942558], - [665.25942558], - [712.49963387], - [777.68147944], - [798.3113107]] - expected_altitudes_m = [[1.06680000e+01], - [1.64717443e+02], - [1.21077165e+03], - [1.65467452e+03], - [1.65467452e+03], - [2.63158548e+03], - [3.89195114e+03], - [4.26784031e+03], - [4.26784031e+03], - [5.08501440e+03], - [6.12319963e+03], - [6.43302565e+03], - [6.43302565e+03], - [7.11281142e+03], - [7.98114971e+03], - [8.23811059e+03], - [8.23811059e+03], - [8.78587957e+03], - [9.45185516e+03], - [9.64164118e+03], - [9.64164118e+03], - [1.00442465e+04], - [1.05301137e+04], - [1.06680000e+04]] - expected_masses_kg = [[76735.12841764], - [76606.6291851], - [76423.55875817], - [76369.21098493], - [76369.21098493], - [76249.27821197], - [76096.52180626], - [76051.03001076], - [76051.03001076], - [75951.61028918], - [75824.47689696], - [75786.47518169], - [75786.47518169], - [75703.26334226], - [75596.63038983], - [75564.65308165], - [75564.65308165], - [75493.66861479], - [75400.85356264], - [75372.67886333], - [75372.67886333], - [75310.24572772], - [75228.35359487], - [75203.34794937]] - expected_ranges_m = [[0.], - [6656.35106052], - [19411.34037117], - [23606.44276229], - [23606.44276229], - [33597.9222712], - [47757.51502804], - [52308.8364503], - [52308.8364503], - [62843.02681099], - [77579.88662088], - [82280.86896803], - [82280.86896803], - [93082.94529627], - [108032.30577631], - [112765.20449737], - [112765.20449737], - [123607.6358803], - [138572.23956024], - [143309.37828794], - [143309.37828794], - [154158.17439593], - [169129.72020176], - [173868.65393385]] - expected_velocities_ms = [[102.08635556], - [173.4078533], - [206.56979636], - [209.71234319], - [209.71234319], - [215.12096513], - [220.69657248], - [222.14669648], - [222.14669648], - [225.06833215], - [228.02045426], - [228.64470582], - [228.64470582], - [229.49739505], - [229.80567178], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554], - [229.81001554]] - expected_thrusts_N = [[183100.97258682], - [163996.9938714], - [144753.36497874], - [140427.87965941], - [140427.87965941], - [131136.19372391], - [119398.47487166], - [115939.50935006], - [115939.50935006], - [108449.59352749], - [99269.67371293], - [96533.89180294], - [96533.89180294], - [90902.4892038], - [84031.52375462], - [81889.41102505], - [81889.41102505], - [77138.3352612], - [71330.53467419], - [69720.96587699], - [69720.96587699], - [66405.48655242], - [62587.8225939], - [61541.80174696]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - test = ClimbPhaseTestCase() - test.bench_test_climb_large_single_aisle_2() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py deleted file mode 100644 index c88f5dd8e..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py +++ /dev/null @@ -1,316 +0,0 @@ -############################################################### -# NOTES: -# Includes: -# Cruise -# Computed Aero -# Large Single Aisle 1 data -############################################################### -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - - -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 30 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-5 - driver.opt_settings["iSumm"] = 6 - driver.opt_settings["Verify level"] = 3 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_min_cruise = 30000*_units.foot # m - alt_max_cruise = 36000*_units.foot # m - alt_i_cruise = alt_min_cruise - alt_f_cruise = 36000*_units.foot # m - mass_i_cruise = 176765*_units.lb # kg - mass_f_cruise = 143521*_units.lb # kg - velocity_i_cruise = 465.55*_units.knot # m/s - velocity_f_cruise = 465.55*_units.knot # m/s - mach_i_cruise = 0.79 - mach_f_cruise = 0.79 - mach_min_cruise = 0.78999 - mach_max_cruise = 0.79001 - 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 - - prob.set_solver_print(level=0) - - transcription = dm.Radau(num_segments=8, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - # engine_models = aviary_inputs['engine_models'] - - cruise_options = Cruise( - 'test_cruise', - min_altitude=alt_min_cruise, # m - max_altitude=alt_max_cruise, # m - # note, Mach = 0.0 causes an error in aero, perhaps in other code - min_mach=mach_min_cruise, - max_mach=mach_max_cruise, - required_available_climb_rate=300*_units.foot/_units.minute, # ft/min to m/s - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - # engine_models=engine_models, - no_descent=True, - velocity_f_cruise=velocity_f_cruise, - mass_f_cruise=mass_f_cruise, - range_f_cruise=range_f_cruise, - - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(MissionODE, transcription) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-mass_f_cruise) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - # IVC = prob.model.add_subsystem('IVC', om.IndepVarComp(), promotes_outputs=['*']) - # IVC.add_output('alt_i', val=32000, units='ft') - prob.model.add_constraint( - 'traj.cruise.states:altitude', - indices=[0], equals=alt_min_cruise, units='m', ref=alt_max_cruise) - - # Alternative implmentation of above - # holds the first node in altitude constant - # cruise.set_state_options(Dynamic.Mission.ALTITUDE, fix_initial=True) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[ - alt_i_cruise, (alt_f_cruise + alt_i_cruise) / 2]), units='m') - prob.set_val( - 'traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[ - velocity_i_cruise, velocity_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_climb_max.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@unittest.skip('benchmark cruise climb currently broken') -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_climb_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') - - expected_times_s = [ - [1572.0], [2654.1067424751645], [4147.193185981006], - [4619.749940380141], [4619.749940380141], [5701.856682855307], - [7194.943126361148], [7667.499880760283], [7667.499880760283], - [8749.606623235448], [10242.693066741289], [10715.249821140425], - [10715.249821140425], [11797.356563615589], [13290.44300712143], - [13762.999761520567], [13762.999761520567], [14845.106503995732], - [16338.192947501573], [16810.749701900706], [16810.749701900706], - [17892.856444375873], [19385.942887881713], [19858.49964228085], - [19858.49964228085], [20940.606384756014], [22433.692828261857], - [22906.249582660992], [22906.249582660992], [23988.356325136156], - [25481.442768642], [25953.999523041133]] - expected_altitudes_m = [ - [9143.999999999998], [9708.208298692567], [10127.822388940609], - [10214.217379879337], [10214.217379879337], [10369.633608560018], - [10522.493213427248], [10561.102831034279], [10561.102831034279], - [10628.89921313077], [10700.84689461149], [10720.94842484514], - [10720.94842484514], [10759.7268947497], [10811.373374694173], - [10828.933975559758], [10828.933975559758], [10866.85055516194], - [10912.976573928156], [10924.787065056735], [10924.787065056735], - [10948.28098891448], [10967.163582971652], [10969.578328436102], - [10969.578328436102], [10971.188528219269], [10971.305320817934], - [10972.40306787028], [10972.40306787028], [10972.800000000001], - [10972.682828875833], [10972.8]] - expected_masses_kg = [ - [80179.25528304999], [79388.27899969438], [78357.5492916318], - [78038.12469387538], [78038.12469387538], [77318.48636094612], - [76344.12665022336], [76039.40895912607], [76039.40895912607], - [75347.90752400359], [74405.46275374181], [74109.60273338258], - [74109.60273338258], [73436.39272100825], [72516.3728326044], - [72227.22710472894], [72227.22710472894], [71569.02331279762], - [70669.56072490575], [70386.99122373879], [70386.99122373879], - [69743.47490624938], [68863.48019743375], [68586.78382987661], - [68586.78382987661], [67956.17424058718], [67092.43136900471], - [66820.49389265837], [66820.49389265837], [66200.47169407656], - [65350.50275054499], [65082.74154168183]] - expected_ranges_m = [ - [296875.60000000003], [554932.6549301515], [908399.8849826958], - [1019938.0213070473], [1019938.0213070473], [1274830.9442516388], - [1625714.5770829467], [1736624.0715069345], [1736624.0715069345], - [1990386.259724133], [2340154.5629672543], [2450786.080862452], - [2450786.080862452], [2704005.1890667905], [3053155.1477462808], - [3163604.8984363866], [3163604.8984363866], [3416419.8294669725], - [3765031.23567717], [3875315.9608939146], [3875315.9608939146], - [4127790.908533788], [4476045.826943081], [4586252.017090351], - [4586252.017090351], [4838601.188787049], [5186784.687764149], - [5296985.604312349], [5296985.604312349], [5549329.03066934], - [5897505.925045533], [6007702.8]] - expected_velocities_ms = [ - [239.49901683172416], [237.57721365239863], [236.1272332817375], - [235.83480578606836], [235.83480578606836], [235.29228140558052], - [234.76087668521515], [234.63268475430843], [234.63268475430843], - [234.3910317141664], [234.14254607637204], [234.07650600638797], - [234.07650600638797], [233.93612811601653], [233.75522209810927], - [233.69840302886462], [233.69840302886462], [233.56754384846963], - [233.4030426703855], [233.35949436934354], [233.35949436934354], - [233.28100688012185], [233.21763783283092], [233.20729273195352], - [233.20729273195352], [233.19770503012535], [233.1994910278998], - [233.19937577943125], [233.19937577943125], [233.19406389286172], - [233.19249705434646], [233.197992365194]] - expected_thrusts_N = [ - [46413.113617016286], [43959.216926887144], [42322.72191477366], - [42001.69876565644], [42001.698765656445], [41407.67462380937], - [40737.526959795134], [40531.856232353945], [40531.85623235394], - [40132.12747513132], [39640.66854140172], [39484.44541552107], - [39484.44541552107], [39159.04488467944], [38737.64967064259], - [38601.13281610918], [38601.13281610918], [38291.27389642972], - [37859.254019237305], [37729.15520426054], [37729.155204260525], - [37427.990254061384], [37028.69942780689], [36907.64255965252], - [36907.64255965253], [36649.2311134786], [36319.78199219473], - [36213.12929993469], [36213.12929994349], [35988.316744926444], - [35701.59647680185], [35614.98883340026]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # Objective - - rtol = 1e-2 - - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py deleted file mode 100644 index b9925cf5b..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py +++ /dev/null @@ -1,253 +0,0 @@ -''' -NOTES: -Includes: -Cruise -Computed Aero -Large Single Aisle 1 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs -from packaging import version -from aviary.variable_info.variables_in import VariablesIn - -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import (get_flops_inputs, - get_flops_outputs) -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - 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 = 176765*_units.lb # kg - mass_f_cruise = 143521*_units.lb # kg - v_i_cruise = 455.49*_units.knot # m/s - v_f_cruise = 455.49*_units.knot # m/s - mach_i_cruise = 0.79 - mach_f_cruise = 0.79 - mach_min_cruise = 0.79 - mach_max_cruise = 0.79 - 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 - - prob.set_solver_print(level=2) - - transcription = dm.Radau(num_segments=1, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_outputs = get_flops_outputs('LargeSingleAisle1FLOPS') - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - cruise_options = Cruise( - 'test_cruise', - user_options=AviaryValues({ - 'min_altitude': (alt_min_cruise, 'm'), - 'max_altitude': (alt_max_cruise, 'm'), - 'min_mach': (mach_min_cruise, 'unitless'), - 'max_mach': (mach_max_cruise, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (True, 'unitless'), - 'fix_final': (True, 'unitless'), - }), - core_subsystems=core_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription, - ) - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.timeseries_options['use_prefix'] = True - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs, phases=['cruise']) - - prob.model.add_subsystem( - 'input_sink', - VariablesIn(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - key = Aircraft.Engine.THRUST_REVERSERS_MASS - val, units = aviary_outputs.get_item(key) - prob.model.set_input_defaults(key, val, units) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_max.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@use_tempdirs -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') - - expected_times_s = [[1572.], [10227.56555775], - [22170.47940152], [25950.37079939]] - expected_altitudes_m = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg = [[80179.25528305], [ - 74612.30190345], [67357.05992796], [65154.3328912]] - expected_ranges_m = [[296875.6], [2324510.6550793], - [5122233.1849208], [6007702.8]] - expected_velocities_ms = [[234.25795132], [ - 234.25795132], [234.25795132], [234.25795132]] - expected_thrusts_N = [[41817.82877662], [ - 39634.49609004], [36930.60549609], [36149.38784885]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py deleted file mode 100644 index 8e1cfae23..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py +++ /dev/null @@ -1,247 +0,0 @@ -''' -NOTES: -Includes: -Cruise -Computed Aero -Large Single Aisle 2 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.cruise_phase import Cruise -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.validation_cases.validation_tests import (get_flops_inputs, - get_flops_outputs) -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic - -mpl.rc('figure', max_open_warning=0) - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark currently hits iteration limit - problem only converges when velocity ref & ref0 in energyphase is changed to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 1e-5 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-6 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - 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 = 169730*_units.lb # kg - mass_f_cruise = 139810*_units.lb # kg - v_i_cruise = 452.61*_units.knot # m/s - v_f_cruise = 452.61*_units.knot # m/s - mach_i_cruise = 0.785 - mach_f_cruise = 0.785 - mach_min_cruise = 0.785 - mach_max_cruise = 0.785 - range_i_cruise = 116.6*_units.nautical_mile # m - range_f_cruise = 2558.3*_units.nautical_mile # m - t_i_cruise = 19.08*_units.minute # sec - t_f_cruise = 342.77*_units.minute # sec - t_duration_cruise = t_f_cruise - t_i_cruise # sec - - prob.set_solver_print(level=2) - - transcription = dm.Radau(num_segments=1, order=3, compressed=True) - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - aviary_outputs = get_flops_outputs('LargeSingleAisle2FLOPS') - - cruise_options = Cruise( - 'test_cruise', - min_altitude=alt_min_cruise, # m - max_altitude=alt_max_cruise, # m - # note, Mach = 0.0 causes an error in aero, perhaps in other code - min_mach=mach_min_cruise, - max_mach=mach_max_cruise, - required_available_climb_rate=300*_units.foot/_units.minute, # ft/min to m/s - fix_initial=True, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - cruise = cruise_options.build_phase(MissionODE, transcription) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - traj.add_phase('cruise', cruise) - - cruise.set_time_options( - fix_initial=True, fix_duration=False, units='s', - duration_bounds=(1, t_duration_cruise*2), duration_ref=t_duration_cruise) - - cruise.add_objective(Dynamic.Mission.MASS, loc='final', ref=-1e4) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - key = Aircraft.Engine.THRUST_REVERSERS_MASS - val, units = aviary_outputs.get_item(key) - prob.model.set_input_defaults(key, val, units) - - prob.setup() - - 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.states:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val('traj.cruise.states:velocity', cruise.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi - - prob.set_val('traj.cruise.controls:velocity_rate', - cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.cruise.controls:throttle', - cruise.interp(Dynamic.Mission.THROTTLE, ys=[0.5, 0.5]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='cruise_large_single_aisle_2.db') - # TODO Simulate=True is crashing here so turned it off - - prob.cleanup() - prob.record("final") - - return prob - - -@unittest.skip('benchmark_cruise_large_single_aisle_2 currently broken') -class CruisePhaseTestCase(unittest.TestCase): - def bench_test_cruise_large_single_asile_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') - velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.cruise.timeseries.thrust_net', units='N') - - expected_times_s = [[1144.8], [8042.22760495], - [17559.26991489], [20571.38126654]] - expected_altitudes_m = [[10668.], [10668.], [10668.], [10668.]] - expected_masses_kg = [[76988.2329601], [ - 72122.85057432], [65811.40723995], [63888.48266274]] - expected_ranges_m = [[215943.2], [1821494.02176252], - [4036826.45823737], [4737971.6]] - expected_velocities_ms = [[232.77530606], [ - 232.77530606], [232.77530606], [232.77530606]] - expected_thrusts_N = [[40492.90002165], [ - 38252.99661427], [35778.79636585], [35144.49009256]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - # Changes to hardcoded tabular aero data changed this benchmark. Update benchmark - # test's expected values when aircraft-specific tabluar aero is avaliable - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py deleted file mode 100644 index c1dba6168..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py +++ /dev/null @@ -1,255 +0,0 @@ -''' -NOTES: -Includes: -Descent -Computed Aero -Large Single Aisle 1 data -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE descent profile is improved when velocity ref in EnergyPhase change to 1e3 - Implementing that velocity ref change breaks several mission benchmarks -''' -# benchmark based on Large Single Aisle 1 (fixed cruise alt) FLOPS model - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 5e-3 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i_descent = 35000*_units.foot - alt_f_descent = 0*_units.foot - v_i_descent = 455.49*_units.knot - v_f_descent = 198.44*_units.knot - mach_i_descent = 0.79 - mach_f_descent = 0.3 - mass_i_descent = 143521*_units.pound - mass_f_descent = 143035*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_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 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') - - descent_options = Descent( - 'test_descent', - final_altitude=alt_f_descent, - initial_altitude=alt_i_descent, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - final_mach=mach_f_descent, - initial_mach=mach_i_descent, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=5, order=3, compressed=True) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - descent = descent_options.build_phase(MissionODE, transcription) - - # descent.add_objective(Dynamic.Mission.MASS, ref=-1e4, loc='final') - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') - - traj.add_phase('descent', descent) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - # set initial conditions - 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.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='descent_max.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_descent_large_single_aisle_1 currently broken') -class DescentPhaseTestCase(unittest.TestCase): - def bench_test_descent_large_single_aisle_1(self): - - prob = run_trajectory() - - times = prob.get_val('traj.descent.timeseries.time', units='s') - altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') - - expected_times_s = [ - [25942.8], [26067.38110599], [26239.2776049], [26293.68225907], - [26293.68225907], [26418.26336507], [26590.15986397], [26644.56451815], - [26644.56451815], [26769.14562414], [26941.04212305], [26995.44677722], - [26995.44677722], [27120.02788321], [27291.92438212], [27346.3290363], - [27346.3290363], [27470.91014229], [27642.80664119], [27697.21129537]] - expected_altitudes_m = [ - [10668.], [9630.58727675], [8607.44716937], [8325.35146852], - [8325.35146852], [7618.26503578], [6519.12597312], [6144.16296733], - [6144.16296733], [5222.63590813], [3906.74184382], [3501.58245681], - [3501.58245681], [2693.56449806], [1613.14062128], [1227.34540813], - [1227.34540813], [472.05630168], [0.], [0.]] - expected_masses_kg = [ - [65100.03053477], [65068.4860871], [65009.01063053], [64988.47429787], - [64988.47429787], [64942.20142996], [64875.19680192], [64851.91888669], - [64851.91888669], [64793.85853886], [64706.58329093], [64678.30905669], - [64678.30905669], [64614.11135757], [64531.47572247], [64507.94243863], - [64507.94243863], [64464.03072407], [64420.28475648], [64408.7201039]] - expected_ranges_m = [ - [6007702.8], [6036868.3987895], [6077125.1955833], - [6089867.31136598], [6089867.31136598], [6119045.21397484], - [6159302.44709504], [6172042.94318126], [6172042.94318126], - [6201214.75820313], [6241466.48424821], [6254207.73380962], - [6254207.73380962], [6283402.65691348], [6322851.72600445], - [6334884.03220066], [6334884.03220066], [6360443.88994895], - [6388386.24507732], [6394712.53233535]] - expected_velocities_ms = [ - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [234.25795132], [234.25795132], [234.25795132], - [234.25795132], [233.47298378], [223.67831268], [216.71997882], - [216.71997882], [190.9857791], [129.0266439], [102.08605905]] - expected_thrusts_N = [ - [9516.07730964], [18867.54655988], [26134.27560127], [26569.54809341], - [26569.54809341], [26513.67959312], [27279.65638053], [27558.344662], - [27558.344662], [29558.29975054], [37141.0454636], [40960.56830135], - [40960.56830135], [46197.31464087], [36817.32495137], [29341.51748247], - [29341.51748247], [14369.16584473], [0.], [2.27381718e-11]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py deleted file mode 100644 index e6378c4a2..000000000 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py +++ /dev/null @@ -1,256 +0,0 @@ -''' -NOTES: -Includes: -Descent -Computed Aero -Large Single Aisle 2 data -CURRENTLY REMOVED FROM BENCHMARK TEST SUITE -''' - -import unittest - -import dymos as dm -# Suppress the annoying warnings from matplotlib when running dymos. -import matplotlib as mpl -import numpy as np -import openmdao.api as om -import scipy.constants as _units - -from dymos.utils.testing_utils import assert_timeseries_near_equal -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.descent_phase import Descent -from aviary.interface.default_phase_info.height_energy import prop, aero, geom -from aviary.subsystems.premission import CorePreMission -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic - -mpl.rc('figure', max_open_warning=0) - - -try: - import pyoptsparse - -except ImportError: - pyoptsparse = None - - -''' -NOTE benchmark only reaches 0-3 after 50 iterations with bad plots - problem easily converges with 0-1 when velocity ref & ref0 in energyphase is changed - to 1e3. - Changing velocity ref breaks some full-mission benchmarks, so is currently not - implemented -''' - - -def run_trajectory(): - prob = om.Problem(model=om.Group()) - - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 50 - driver.opt_settings["Major optimality tolerance"] = 5e-3 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 - - # TODO enable coloring once issue has been resolved: - # https://github.com/OpenMDAO/OpenMDAO/issues/2507 - # driver.declare_coloring() - - ########################## - # Problem Settings # - ########################## - alt_i = 35000*_units.foot - alt_f = 35*_units.foot - v_i = 452.61*_units.knot - v_f = 198.44*_units.knot - mach_i = 0.785 - mach_f = 0.3 - mass_i = 140515*_units.pound - mass_f = 140002*_units.pound - range_i = 2830.8*_units.nautical_mile - range_f = 2960.0*_units.nautical_mile - t_i_descent = 0.0 - t_f_descent = 2000.0 - - ########################################## - # Aircraft Input Variables and Options # - ########################################## - - aviary_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') - - descent_options = Descent( - 'test_descent', - final_altitude=alt_f, - initial_altitude=alt_i, - # note, Mach = 0.0 causes an error in aero, perhaps in other code - final_mach=mach_f, - initial_mach=mach_i, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - aviary_options=aviary_inputs, - ) - - # replace debug_no_mass flag with list of subsystem builders without mass - core_subsystems = [prop, geom, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'core_premission', - CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - transcription = dm.Radau(num_segments=5, order=3, compressed=True) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - descent = descent_options.build_phase(MissionODE, transcription) - - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') - traj.add_phase('descent', descent) - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs) - - # Set initial default values for all aircraft variables. - set_aviary_initial_values(prob.model, aviary_inputs) - - prob.setup() - - # set initial conditions - prob.set_val('traj.descent.t_initial', t_i_descent, units='s') - prob.set_val('traj.descent.t_duration', t_f_descent, units='s') - - prob.set_val('traj.descent.states:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i, alt_f]), units='m') - prob.set_val('traj.descent.states:velocity', descent.interp( - Dynamic.Mission.VELOCITY, ys=[v_i, v_f]), units='m/s') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i, mass_f]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i, range_f]), units='m') - - prob.set_val('traj.descent.controls:velocity_rate', - descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), - units='m/s**2') - prob.set_val('traj.descent.controls:throttle', - descent.interp(Dynamic.Mission.THROTTLE, ys=[0.0, 0.0]), - units='unitless') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=False, make_plots=False, - solution_record_file='descent_large_single_aisle_2.db') - prob.record("final") - prob.cleanup() - - return prob - - -@unittest.skip('benchmark_descent_large_single_aisle_2 currently broken') -class DescentPhaseTestCase(unittest.TestCase): - def bench_test_descent_large_single_aisle_2(self): - - prob = run_trajectory() - - times = prob.get_val('traj.descent.timeseries.time', units='s') - altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') - masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') - velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') - thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') - - expected_times_s = [ - [0.], [142.02539503], [337.99145239], [400.01403952], - [400.01403952], [542.03943455], [738.0054919], [800.02807903], - [800.02807903], [942.05347406], [1138.01953142], [1200.04211855], - [1200.04211855], [1342.06751358], [1538.03357093], [1600.05615806], - [1600.05615806], [1742.08155309], [1938.04761045], [2000.07019758]] - expected_altitudes_m = [ - [10668.], [9548.97609287], [8538.42241675], [8275.01276129], - [8275.01276129], [7601.31902636], [6519.47805911], [6141.13701298], - [6141.13701298], [5205.26802003], [3963.90368243], [3634.87695679], - [3634.87695679], [3055.62551952], [2221.91470683], [1840.14771729], - [1840.14771729], [870.95857222], [10.668], [10.668]] - expected_masses_kg = [ - [63736.53187055], [63688.55056043], [63592.93766122], [63558.62366657], - [63558.62366657], [63480.12720033], [63368.68894184], [63331.87300229], - [63331.87300229], [63243.53017169], [63103.08546544], [63051.9162013], - [63051.9162013], [62922.36463692], [62748.94842397], [62704.12656931], - [62704.12656931], [62627.76510694], [62566.74093186], [62554.55364275]] - expected_ranges_m = [ - [5242641.6], [5275682.08024547], [5321287.43849558], - [5335722.05453227], [5335722.05453227], [5368775.18998604], - [5414378.40648958], [5428810.78044196], [5428810.78044196], - [5461857.5756481], [5507456.7101919], [5521890.39254914], - [5521890.39254914], [5554951.82532665], [5599686.46586361], - [5613370.90489204], [5613370.90489204], [5642618.8601419], - [5674799.0551216], [5682083.57281856]] - expected_velocities_ms = [ - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.77530606], [232.77530606], [232.77530606], - [232.77530606], [232.05265856], [223.03560479], [216.62970611], - [216.62970611], [192.53473927], [130.45545087], [102.07377559]] - expected_thrusts_N = [ - [10348.85799036], [20322.69938272], [27901.58834456], - [28262.62341568], [28262.62341568], [28062.43245824], - [28590.47833586], [28815.02361611], [28815.02361611], - [30869.45928917], [38383.90751338], [41973.2222718], - [41973.2222718], [46287.80542225], [36032.4169276], - [28755.10323868], [28755.10323868], [13691.34754408], [0.], [0.]] - - expected_times_s = np.array(expected_times_s) - expected_altitudes_m = np.array(expected_altitudes_m) - expected_masses_kg = np.array(expected_masses_kg) - expected_ranges_m = np.array(expected_ranges_m) - expected_velocities_ms = np.array(expected_velocities_ms) - expected_thrusts_N = np.array(expected_thrusts_N) - - # NOTE rtol = 0.01 = 1% different from truth (first timeseries) - # atol = 1 = no more than +/-1 meter difference between values - atol = 1e-2 - rtol = 1e-3 - - # Objective - assert_near_equal(times[-1], expected_times_s[-1], tolerance=rtol) - - # Flight path - - assert_timeseries_near_equal( - expected_times_s, expected_masses_kg, times, masses, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_ranges_m, times, ranges, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_velocities_ms, times, velocities, - abs_tolerance=atol, rel_tolerance=rtol) - assert_timeseries_near_equal( - expected_times_s, expected_thrusts_N, times, thrusts, - abs_tolerance=atol, rel_tolerance=rtol) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py index fdd3c0384..598e1ba8b 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py @@ -5,7 +5,7 @@ from aviary.mission.gasp_based.polynomial_fit import PolynomialFit from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.interface.default_phase_info.height_energy import default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_mission_subsystems def run_ascent(make_plots=False): diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index a163553ea..13219ce56 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -26,7 +26,7 @@ from aviary.variable_info.variables import Mission from aviary.variable_info.variables import Settings from aviary.variable_info.enums import EquationsOfMotion, LegacyCode -from aviary.interface.default_phase_info.height_energy import default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_mission_subsystems Dynamic = _Dynamic.Mission @@ -315,7 +315,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv index 81ac1ee35..2ceb7088d 100644 --- a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv +++ b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv @@ -169,7 +169,7 @@ mission:takeoff:rolling_friction_coefficient,0.0175,unitless mission:takeoff:spoiler_drag_coefficient,0.085,unitless mission:takeoff:spoiler_lift_coefficient,-0.81,unitless mission:takeoff:thrust_incidence,0,deg -settings:equations_of_motion,height_energy +settings:equations_of_motion,simple settings:mass_method,FLOPS # Unconverted Values diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py index feeca95a1..8b3f48616 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py index 37ef21ff0..3f36a12f2 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py index 667b0d72a..2c1328bc7 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py @@ -262,7 +262,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py index ca02d5832..f8fe5041a 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index 2d4ea4703..abdddb634 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -155,5 +155,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,height_energy +settings:equations_of_motion,simple settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 5c0d0b8a0..b0c9ace8d 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -269,5 +269,5 @@ mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,height_energy +settings:equations_of_motion,simple settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py index 3788620b8..c6a26a221 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.height_energy import aero, prop, geom +from aviary.interface.default_phase_info.simple import aero, prop, geom from aviary.utils.aviary_values import get_items from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index edd31adfa..a09db92f1 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -88,7 +88,8 @@ def test_solved_aero_pass_polar(self): prob = AviaryProblem() - prob.load_inputs(csv_path, ph_in) + prob.load_inputs( + "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv", ph_in) prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, np.zeros_like(CL), units='unitless') diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py index 897caf9a5..216f17fc5 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py @@ -8,7 +8,7 @@ from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.height_energy import aero, prop, geom +from aviary.interface.default_phase_info.simple import aero, prop, geom from aviary.utils.aviary_values import AviaryValues, get_items from aviary.utils.functions import set_aviary_initial_values from aviary.utils.named_values import NamedValues diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 87a2251e1..07ebbf478 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -13,7 +13,7 @@ from aviary.variable_info.variables import Aircraft, Mission from aviary.variable_info.variables_in import VariablesIn from aviary.utils.functions import set_aviary_initial_values -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index 3273f0ee5..82aad72c3 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -108,7 +108,7 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, for var, (val, units) in sorted(vehicle_data['input_values']): writer.writerow([var] + val + [units]) if legacy_code is FLOPS: - EOM = 'height_energy' + EOM = 'simple' mass = 'FLOPS' if legacy_code is GASP: EOM = '2DOF' diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 0b1dd82f6..5ddf69121 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -5,7 +5,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info -from aviary.interface.default_phase_info.simple import phase_info as height_energy_phase_info +from aviary.interface.default_phase_info.simple import phase_info as simple_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info from aviary.variable_info.enums import EquationsOfMotion @@ -45,8 +45,8 @@ def test_gasp_zero_iters(self): class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") - def test_height_energy_zero_iters(self): - local_phase_info = deepcopy(height_energy_phase_info) + def test_simple_zero_iters(self): + local_phase_info = deepcopy(simple_phase_info) self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', local_phase_info) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index aff3bb72c..98b67bb04 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -20,7 +20,7 @@ inputs as _inputs from aviary.variable_info.variables import Dynamic as _Dynamic from aviary.variable_info.variables_in import VariablesIn -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems from aviary.subsystems.premission import CorePreMission Dynamic = _Dynamic.Mission diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 160819283..3de522d6f 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -26,7 +26,7 @@ from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload try: diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 512b710d8..99b4c3c31 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -18,7 +18,7 @@ landing_fullstop_user_options as _landing_fullstop_user_options) from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index bc403ccbf..abe145537 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -18,7 +18,7 @@ takeoff_liftoff_user_options as _takeoff_liftoff_user_options) from aviary.variable_info.variables import Aircraft, Dynamic as _Dynamic -from aviary.interface.default_phase_info.height_energy import default_premission_subsystems +from aviary.interface.default_phase_info.simple import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 81efcaf14..22aa5a384 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -8,7 +8,6 @@ from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.simple import phase_info @use_tempdirs @@ -273,7 +272,6 @@ def bench_test_swap_4_FwFm(self): 'input_initial': True, "optimize_mach": True, "optimize_altitude": True, - "polynomial_control_order": None, "use_polynomial_control": False, "num_segments": 6, "order": 3, @@ -324,7 +322,6 @@ def bench_test_swap_4_FwFm(self): "user_options": { "optimize_mach": True, "optimize_altitude": True, - "polynomial_control_order": None, "use_polynomial_control": False, "num_segments": 5, "order": 3, diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 949253944..802232eb2 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -57,7 +57,6 @@ class EquationsOfMotion(Enum): """ Available equations of motion for use during mission analysis """ - HEIGHT_ENERGY = 'height_energy' TWO_DEGREES_OF_FREEDOM = '2DOF' # TODO these are a little out of place atm SIMPLE = 'simple' From 68fba1b4d2f6a94fd2c01c7e1916fa854ace32a8 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 11 Jan 2024 14:34:44 -0600 Subject: [PATCH 029/111] Moving to height_energy --- aviary/api.py | 7 +- .../default_phase_info/height_energy.py | 251 +++------- aviary/interface/default_phase_info/simple.py | 99 ---- aviary/interface/methods_for_level2.py | 32 +- aviary/interface/test/test_basic_report.py | 2 +- .../interface/test/test_check_phase_info.py | 10 +- aviary/interface/test/test_interface_bugs.py | 2 +- aviary/interface/test/test_phase_info.py | 2 +- aviary/interface/test/test_reserve_support.py | 2 +- aviary/interface/utils/check_phase_info.py | 4 +- .../flops_based/ode/test/test_landing_ode.py | 2 +- .../flops_based/ode/test/test_takeoff_ode.py | 2 +- .../flops_based/phases/simple_energy_phase.py | 440 ------------------ .../phases/run_phases/run_ascent.py | 2 +- aviary/models/N3CC/N3CC_data.py | 4 +- ...N3CC_generic_low_speed_polars_FLOPSinp.csv | 2 +- .../large_single_aisle_1_FLOPS_data.py | 2 +- .../large_single_aisle_2_FLOPS_data.py | 2 +- .../large_single_aisle_2_altwt_FLOPS_data.py | 2 +- ...ge_single_aisle_2_detailwing_FLOPS_data.py | 2 +- .../test_aircraft/aircraft_for_bench_FwFm.csv | 2 +- .../aircraft_for_bench_FwFm_simple.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- .../aircraft_for_bench_GwFm_simple.csv | 2 +- .../test/data/high_wing_single_aisle.csv | 2 +- .../test/test_computed_aero_group.py | 2 +- .../test/test_solved_aero_group.py | 2 +- .../test/test_tabular_aero_group.py | 2 +- .../test/test_external_subsystem_bus.py | 2 +- .../test/test_flops_based_premission.py | 2 +- aviary/utils/Fortran_to_Aviary.py | 2 +- .../benchmark_tests/test_0_iters.py | 2 +- .../test_FLOPS_balanced_field_length.py | 2 +- .../test_FLOPS_based_sizing_N3CC.py | 4 +- .../test_FLOPS_detailed_landing.py | 2 +- .../test_FLOPS_detailed_takeoff.py | 2 +- .../benchmark_tests/test_bench_GwFm.py | 2 +- aviary/variable_info/enums.py | 2 +- 38 files changed, 132 insertions(+), 777 deletions(-) delete mode 100644 aviary/interface/default_phase_info/simple.py delete mode 100644 aviary/mission/flops_based/phases/simple_energy_phase.py diff --git a/aviary/api.py b/aviary/api.py index d86b1158f..412e843fe 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -32,10 +32,9 @@ from aviary.utils.data_interpolator_builder import build_data_interpolator from aviary.variable_info.enums import AlphaModes, AnalysisScheme, ProblemType, SpeedType, GASPEngineType, FlapType, EquationsOfMotion, LegacyCode, Verbosity from aviary.interface.default_phase_info.two_dof import phase_info as default_2DOF_phase_info -from aviary.interface.default_phase_info.simple import phase_info as default_simple_phase_info from aviary.interface.default_phase_info.two_dof_fiti import create_2dof_based_ascent_phases, create_2dof_based_descent_phases from aviary.interface.default_phase_info.solved import phase_info as default_solved_phase_info -from aviary.interface.default_phase_info.simple import phase_info as default_simple_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as default_height_energy_phase_info from aviary.interface.methods_for_level1 import run_level_1 from aviary.interface.methods_for_level1 import run_aviary from aviary.interface.methods_for_level2 import AviaryProblem @@ -46,7 +45,7 @@ from aviary.utils.options import list_options from aviary.constants import GRAV_METRIC_GASP, GRAV_ENGLISH_GASP, GRAV_METRIC_FLOPS, GRAV_ENGLISH_FLOPS, GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH, RHO_SEA_LEVEL_METRIC, MU_TAKEOFF, MU_LANDING, PSLS_PSF, TSLS_DEGR, RADIUS_EARTH_METRIC from aviary.subsystems.test.subsystem_tester import TestSubsystemBuilderBase, skipIfMissingDependencies -from aviary.interface.default_phase_info.simple import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems ################### # Level 3 Imports # @@ -86,7 +85,7 @@ # Phase builders from aviary.mission.flops_based.phases.phase_builder_base import PhaseBuilderBase # note that this is only for simplified right now -from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase as HeightEnergyPhaseBuilder +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase as HeightEnergyPhaseBuilder from aviary.mission.flops_based.phases.build_landing import Landing as HeightEnergyLandingPhaseBuilder # note that this is only for simplified right now from aviary.mission.flops_based.phases.build_takeoff import Takeoff as HeightEnergyTakeoffPhaseBuilder diff --git a/aviary/interface/default_phase_info/height_energy.py b/aviary/interface/default_phase_info/height_energy.py index 66d584192..29dcd56ea 100644 --- a/aviary/interface/default_phase_info/height_energy.py +++ b/aviary/interface/default_phase_info/height_energy.py @@ -3,12 +3,10 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -from aviary.variable_info.variables import Dynamic, Mission from aviary.variable_info.enums import LegacyCode FLOPS = LegacyCode.FLOPS - prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) mass = CoreMassBuilder('core_mass', BaseMetaData, FLOPS) aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) @@ -17,188 +15,85 @@ default_premission_subsystems = [prop, geom, mass, aero] default_mission_subsystems = [aero, prop] + phase_info = { - 'pre_mission': { - 'include_takeoff': True, - 'optimize_mass': True, - }, - 'climb': { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'computed'} - }, - 'user_options': { - 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.RANGE: False}, - 'fix_initial_time': True, - 'fix_duration': False, - 'num_segments': 6, - 'order': 3, - 'initial_altitude': (0., 'ft'), - 'initial_ref': (1., 's'), - 'initial_bounds': ((0., 500.), 's'), - 'duration_ref': (1452., 's'), - 'duration_bounds': ((726., 2904.), 's'), - 'final_altitude': (10668, 'm'), - 'input_initial': True, - 'no_descent': False, - 'initial_mach': 0.1, - 'final_mach': 0.79, - 'fix_range': False, - 'add_initial_mass_constraint': False, + "pre_mission": {"include_takeoff": False, "optimize_mass": True}, + "climb": { + "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, + "user_options": { + "optimize_mach": False, + "optimize_altitude": False, + "polynomial_control_order": 1, + "num_segments": 5, + "order": 3, + "solve_for_range": False, + "initial_mach": (0.2, "unitless"), + "final_mach": (0.72, "unitless"), + "mach_bounds": ((0.18, 0.74), "unitless"), + "initial_altitude": (0.0, "ft"), + "final_altitude": (32000.0, "ft"), + "altitude_bounds": ((0.0, 34000.0), "ft"), + "throttle_enforcement": "path_constraint", + "fix_initial": True, + "constrain_final": False, + "fix_duration": False, + "initial_bounds": ((0.0, 0.0), "min"), + "duration_bounds": ((64.0, 192.0), "min"), + "add_initial_mass_constraint": False, }, - 'initial_guesses': { - 'times': ([2., 24.2], 'min'), - 'altitude': ([0., 35.e3], 'ft'), - 'velocity': ([220., 455.49], 'kn'), - 'mass': ([170.e3, 165.e3], 'lbm'), - 'range': ([0., 160.3], 'nmi'), - 'velocity_rate': ([0.25, 0.05], 'm/s**2'), - 'throttle': ([0.5, 0.5], 'unitless'), - } + "initial_guesses": {"times": ([0, 128], "min")}, }, - 'cruise': { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'computed'} + "cruise": { + "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, + "user_options": { + "optimize_mach": False, + "optimize_altitude": False, + "polynomial_control_order": 1, + "num_segments": 5, + "order": 3, + "solve_for_range": False, + "initial_mach": (0.72, "unitless"), + "final_mach": (0.72, "unitless"), + "mach_bounds": ((0.7, 0.74), "unitless"), + "initial_altitude": (32000.0, "ft"), + "final_altitude": (34000.0, "ft"), + "altitude_bounds": ((23000.0, 38000.0), "ft"), + "throttle_enforcement": "boundary_constraint", + "fix_initial": False, + "constrain_final": False, + "fix_duration": False, + "initial_bounds": ((64.0, 192.0), "min"), + "duration_bounds": ((56.5, 169.5), "min"), }, - 'user_options': { - 'fix_initial': False, - 'fix_final': False, - 'fix_duration': False, - 'num_segments': 1, - 'order': 3, - 'initial_ref': (1., 's'), - 'initial_bounds': ((500., 4000.), 's'), - 'duration_ref': (24370.8, 's'), - 'duration_bounds': ((726., 48741.6), 's'), - 'min_altitude': (10.668e3, 'm'), - 'max_altitude': (10.668e3, 'm'), - 'min_mach': 0.79, - 'max_mach': 0.79, - 'required_available_climb_rate': (1.524, 'm/s'), - 'mass_f_cruise': (1.e4, 'kg'), - 'range_f_cruise': (1.e6, 'm'), - }, - 'initial_guesses': { - 'times': ([26.2, 406.18], 'min'), - 'altitude': ([35.e3, 35.e3], 'ft'), - 'velocity': ([455.49, 455.49], 'kn'), - 'mass': ([165.e3, 140.e3], 'lbm'), - 'range': ([160.3, 3243.9], 'nmi'), - 'velocity_rate': ([0., 0.], 'm/s**2'), - 'throttle': ([0.95, 0.9], 'unitless'), - } + "initial_guesses": {"times": ([128, 113], "min")}, }, - 'descent': { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'computed'} - }, - 'user_options': { - 'fix_initial': False, - 'fix_range': True, - 'fix_duration': False, - 'num_segments': 5, - 'order': 3, - 'initial_ref': (1., 's'), - 'initial_bounds': ((10.e3, 30.e3), 's'), - 'duration_ref': (1754.4, 's'), - 'duration_bounds': ((726., 3508.8), 's'), - 'initial_altitude': (10.668e3, 'm'), - 'final_altitude': (10.668, 'm'), - 'initial_mach': 0.79, - 'final_mach': 0.3, - 'no_climb': False, + "descent": { + "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, + "user_options": { + "optimize_mach": False, + "optimize_altitude": False, + "polynomial_control_order": 1, + "num_segments": 5, + "order": 3, + "solve_for_range": False, + "initial_mach": (0.72, "unitless"), + "final_mach": (0.36, "unitless"), + "mach_bounds": ((0.34, 0.74), "unitless"), + "initial_altitude": (34000.0, "ft"), + "final_altitude": (500.0, "ft"), + "altitude_bounds": ((0.0, 38000.0), "ft"), + "throttle_enforcement": "path_constraint", + "fix_initial": False, + "constrain_final": True, + "fix_duration": False, + "initial_bounds": ((120.5, 361.5), "min"), + "duration_bounds": ((29.0, 87.0), "min"), }, - 'initial_guesses': { - 'times': ([432.38, 29.24], 'min'), - 'altitude': ([35.e3, 35.], 'ft'), - 'velocity': ([455.49, 198.44], 'kn'), - 'mass': ([120.e3, 115.e3], 'lbm'), - 'range': ([3243.9, 3378.7], 'nmi'), - 'velocity_rate': ([-0.25, 0.0], 'm/s**2'), - 'throttle': ([0., 0.], 'unitless'), - } + "initial_guesses": {"times": ([241, 58], "min")}, }, - 'post_mission': { - 'include_landing': True, + "post_mission": { + "include_landing": False, + "constrain_range": True, + "target_range": (1906, "nmi"), }, } - - -def phase_info_parameterization(phase_info, aviary_inputs): - """ - Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise Mach number, - cruise range, design gross mass. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - aviary_inputs : - Object containing values and units for all aviary inputs and options - - Returns - ------- - dict - Modified phase_info that has been changed to match the new mission - parameters - """ - - range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units='NM') - alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') - gross_mass = aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm') - mach_cruise = aviary_inputs.get_val(Mission.Summary.CRUISE_MACH) - - # Range - range_scale = 1.0 - old_range_cruise = 3500.0 - if range_cruise != old_range_cruise: - range_scale = range_cruise / old_range_cruise - - vals = phase_info['descent']['initial_guesses']['range'][0] - new_vals = [vals[0] * range_scale, vals[1] * range_scale] - phase_info['descent']['initial_guesses']['range'] = (new_vals, 'NM') - - vals = phase_info['cruise']['initial_guesses']['range'][0] - new_val = vals[1] * range_scale - phase_info['cruise']['initial_guesses']['range'] = ([vals[0], new_val], 'NM') - - # Altitude - - # This doesn't seem to be stored regularly in some of the files. - old_alt_cruise = 35000 - if alt_cruise != old_alt_cruise: - - phase_info['climb']['initial_guesses']['altitude'] = ([0.0, alt_cruise], 'ft') - phase_info['climb']['user_options']['final_altitude'] = (alt_cruise, 'ft') - phase_info['cruise']['initial_guesses']['altitude'] = \ - ([alt_cruise, alt_cruise], 'ft') - phase_info['cruise']['user_options']['min_altitude'] = (alt_cruise, 'ft') - phase_info['cruise']['user_options']['max_altitude'] = (alt_cruise, 'ft') - phase_info['descent']['initial_guesses']['altitude'] = ([alt_cruise, 0.0], 'ft') - - # TODO - Could adjust time guesses/bounds in climb2 and desc2. - - # Mass - old_gross_mass = 175400.0 - if gross_mass != old_gross_mass: - - # Note, this requires that the guess for gross mass is pretty close to the - # compute mass. - - mass_scale = gross_mass / old_gross_mass - - for phase in ['climb', 'cruise', 'descent']: - vals = phase_info[phase]['initial_guesses']['mass'][0] - new_vals = [vals[0] * mass_scale, vals[1] * mass_scale] - phase_info[phase]['initial_guesses']['mass'] = (new_vals, 'lbm') - - # Mach - old_mach_cruise = 0.79 - if mach_cruise != old_mach_cruise: - - phase_info['climb']['user_options']['final_mach'] = mach_cruise - phase_info['cruise']['user_options']['min_mach'] = mach_cruise - phase_info['cruise']['user_options']['max_mach'] = mach_cruise - phase_info['descent']['user_options']['initial_mach'] = mach_cruise - - return phase_info diff --git a/aviary/interface/default_phase_info/simple.py b/aviary/interface/default_phase_info/simple.py deleted file mode 100644 index 29dcd56ea..000000000 --- a/aviary/interface/default_phase_info/simple.py +++ /dev/null @@ -1,99 +0,0 @@ -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder -from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder -from aviary.subsystems.mass.mass_builder import CoreMassBuilder -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder -from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -from aviary.variable_info.enums import LegacyCode - -FLOPS = LegacyCode.FLOPS - -prop = CorePropulsionBuilder('core_propulsion', BaseMetaData) -mass = CoreMassBuilder('core_mass', BaseMetaData, FLOPS) -aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) -geom = CoreGeometryBuilder('core_geometry', BaseMetaData, FLOPS) - -default_premission_subsystems = [prop, geom, mass, aero] -default_mission_subsystems = [aero, prop] - - -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_range": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 34000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), - "add_initial_mass_constraint": False, - }, - "initial_guesses": {"times": ([0, 128], "min")}, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_range": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (34000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((56.5, 169.5), "min"), - }, - "initial_guesses": {"times": ([128, 113], "min")}, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_range": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (34000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 38000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), - }, - "initial_guesses": {"times": ([241, 58], "min")}, - }, - "post_mission": { - "include_landing": False, - "constrain_range": True, - "target_range": (1906, "nmi"), - }, -} diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 1c2084bc6..5227a27ed 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -19,7 +19,7 @@ from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE from aviary.mission.gasp_based.ode.params import ParamPort from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import \ @@ -67,7 +67,7 @@ GASP = LegacyCode.GASP TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM -SIMPLE = EquationsOfMotion.SIMPLE +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY SOLVED = EquationsOfMotion.SOLVED @@ -206,8 +206,8 @@ def load_inputs(self, input_filename, phase_info=None, engine_builder=None): else: if self.mission_method is TWO_DEGREES_OF_FREEDOM: from aviary.interface.default_phase_info.two_dof import phase_info - elif self.mission_method is SIMPLE: - from aviary.interface.default_phase_info.simple import phase_info + elif self.mission_method is HEIGHT_ENERGY: + from aviary.interface.default_phase_info.height_energy import phase_info elif self.mission_method is SOLVED: from aviary.interface.default_phase_info.solved import phase_info @@ -240,7 +240,7 @@ def load_inputs(self, input_filename, phase_info=None, engine_builder=None): ## PROCESSING ## # set up core subsystems - if mission_method is SIMPLE: + if mission_method is HEIGHT_ENERGY: everything_else_origin = FLOPS elif mission_method in (TWO_DEGREES_OF_FREEDOM, SOLVED): everything_else_origin = GASP @@ -412,7 +412,7 @@ def add_pre_mission_systems(self): self._add_gasp_takeoff_systems() # Check for HE mission method - elif self.mission_method is SIMPLE: + elif self.mission_method is HEIGHT_ENERGY: self._add_flops_takeoff_systems() def _add_flops_takeoff_systems(self): @@ -714,7 +714,7 @@ def _get_simple_phase(self, phase_name, phase_idx): default_mission_subsystems = [ subsystems['aerodynamics'], subsystems['propulsion']] - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: phase_object = EnergyPhase.from_phase_info( phase_name, phase_options, default_mission_subsystems, meta_data=self.meta_data) @@ -747,7 +747,7 @@ def _get_simple_phase(self, phase_name, phase_idx): fix_initial_time = get_initial(fix_initial, "time", True) input_initial = False - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: user_options.set_val('initial_ref', 10., 'min') duration_bounds = user_options.get_val("duration_bounds", 'min') user_options.set_val( @@ -1051,7 +1051,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): if phase_name == 'ascent': self._add_groundroll_eq_constraint(phase) - elif self.mission_method is SIMPLE: + elif self.mission_method is HEIGHT_ENERGY: for phase_idx, phase_name in enumerate(phases): phase = traj.add_phase( phase_name, self._get_simple_phase(phase_name, phase_idx)) @@ -1173,7 +1173,7 @@ def add_post_mission_systems(self, include_landing=True): """ if include_landing and self.post_mission_info['include_landing']: - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: self._add_flops_landing_systems() elif self.mission_method is TWO_DEGREES_OF_FREEDOM: self._add_gasp_landing_systems() @@ -1192,7 +1192,7 @@ def add_post_mission_systems(self, include_landing=True): self.post_mission.add_subsystem(external_subsystem.name, subsystem_postmission) - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: phases = list(self.phase_info.keys()) ecomp = om.ExecComp('fuel_burned = initial_mass - mass_final', initial_mass={'units': 'lbm'}, @@ -1358,7 +1358,7 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): phases, vars=[Dynamic.Mission.RANGE], units='m', ref=10.e3) self.traj.link_phases(phases[:7], vars=['TAS'], units='kn', ref=200.) - elif self.mission_method is SIMPLE: + elif self.mission_method is HEIGHT_ENERGY: self.traj.link_phases( phases, ["time", Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=True) @@ -1619,7 +1619,7 @@ def add_design_variables(self): for dv_name, dv_dict in dv_dict.items(): self.model.add_design_var(dv_name, **dv_dict) - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: optimize_mass = self.pre_mission_info.get('optimize_mass') if optimize_mass: self.model.add_design_var(Mission.Design.GROSS_MASS, units='lbm', @@ -1742,7 +1742,7 @@ def add_objective(self, objective_type=None, ref=None): self.model.add_objective(Mission.Objectives.FUEL, ref=ref) # If 'mission_method' is 'FLOPS', add a 'fuel_burned' objective - elif self.mission_method is SIMPLE: + elif self.mission_method is HEIGHT_ENERGY: ref = ref if ref is not None else default_ref_values.get("fuel_burned", 1) self.model.add_objective("fuel_burned", ref=ref) @@ -2031,7 +2031,7 @@ def _add_guesses(self, phase_name, phase, guesses): rotation_mass = self.initial_guesses['rotation_mass'] flight_duration = self.initial_guesses['flight_duration'] - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: control_keys = ["mach", "altitude"] state_keys = ["mass", "range"] else: @@ -2045,7 +2045,7 @@ def _add_guesses(self, phase_name, phase, guesses): prob_keys = ["tau_gear", "tau_flaps"] # for the simple mission method, use the provided initial and final mach and altitude values from phase_info - if self.mission_method is SIMPLE: + if self.mission_method is HEIGHT_ENERGY: initial_altitude = self.phase_info[phase_name]['user_options']['initial_altitude'] final_altitude = self.phase_info[phase_name]['user_options']['final_altitude'] initial_mach = self.phase_info[phase_name]['user_options']['initial_mach'] diff --git a/aviary/interface/test/test_basic_report.py b/aviary/interface/test/test_basic_report.py index 02d2ddc25..01b166d9f 100644 --- a/aviary/interface/test/test_basic_report.py +++ b/aviary/interface/test/test_basic_report.py @@ -5,7 +5,7 @@ from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.simple import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.interface.methods_for_level1 import run_aviary from openmdao.utils.testing_utils import use_tempdirs diff --git a/aviary/interface/test/test_check_phase_info.py b/aviary/interface/test/test_check_phase_info.py index 593d80cb5..f30b697d5 100644 --- a/aviary/interface/test/test_check_phase_info.py +++ b/aviary/interface/test/test_check_phase_info.py @@ -2,25 +2,25 @@ import copy from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.interface.default_phase_info.simple import phase_info as phase_info_flops +from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_flops from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_gasp from aviary.variable_info.enums import EquationsOfMotion -SIMPLE = EquationsOfMotion.SIMPLE +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM class TestCheckInputs(unittest.TestCase): def test_correct_input_simple(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_flops, mission_method=SIMPLE)) + self.assertTrue(check_phase_info(phase_info_flops, mission_method=HEIGHT_ENERGY)) def test_incorrect_tuple(self): # Let's replace a tuple with a float in the 'climb' phase incorrect_tuple_phase_info = copy.deepcopy(phase_info_flops) incorrect_tuple_phase_info['climb']['user_options']['initial_altitude'] = 10.668e3 with self.assertRaises(ValueError): - check_phase_info(incorrect_tuple_phase_info, mission_method=SIMPLE) + check_phase_info(incorrect_tuple_phase_info, mission_method=HEIGHT_ENERGY) def test_incorrect_unit(self): # Let's replace a valid unit with an invalid one in the 'climb' phase @@ -29,7 +29,7 @@ def test_incorrect_unit(self): 10.668e3, 'invalid_unit') with self.assertRaisesRegex(ValueError, "Key initial_altitude in phase climb has an invalid unit invalid_unit."): - check_phase_info(incorrect_unit_phase_info, mission_method=SIMPLE) + check_phase_info(incorrect_unit_phase_info, mission_method=HEIGHT_ENERGY) def test_correct_input_gasp(self): # This should pass without any issue as it's the same valid dict as before diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index ed811bc2c..59f614e3d 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -6,7 +6,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.interface.default_phase_info.simple import phase_info as ph_in +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in from aviary.variable_info.variables import Aircraft from openmdao.utils.testing_utils import use_tempdirs diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index ffefec9ae..812410958 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -78,7 +78,7 @@ def _test_phase_info_dict(self, phase_info_dict, name): def test_default_phase_simple(self): """Tests the roundtrip conversion for default_phase_info.simple""" - from aviary.interface.default_phase_info.simple import phase_info + from aviary.interface.default_phase_info.height_energy import phase_info local_phase_info = deepcopy(phase_info) self._test_phase_info_dict(local_phase_info, 'cruise') diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 0b6e3e2cf..0f0fce3b5 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -5,7 +5,7 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.default_phase_info.simple import phase_info as ph_in_flops +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_flops from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp from aviary.variable_info.variables import Aircraft, Mission diff --git a/aviary/interface/utils/check_phase_info.py b/aviary/interface/utils/check_phase_info.py index ecd21875c..48dc43a1b 100644 --- a/aviary/interface/utils/check_phase_info.py +++ b/aviary/interface/utils/check_phase_info.py @@ -2,7 +2,7 @@ from aviary.variable_info.enums import SpeedType, EquationsOfMotion TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM -SIMPLE = EquationsOfMotion.SIMPLE +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY SOLVED = EquationsOfMotion.SOLVED @@ -193,7 +193,7 @@ def check_phase_info(phase_info, mission_method): phase_keys[phase] = phase_keys_gasp[phase] elif mission_method is SOLVED: return - elif mission_method is SIMPLE: + elif mission_method is HEIGHT_ENERGY: for phase in phase_info: if phase != 'pre_mission' and phase != 'post_mission': phase_keys[phase] = {**common_keys, **common_entries} diff --git a/aviary/mission/flops_based/ode/test/test_landing_ode.py b/aviary/mission/flops_based/ode/test/test_landing_ode.py index e3faf4747..16e34c0f2 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_ode.py +++ b/aviary/mission/flops_based/ode/test/test_landing_ode.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.simple import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems from aviary.mission.flops_based.ode.landing_ode import FlareODE from aviary.models.N3CC.N3CC_data import ( detailed_landing_flare, inputs, landing_subsystem_options) diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py index ebcf3a092..fd39339e5 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py @@ -3,7 +3,7 @@ import openmdao.api as om -from aviary.interface.default_phase_info.simple import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE from aviary.models.N3CC.N3CC_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, takeoff_subsystem_options, inputs) diff --git a/aviary/mission/flops_based/phases/simple_energy_phase.py b/aviary/mission/flops_based/phases/simple_energy_phase.py deleted file mode 100644 index 6da23cbdb..000000000 --- a/aviary/mission/flops_based/phases/simple_energy_phase.py +++ /dev/null @@ -1,440 +0,0 @@ -import dymos as dm - -from aviary.mission.flops_based.phases.phase_builder_base import ( - register, PhaseBuilderBase, InitialGuessControl, InitialGuessParameter, - InitialGuessPolynomialControl, InitialGuessState, InitialGuessTime) - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial -from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.ode.simple_mission_ODE import MissionODE - - -# TODO: support/handle the following in the base class -# - phase.set_time_options() -# - currently handled in level 3 interface implementation -# - self.external_subsystems -# - self.meta_data, with cls.default_meta_data customization point -@register -class EnergyPhase(PhaseBuilderBase): - ''' - A phase builder for a simple energy phase. - - Attributes - ---------- - name : str ('energy_phase') - object label - - subsystem_options (None) - dictionary of parameters to be passed to the subsystem builders - - user_options : AviaryValues () - state/path constraint values and flags - - supported options: - - num_segments : int (5) - transcription: number of segments - - order : int (3) - transcription: order of the state transcription; the order of the control - transcription is `order - 1` - - fix_initial : bool (True) - - initial_ref : float (1.0, 's') - - initial_bounds : pair ((0.0, 100.0) 's') - - duration_ref : float (1.0, 's') - - duration_bounds : pair ((0.0, 100.0) 's') - - required_available_climb_rate : float (None) - minimum avaliable climb rate - - constrain_final : bool (False) - - input_initial : bool (False) - - initial_guesses : AviaryValues () - state/path beginning values to be set on the problem - - supported options: - - times - - range - - altitude - - velocity - - velocity_rate - - mass - - throttle - - ode_class : type (None) - advanced: the type of system defining the ODE - - transcription : "Dymos transcription object" (None) - advanced: an object providing the transcription technique of the - optimal control problem - - external_subsystems : Sequence["subsystem builder"] () - advanced - - meta_data : dict (<"builtin" meta data>) - advanced: meta data associated with variables in the Aviary data hierarchy - - default_name : str - class attribute: derived type customization point; the default value - for name - - default_ode_class : type - class attribute: derived type customization point; the default value - for ode_class used by build_phase - - default_meta_data : dict - class attribute: derived type customization point; the default value for - meta_data - - Methods - ------- - build_phase - make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = ('external_subsystems', 'meta_data') - - # region : derived type customization points - _meta_data_ = {} - - _initial_guesses_meta_data_ = {} - - default_name = 'cruise' - - default_ode_class = MissionODE - - default_meta_data = _MetaData - # endregion : derived type customization points - - def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None - ): - super().__init__( - name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) - - # TODO: support external_subsystems and meta_data in the base class - if external_subsystems is None: - external_subsystems = [] - - self.external_subsystems = external_subsystems - - if meta_data is None: - meta_data = self.default_meta_data - - self.meta_data = meta_data - - def build_phase(self, aviary_options: AviaryValues = None): - ''' - Return a new energy phase for analysis using these constraints. - - If ode_class is None, default_ode_class is used. - - If transcription is None, the return value from calling - make_default_transcription is used. - - Parameters - ---------- - aviary_options : AviaryValues () - collection of Aircraft/Mission specific options - - Returns - ------- - dymos.Phase - ''' - phase: dm.Phase = super().build_phase(aviary_options) - - user_options: AviaryValues = self.user_options - - fix_initial = user_options.get_val('fix_initial') - constrain_final = user_options.get_val('constrain_final') - optimize_mach = user_options.get_val('optimize_mach') - optimize_altitude = user_options.get_val('optimize_altitude') - input_initial = user_options.get_val('input_initial') - polynomial_control_order = user_options.get_item('polynomial_control_order')[0] - use_polynomial_control = user_options.get_val('use_polynomial_control') - throttle_enforcement = user_options.get_val('throttle_enforcement') - mach_bounds = user_options.get_item('mach_bounds') - altitude_bounds = user_options.get_item('altitude_bounds') - initial_mach = user_options.get_item('initial_mach')[0] - final_mach = user_options.get_item('final_mach')[0] - initial_altitude = user_options.get_item('initial_altitude')[0] - final_altitude = user_options.get_item('final_altitude')[0] - solve_for_range = user_options.get_val('solve_for_range') - no_descent = user_options.get_val('no_descent') - no_climb = user_options.get_val('no_climb') - - ############## - # Add States # - ############## - # TODO: critically think about how we should handle fix_initial and input_initial defaults. - # In keeping with Dymos standards, the default should be False instead of True. - input_initial_mass = get_initial(input_initial, Dynamic.Mission.MASS) - fix_initial_mass = get_initial(fix_initial, Dynamic.Mission.MASS, True) - - # Experiment: use a constraint for mass instead of connected initial. - # This is due to some problems in mpi. - # This is needed for the cutting edge full subsystem integration. - # TODO: when a Dymos fix is in and we've verified that full case works with the fix, - # remove this argument. - if user_options.get_val('add_initial_mass_constraint'): - phase.add_constraint('rhs_all.initial_mass_residual', equals=0.0, ref=1e4) - input_initial_mass = False - - phase.add_state( - Dynamic.Mission.MASS, fix_initial=fix_initial_mass, fix_final=False, - lower=0.0, ref=1e4, defect_ref=1e6, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, - input_initial=input_initial_mass, - # solve_segments='forward', - ) - - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) - phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=False, - lower=0.0, ref=1e6, defect_ref=1e8, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range, - solve_segments='forward' if solve_for_range else None, - ) - - phase = add_subsystem_variables_to_phase( - phase, self.name, self.external_subsystems) - - ################ - # Add Controls # - ################ - if use_polynomial_control: - phase.add_polynomial_control( - Dynamic.Mission.MACH, - targets=Dynamic.Mission.MACH, units=mach_bounds[1], - opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], - rate_targets=[Dynamic.Mission.MACH_RATE], - order=polynomial_control_order, ref=0.5, - ) - else: - phase.add_control( - Dynamic.Mission.MACH, - targets=Dynamic.Mission.MACH, units=mach_bounds[1], - opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], - rate_targets=[Dynamic.Mission.MACH_RATE], - ref=0.5, - ) - - if optimize_mach and fix_initial: - phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc='initial', equals=initial_mach, - ) - - if optimize_mach and constrain_final: - phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc='final', equals=final_mach, - ) - - # Add altitude rate as a control - if use_polynomial_control: - phase.add_polynomial_control( - Dynamic.Mission.ALTITUDE, - targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], - opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], - rate_targets=[Dynamic.Mission.ALTITUDE_RATE], - order=polynomial_control_order, ref=altitude_bounds[0][1], - ) - else: - phase.add_control( - Dynamic.Mission.ALTITUDE, - targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], - opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], - rate_targets=[Dynamic.Mission.ALTITUDE_RATE], - ref=altitude_bounds[0][1], - ) - - if optimize_altitude and fix_initial: - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='initial', equals=initial_altitude, units=altitude_bounds[1], ref=1.e4, - ) - - if optimize_altitude and constrain_final: - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='final', equals=final_altitude, units=altitude_bounds[1], ref=1.e4, - ) - - ################## - # Add Timeseries # - ################## - phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units='unitless' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' - ) - - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, units='m/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - output_name=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' - ) - - phase.add_timeseries_output( - Dynamic.Mission.ALTITUDE_RATE, - output_name=Dynamic.Mission.ALTITUDE_RATE, units='ft/s' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THROTTLE, - output_name=Dynamic.Mission.THROTTLE, units='unitless' - ) - - phase.add_timeseries_output( - Dynamic.Mission.VELOCITY, - output_name=Dynamic.Mission.VELOCITY, units='m/s' - ) - - ################### - # Add Constraints # - ################### - if no_descent: - phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, lower=0.0) - - if no_climb: - phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, upper=0.0) - - required_available_climb_rate, units = user_options.get_item( - 'required_available_climb_rate') - - if required_available_climb_rate is not None: - phase.add_path_constraint( - Dynamic.Mission.ALTITUDE_RATE_MAX, - lower=required_available_climb_rate, units=units - ) - - if throttle_enforcement == 'boundary_constraint': - phase.add_boundary_constraint( - Dynamic.Mission.THROTTLE, loc='initial', lower=0.0, upper=1.0, units='unitless', - ) - phase.add_boundary_constraint( - Dynamic.Mission.THROTTLE, loc='final', lower=0.0, upper=1.0, units='unitless', - ) - elif throttle_enforcement == 'path_constraint': - phase.add_path_constraint( - Dynamic.Mission.THROTTLE, lower=0.0, upper=1.0, units='unitless', - ) - - return phase - - def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' - user_options = self.user_options - - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') - - seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) - - transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True, - segment_ends=seg_ends) - - return transcription - - def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - # TODO: support external_subsystems and meta_data in the base class - return { - 'external_subsystems': self.external_subsystems, - 'meta_data': self.meta_data, - 'subsystem_options': self.subsystem_options, - 'throttle_enforcement': self.user_options.get_val('throttle_enforcement'), - } - - -EnergyPhase._add_meta_data( - 'num_segments', val=5, desc='transcription: number of segments') - -EnergyPhase._add_meta_data( - 'order', val=3, - desc='transcription: order of the state transcription; the order of the control' - ' transcription is `order - 1`') - -EnergyPhase._add_meta_data('polynomial_control_order', val=3) - -EnergyPhase._add_meta_data('use_polynomial_control', val=True) - -EnergyPhase._add_meta_data('add_initial_mass_constraint', val=False) - -EnergyPhase._add_meta_data('fix_initial', val=True) - -EnergyPhase._add_meta_data('optimize_mach', val=False) - -EnergyPhase._add_meta_data('optimize_altitude', val=False) - -EnergyPhase._add_meta_data('initial_bounds', val=(0., 100.), units='s') - -EnergyPhase._add_meta_data('duration_bounds', val=(0., 100.), units='s') - -EnergyPhase._add_meta_data( - 'required_available_climb_rate', val=None, units='m/s', - desc='minimum avaliable climb rate') - -EnergyPhase._add_meta_data( - 'no_climb', val=False, desc='aircraft is not allowed to climb during phase') - -EnergyPhase._add_meta_data( - 'no_descent', val=False, desc='aircraft is not allowed to descend during phase') - -EnergyPhase._add_meta_data('constrain_final', val=False) - -EnergyPhase._add_meta_data('input_initial', val=False) - -EnergyPhase._add_meta_data('initial_mach', val=None, units='unitless') - -EnergyPhase._add_meta_data('final_mach', val=None, units='unitless') - -EnergyPhase._add_meta_data('initial_altitude', val=None, units='ft') - -EnergyPhase._add_meta_data('final_altitude', val=None, units='ft') - -EnergyPhase._add_meta_data('throttle_enforcement', val=None) - -EnergyPhase._add_meta_data('mach_bounds', val=(0., 2.), units='unitless') - -EnergyPhase._add_meta_data('altitude_bounds', val=(0., 60.e3), units='ft') - -EnergyPhase._add_meta_data('solve_for_range', val=False) - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessTime(), - desc='initial guess for initial time and duration specified as a tuple') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('range'), - desc='initial guess for horizontal distance traveled') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for vertical distances') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('mach'), - desc='initial guess for speed') - -EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') diff --git a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py index 598e1ba8b..fdd3c0384 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_ascent.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_ascent.py @@ -5,7 +5,7 @@ from aviary.mission.gasp_based.polynomial_fit import PolynomialFit from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.interface.default_phase_info.simple import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems def run_ascent(make_plots=False): diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index 13219ce56..a163553ea 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -26,7 +26,7 @@ from aviary.variable_info.variables import Mission from aviary.variable_info.variables import Settings from aviary.variable_info.enums import EquationsOfMotion, LegacyCode -from aviary.interface.default_phase_info.simple import default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_mission_subsystems Dynamic = _Dynamic.Mission @@ -315,7 +315,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv index 2ceb7088d..81ac1ee35 100644 --- a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv +++ b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv @@ -169,7 +169,7 @@ mission:takeoff:rolling_friction_coefficient,0.0175,unitless mission:takeoff:spoiler_drag_coefficient,0.085,unitless mission:takeoff:spoiler_lift_coefficient,-0.81,unitless mission:takeoff:thrust_incidence,0,deg -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,FLOPS # Unconverted Values diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py index 8b3f48616..feeca95a1 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py index 3f36a12f2..37ef21ff0 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py index 2c1328bc7..667b0d72a 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py @@ -262,7 +262,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py index f8fe5041a..ca02d5832 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py +++ b/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py @@ -263,7 +263,7 @@ # Settings # --------------------------- -inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) +inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index abdddb634..2d4ea4703 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -155,5 +155,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv index abdddb634..2d4ea4703 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv @@ -155,5 +155,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index b0c9ace8d..5c0d0b8a0 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -269,5 +269,5 @@ mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv index b0c9ace8d..5c0d0b8a0 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv @@ -269,5 +269,5 @@ mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv index df17fad98..356ddc757 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv +++ b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv @@ -137,5 +137,5 @@ mission:takeoff:fuel_simple,400,lbm mission:takeoff:lift_coefficient_max,2.55,unitless mission:takeoff:lift_over_drag,25,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,simple +settings:equations_of_motion,height_energy settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py index c6a26a221..3788620b8 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py @@ -5,7 +5,7 @@ from openmdao.utils.assert_utils import assert_near_equal from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.simple import aero, prop, geom +from aviary.interface.default_phase_info.height_energy import aero, prop, geom from aviary.utils.aviary_values import get_items from aviary.utils.functions import set_aviary_initial_values from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index a09db92f1..ac78f16d8 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -13,7 +13,7 @@ from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.csv_data_file import read_data_file from aviary.utils.named_values import NamedValues -from aviary.interface.default_phase_info.simple import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info from aviary.variable_info.variables import Aircraft from copy import deepcopy diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py index 216f17fc5..897caf9a5 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py @@ -8,7 +8,7 @@ from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.simple import aero, prop, geom +from aviary.interface.default_phase_info.height_energy import aero, prop, geom from aviary.utils.aviary_values import AviaryValues, get_items from aviary.utils.functions import set_aviary_initial_values from aviary.utils.named_values import NamedValues diff --git a/aviary/subsystems/test/test_external_subsystem_bus.py b/aviary/subsystems/test/test_external_subsystem_bus.py index 97b3c5e69..24f9dd4ba 100644 --- a/aviary/subsystems/test/test_external_subsystem_bus.py +++ b/aviary/subsystems/test/test_external_subsystem_bus.py @@ -9,7 +9,7 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.simple import phase_info as ph_in +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 07ebbf478..87a2251e1 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -13,7 +13,7 @@ from aviary.variable_info.variables import Aircraft, Mission from aviary.variable_info.variables_in import VariablesIn from aviary.utils.functions import set_aviary_initial_values -from aviary.interface.default_phase_info.simple import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index 82aad72c3..3273f0ee5 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -108,7 +108,7 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, for var, (val, units) in sorted(vehicle_data['input_values']): writer.writerow([var] + val + [units]) if legacy_code is FLOPS: - EOM = 'simple' + EOM = 'height_energy' mass = 'FLOPS' if legacy_code is GASP: EOM = '2DOF' diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 5ddf69121..0423ac7de 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -5,7 +5,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info -from aviary.interface.default_phase_info.simple import phase_info as simple_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as simple_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info from aviary.variable_info.enums import EquationsOfMotion diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index 98b67bb04..aff3bb72c 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -20,7 +20,7 @@ inputs as _inputs from aviary.variable_info.variables import Dynamic as _Dynamic from aviary.variable_info.variables_in import VariablesIn -from aviary.interface.default_phase_info.simple import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.subsystems.premission import CorePreMission Dynamic = _Dynamic.Mission diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 3de522d6f..cd7129be8 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -22,11 +22,11 @@ from aviary.variable_info.functions import setup_trajectory_params from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables_in import VariablesIn -from aviary.mission.flops_based.phases.simple_energy_phase import EnergyPhase +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.subsystems.premission import CorePreMission -from aviary.interface.default_phase_info.simple import default_premission_subsystems, default_mission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload try: diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 99b4c3c31..512b710d8 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -18,7 +18,7 @@ landing_fullstop_user_options as _landing_fullstop_user_options) from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.interface.default_phase_info.simple import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index abe145537..bc403ccbf 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -18,7 +18,7 @@ takeoff_liftoff_user_options as _takeoff_liftoff_user_options) from aviary.variable_info.variables import Aircraft, Dynamic as _Dynamic -from aviary.interface.default_phase_info.simple import default_premission_subsystems +from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index b5e9600aa..ad785f4d8 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -15,7 +15,7 @@ from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.simple import phase_info +from aviary.interface.default_phase_info.height_energy import phase_info @use_tempdirs diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 802232eb2..17e8f102c 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -59,7 +59,7 @@ class EquationsOfMotion(Enum): """ TWO_DEGREES_OF_FREEDOM = '2DOF' # TODO these are a little out of place atm - SIMPLE = 'simple' + HEIGHT_ENERGY = 'height_energy' SOLVED = 'solved' From 2fa1bc384ec41c386eb5067937528b6c2d6cdedb Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 11 Jan 2024 14:42:29 -0600 Subject: [PATCH 030/111] Added missing file --- .../flops_based/phases/energy_phase.py | 440 ++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 aviary/mission/flops_based/phases/energy_phase.py diff --git a/aviary/mission/flops_based/phases/energy_phase.py b/aviary/mission/flops_based/phases/energy_phase.py new file mode 100644 index 000000000..6da23cbdb --- /dev/null +++ b/aviary/mission/flops_based/phases/energy_phase.py @@ -0,0 +1,440 @@ +import dymos as dm + +from aviary.mission.flops_based.phases.phase_builder_base import ( + register, PhaseBuilderBase, InitialGuessControl, InitialGuessParameter, + InitialGuessPolynomialControl, InitialGuessState, InitialGuessTime) + +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.variable_meta_data import _MetaData +from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial +from aviary.variable_info.variables import Dynamic +from aviary.mission.flops_based.ode.simple_mission_ODE import MissionODE + + +# TODO: support/handle the following in the base class +# - phase.set_time_options() +# - currently handled in level 3 interface implementation +# - self.external_subsystems +# - self.meta_data, with cls.default_meta_data customization point +@register +class EnergyPhase(PhaseBuilderBase): + ''' + A phase builder for a simple energy phase. + + Attributes + ---------- + name : str ('energy_phase') + object label + + subsystem_options (None) + dictionary of parameters to be passed to the subsystem builders + + user_options : AviaryValues () + state/path constraint values and flags + + supported options: + - num_segments : int (5) + transcription: number of segments + - order : int (3) + transcription: order of the state transcription; the order of the control + transcription is `order - 1` + - fix_initial : bool (True) + - initial_ref : float (1.0, 's') + - initial_bounds : pair ((0.0, 100.0) 's') + - duration_ref : float (1.0, 's') + - duration_bounds : pair ((0.0, 100.0) 's') + - required_available_climb_rate : float (None) + minimum avaliable climb rate + - constrain_final : bool (False) + - input_initial : bool (False) + + initial_guesses : AviaryValues () + state/path beginning values to be set on the problem + + supported options: + - times + - range + - altitude + - velocity + - velocity_rate + - mass + - throttle + + ode_class : type (None) + advanced: the type of system defining the ODE + + transcription : "Dymos transcription object" (None) + advanced: an object providing the transcription technique of the + optimal control problem + + external_subsystems : Sequence["subsystem builder"] () + advanced + + meta_data : dict (<"builtin" meta data>) + advanced: meta data associated with variables in the Aviary data hierarchy + + default_name : str + class attribute: derived type customization point; the default value + for name + + default_ode_class : type + class attribute: derived type customization point; the default value + for ode_class used by build_phase + + default_meta_data : dict + class attribute: derived type customization point; the default value for + meta_data + + Methods + ------- + build_phase + make_default_transcription + validate_options + assign_default_options + ''' + __slots__ = ('external_subsystems', 'meta_data') + + # region : derived type customization points + _meta_data_ = {} + + _initial_guesses_meta_data_ = {} + + default_name = 'cruise' + + default_ode_class = MissionODE + + default_meta_data = _MetaData + # endregion : derived type customization points + + def __init__( + self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, + ode_class=None, transcription=None, core_subsystems=None, + external_subsystems=None, meta_data=None + ): + super().__init__( + name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) + + # TODO: support external_subsystems and meta_data in the base class + if external_subsystems is None: + external_subsystems = [] + + self.external_subsystems = external_subsystems + + if meta_data is None: + meta_data = self.default_meta_data + + self.meta_data = meta_data + + def build_phase(self, aviary_options: AviaryValues = None): + ''' + Return a new energy phase for analysis using these constraints. + + If ode_class is None, default_ode_class is used. + + If transcription is None, the return value from calling + make_default_transcription is used. + + Parameters + ---------- + aviary_options : AviaryValues () + collection of Aircraft/Mission specific options + + Returns + ------- + dymos.Phase + ''' + phase: dm.Phase = super().build_phase(aviary_options) + + user_options: AviaryValues = self.user_options + + fix_initial = user_options.get_val('fix_initial') + constrain_final = user_options.get_val('constrain_final') + optimize_mach = user_options.get_val('optimize_mach') + optimize_altitude = user_options.get_val('optimize_altitude') + input_initial = user_options.get_val('input_initial') + polynomial_control_order = user_options.get_item('polynomial_control_order')[0] + use_polynomial_control = user_options.get_val('use_polynomial_control') + throttle_enforcement = user_options.get_val('throttle_enforcement') + mach_bounds = user_options.get_item('mach_bounds') + altitude_bounds = user_options.get_item('altitude_bounds') + initial_mach = user_options.get_item('initial_mach')[0] + final_mach = user_options.get_item('final_mach')[0] + initial_altitude = user_options.get_item('initial_altitude')[0] + final_altitude = user_options.get_item('final_altitude')[0] + solve_for_range = user_options.get_val('solve_for_range') + no_descent = user_options.get_val('no_descent') + no_climb = user_options.get_val('no_climb') + + ############## + # Add States # + ############## + # TODO: critically think about how we should handle fix_initial and input_initial defaults. + # In keeping with Dymos standards, the default should be False instead of True. + input_initial_mass = get_initial(input_initial, Dynamic.Mission.MASS) + fix_initial_mass = get_initial(fix_initial, Dynamic.Mission.MASS, True) + + # Experiment: use a constraint for mass instead of connected initial. + # This is due to some problems in mpi. + # This is needed for the cutting edge full subsystem integration. + # TODO: when a Dymos fix is in and we've verified that full case works with the fix, + # remove this argument. + if user_options.get_val('add_initial_mass_constraint'): + phase.add_constraint('rhs_all.initial_mass_residual', equals=0.0, ref=1e4) + input_initial_mass = False + + phase.add_state( + Dynamic.Mission.MASS, fix_initial=fix_initial_mass, fix_final=False, + lower=0.0, ref=1e4, defect_ref=1e6, units='kg', + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, + input_initial=input_initial_mass, + # solve_segments='forward', + ) + + input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) + fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) + phase.add_state( + Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=False, + lower=0.0, ref=1e6, defect_ref=1e8, units='m', + rate_source=Dynamic.Mission.RANGE_RATE, + input_initial=input_initial_range, + solve_segments='forward' if solve_for_range else None, + ) + + phase = add_subsystem_variables_to_phase( + phase, self.name, self.external_subsystems) + + ################ + # Add Controls # + ################ + if use_polynomial_control: + phase.add_polynomial_control( + Dynamic.Mission.MACH, + targets=Dynamic.Mission.MACH, units=mach_bounds[1], + opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], + rate_targets=[Dynamic.Mission.MACH_RATE], + order=polynomial_control_order, ref=0.5, + ) + else: + phase.add_control( + Dynamic.Mission.MACH, + targets=Dynamic.Mission.MACH, units=mach_bounds[1], + opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], + rate_targets=[Dynamic.Mission.MACH_RATE], + ref=0.5, + ) + + if optimize_mach and fix_initial: + phase.add_boundary_constraint( + Dynamic.Mission.MACH, loc='initial', equals=initial_mach, + ) + + if optimize_mach and constrain_final: + phase.add_boundary_constraint( + Dynamic.Mission.MACH, loc='final', equals=final_mach, + ) + + # Add altitude rate as a control + if use_polynomial_control: + phase.add_polynomial_control( + Dynamic.Mission.ALTITUDE, + targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], + opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], + rate_targets=[Dynamic.Mission.ALTITUDE_RATE], + order=polynomial_control_order, ref=altitude_bounds[0][1], + ) + else: + phase.add_control( + Dynamic.Mission.ALTITUDE, + targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], + opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], + rate_targets=[Dynamic.Mission.ALTITUDE_RATE], + ref=altitude_bounds[0][1], + ) + + if optimize_altitude and fix_initial: + phase.add_boundary_constraint( + Dynamic.Mission.ALTITUDE, loc='initial', equals=initial_altitude, units=altitude_bounds[1], ref=1.e4, + ) + + if optimize_altitude and constrain_final: + phase.add_boundary_constraint( + Dynamic.Mission.ALTITUDE, loc='final', equals=final_altitude, units=altitude_bounds[1], ref=1.e4, + ) + + ################## + # Add Timeseries # + ################## + phase.add_timeseries_output( + Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units='unitless' + ) + + phase.add_timeseries_output( + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + ) + + phase.add_timeseries_output( + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + ) + + phase.add_timeseries_output( + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, units='m/s' + ) + + phase.add_timeseries_output( + Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + output_name=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' + ) + + phase.add_timeseries_output( + Dynamic.Mission.ALTITUDE_RATE, + output_name=Dynamic.Mission.ALTITUDE_RATE, units='ft/s' + ) + + phase.add_timeseries_output( + Dynamic.Mission.THROTTLE, + output_name=Dynamic.Mission.THROTTLE, units='unitless' + ) + + phase.add_timeseries_output( + Dynamic.Mission.VELOCITY, + output_name=Dynamic.Mission.VELOCITY, units='m/s' + ) + + ################### + # Add Constraints # + ################### + if no_descent: + phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, lower=0.0) + + if no_climb: + phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, upper=0.0) + + required_available_climb_rate, units = user_options.get_item( + 'required_available_climb_rate') + + if required_available_climb_rate is not None: + phase.add_path_constraint( + Dynamic.Mission.ALTITUDE_RATE_MAX, + lower=required_available_climb_rate, units=units + ) + + if throttle_enforcement == 'boundary_constraint': + phase.add_boundary_constraint( + Dynamic.Mission.THROTTLE, loc='initial', lower=0.0, upper=1.0, units='unitless', + ) + phase.add_boundary_constraint( + Dynamic.Mission.THROTTLE, loc='final', lower=0.0, upper=1.0, units='unitless', + ) + elif throttle_enforcement == 'path_constraint': + phase.add_path_constraint( + Dynamic.Mission.THROTTLE, lower=0.0, upper=1.0, units='unitless', + ) + + return phase + + def make_default_transcription(self): + ''' + Return a transcription object to be used by default in build_phase. + ''' + user_options = self.user_options + + num_segments, _ = user_options.get_item('num_segments') + order, _ = user_options.get_item('order') + + seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) + + transcription = dm.Radau( + num_segments=num_segments, order=order, compressed=True, + segment_ends=seg_ends) + + return transcription + + def _extra_ode_init_kwargs(self): + """ + Return extra kwargs required for initializing the ODE. + """ + # TODO: support external_subsystems and meta_data in the base class + return { + 'external_subsystems': self.external_subsystems, + 'meta_data': self.meta_data, + 'subsystem_options': self.subsystem_options, + 'throttle_enforcement': self.user_options.get_val('throttle_enforcement'), + } + + +EnergyPhase._add_meta_data( + 'num_segments', val=5, desc='transcription: number of segments') + +EnergyPhase._add_meta_data( + 'order', val=3, + desc='transcription: order of the state transcription; the order of the control' + ' transcription is `order - 1`') + +EnergyPhase._add_meta_data('polynomial_control_order', val=3) + +EnergyPhase._add_meta_data('use_polynomial_control', val=True) + +EnergyPhase._add_meta_data('add_initial_mass_constraint', val=False) + +EnergyPhase._add_meta_data('fix_initial', val=True) + +EnergyPhase._add_meta_data('optimize_mach', val=False) + +EnergyPhase._add_meta_data('optimize_altitude', val=False) + +EnergyPhase._add_meta_data('initial_bounds', val=(0., 100.), units='s') + +EnergyPhase._add_meta_data('duration_bounds', val=(0., 100.), units='s') + +EnergyPhase._add_meta_data( + 'required_available_climb_rate', val=None, units='m/s', + desc='minimum avaliable climb rate') + +EnergyPhase._add_meta_data( + 'no_climb', val=False, desc='aircraft is not allowed to climb during phase') + +EnergyPhase._add_meta_data( + 'no_descent', val=False, desc='aircraft is not allowed to descend during phase') + +EnergyPhase._add_meta_data('constrain_final', val=False) + +EnergyPhase._add_meta_data('input_initial', val=False) + +EnergyPhase._add_meta_data('initial_mach', val=None, units='unitless') + +EnergyPhase._add_meta_data('final_mach', val=None, units='unitless') + +EnergyPhase._add_meta_data('initial_altitude', val=None, units='ft') + +EnergyPhase._add_meta_data('final_altitude', val=None, units='ft') + +EnergyPhase._add_meta_data('throttle_enforcement', val=None) + +EnergyPhase._add_meta_data('mach_bounds', val=(0., 2.), units='unitless') + +EnergyPhase._add_meta_data('altitude_bounds', val=(0., 60.e3), units='ft') + +EnergyPhase._add_meta_data('solve_for_range', val=False) + +EnergyPhase._add_initial_guess_meta_data( + InitialGuessTime(), + desc='initial guess for initial time and duration specified as a tuple') + +EnergyPhase._add_initial_guess_meta_data( + InitialGuessState('range'), + desc='initial guess for horizontal distance traveled') + +EnergyPhase._add_initial_guess_meta_data( + InitialGuessState('altitude'), + desc='initial guess for vertical distances') + +EnergyPhase._add_initial_guess_meta_data( + InitialGuessState('mach'), + desc='initial guess for speed') + +EnergyPhase._add_initial_guess_meta_data( + InitialGuessState('mass'), + desc='initial guess for mass') From 0c9be9b2de2af51990b7eef19cd4f70714155734 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 11 Jan 2024 14:44:33 -0600 Subject: [PATCH 031/111] Moved simple to mission --- .../flops_based/ode/{simple_mission_EOM.py => mission_EOM.py} | 0 .../flops_based/ode/{simple_mission_ODE.py => mission_ODE.py} | 2 +- aviary/mission/flops_based/phases/energy_phase.py | 2 +- aviary/mission/flops_based/phases/phase_builder_base.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename aviary/mission/flops_based/ode/{simple_mission_EOM.py => mission_EOM.py} (100%) rename aviary/mission/flops_based/ode/{simple_mission_ODE.py => mission_ODE.py} (99%) diff --git a/aviary/mission/flops_based/ode/simple_mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py similarity index 100% rename from aviary/mission/flops_based/ode/simple_mission_EOM.py rename to aviary/mission/flops_based/ode/mission_EOM.py diff --git a/aviary/mission/flops_based/ode/simple_mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py similarity index 99% rename from aviary/mission/flops_based/ode/simple_mission_ODE.py rename to aviary/mission/flops_based/ode/mission_ODE.py index 58554956b..ef4c1a23f 100644 --- a/aviary/mission/flops_based/ode/simple_mission_ODE.py +++ b/aviary/mission/flops_based/ode/mission_ODE.py @@ -2,7 +2,7 @@ import openmdao.api as om from dymos.models.atmosphere import USatm1976Comp -from aviary.mission.flops_based.ode.simple_mission_EOM import MissionEOM +from aviary.mission.flops_based.ode.mission_EOM import MissionEOM from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import promote_aircraft_and_mission_vars from aviary.variable_info.variable_meta_data import _MetaData diff --git a/aviary/mission/flops_based/phases/energy_phase.py b/aviary/mission/flops_based/phases/energy_phase.py index 6da23cbdb..a1452a3f3 100644 --- a/aviary/mission/flops_based/phases/energy_phase.py +++ b/aviary/mission/flops_based/phases/energy_phase.py @@ -8,7 +8,7 @@ from aviary.variable_info.variable_meta_data import _MetaData from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.ode.simple_mission_ODE import MissionODE +from aviary.mission.flops_based.ode.mission_ODE import MissionODE # TODO: support/handle the following in the base class diff --git a/aviary/mission/flops_based/phases/phase_builder_base.py b/aviary/mission/flops_based/phases/phase_builder_base.py index 0ff2b77f4..b299689c5 100644 --- a/aviary/mission/flops_based/phases/phase_builder_base.py +++ b/aviary/mission/flops_based/phases/phase_builder_base.py @@ -28,7 +28,7 @@ import numpy as np import openmdao.api as om -from aviary.mission.flops_based.ode.simple_mission_ODE import MissionODE +from aviary.mission.flops_based.ode.mission_ODE import MissionODE from aviary.utils.aviary_values import AviaryValues, get_keys _require_new_meta_data_class_attr_ = \ From a085bac645ac3b494403a384faa940c9a3ae28b5 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Thu, 11 Jan 2024 17:21:40 -0800 Subject: [PATCH 032/111] Fixes for setting and using reserve values Removed unused Enum Allow user to set both the fraction and the additional reserve Fixed backwards incompatibility with GASP decks Updated docs --- .../getting_started/input_csv_phase_info.md | 8 +-- aviary/interface/methods_for_level2.py | 56 ++++++++++--------- aviary/interface/test/test_reserve_support.py | 4 +- .../large_single_aisle_1_GwGm.csv | 4 +- .../small_single_aisle_GwGm.csv | 4 +- .../small_single_aisle_GwGm.dat | 2 +- .../test_aircraft/aircraft_for_bench_FwFm.csv | 2 +- .../test_aircraft/aircraft_for_bench_FwGm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwGm.csv | 2 +- ...converter_configuration_test_data_GwGm.csv | 4 +- ...converter_configuration_test_data_GwGm.dat | 2 +- aviary/utils/Fortran_to_Aviary.py | 14 +++-- aviary/utils/process_input_decks.py | 38 ++++++------- aviary/variable_info/enums.py | 24 -------- aviary/variable_info/variable_meta_data.py | 34 +++++++---- aviary/variable_info/variables.py | 5 +- 17 files changed, 100 insertions(+), 107 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.md b/aviary/docs/getting_started/input_csv_phase_info.md index 01f0a59db..4863a70a0 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.md +++ b/aviary/docs/getting_started/input_csv_phase_info.md @@ -19,12 +19,12 @@ This section is under development. - reserves: 0 The initial guess of `reserves` is used to define the reserve fuel. Initially, its value can be anything larger than or equal to 0. There are two Aviary variables to control the reserve fuel in the model file (`.csv`): -- `Aircraft.Design.FIXED_RESERVES_FUEL`: the required fuel reserves: directly in lbm, -- `Aircraft.Design.RESERVES_FRACTION`: the required fuel reserves: given as a proportion of mission fuel. +- `Aircraft.Design.RESERVE_FUEL_ADDITIONAL`: the required fuel reserves: directly in lbm, +- `Aircraft.Design.RESERVE_FUEL_FRACTION`: the required fuel reserves: given as a proportion of mission fuel. -Users should set one of them to zero. If the value of initial guess of `reserves` (also in the model file if any) is 0, the initial guess of reserve fuel comes from the above two Aviary variables. Otherwise, it is determined by the parameter `reserves`: +If the value of initial guess of `reserves` (also in the model file if any) is 0, the initial guess of reserve fuel comes from the above two Aviary variables. Otherwise, it is determined by the parameter `reserves`: - if `reserves > 10`, we assume it is the actual fuel reserves. -- if `0.0 <= reserves <= 10`, we assume it is the fraction of the mission fuel. The case when `reserves` is between 1 and 10 is non-sensical but technically valid. +- if `0.0 <= reserves <= 10`, we assume it is the fraction of the mission fuel. The initial guess of `reserves` is always converted to the actual design reserves (instead of reserve factor) and is used to update the initial guesses of `fuel_burn_per_passenger_mile` and `cruise_mass_final`. diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 9feb8f85e..2eb0d3e01 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2451,30 +2451,34 @@ def _add_gasp_landing_systems(self): def _add_fuel_reserve_component(self, reserves_name=Mission.Design.RESERVE_FUEL): reserves_val = self.aviary_inputs.get_val( - Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm') reserves_frac = self.aviary_inputs.get_val( - Aircraft.Design.RESERVES_FRACTION, units='unitless') - if reserves_val > 0.0: - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_val}", - reserve_fuel={"val": reserves_val, "units": "lbm"} - ), - promotes_outputs=[("reserve_fuel", reserves_name)], - ) - elif reserves_frac >= 0: - self.model.add_subsystem( - "reserves_calc", - om.ExecComp( - f"reserve_fuel = {reserves_frac}*(takeoff_mass - final_mass)", - takeoff_mass={"units": "lbm"}, - final_mass={"units": "lbm"}, - reserve_fuel={"units": "lbm"} - ), - promotes_inputs=[ - ("takeoff_mass", Mission.Summary.GROSS_MASS), - ("final_mass", Mission.Landing.TOUCHDOWN_MASS), - ], - promotes_outputs=[("reserve_fuel", reserves_name)], - ) + Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') + + if reserves_frac == 0 and reserves_val == 0: + return + + input_data = {} + input_promotions = {} + equation_string = f"reserve_fuel = " + if reserves_frac != 0: + input_data = {'takeoff_mass': {"units": "lbm"}, + 'final_mass': {"units": "lbm"}} + input_promotions = {'promotes_inputs': [ + ("takeoff_mass", Mission.Summary.GROSS_MASS), + ("final_mass", Mission.Landing.TOUCHDOWN_MASS) + ]} + equation_string += f"{reserves_frac}*(takeoff_mass - final_mass)" + if reserves_val != 0: + equation_string += f" + {reserves_val}" + + self.model.add_subsystem( + "reserves_calc", + om.ExecComp( + equation_string, + reserve_fuel={"val": reserves_val, "units": "lbm"}, + **input_data + ), + promotes_outputs=[("reserve_fuel", reserves_name)], + **input_promotions + ) diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 860ac397e..ef47fce98 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -26,7 +26,7 @@ def test_post_mission_promotion(self): prob.check_inputs() prob.aviary_inputs.set_val( - Aircraft.Design.FIXED_RESERVES_FUEL, 10000.0, units='lbm') + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, 10000.0, units='lbm') prob.add_pre_mission_systems() prob.add_phases() @@ -74,7 +74,7 @@ def test_gasp_relative_reserve(self): prob.run_model() res_frac = prob.aviary_inputs.get_val( - Aircraft.Design.RESERVES_FRACTION, units='unitless') + Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') td_mass = prob.model.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm') reserve = prob.model.get_val(Mission.Design.RESERVE_FUEL, units='lbm') assert_near_equal(reserve, res_frac * (140000.0 - td_mass), 1e-3) diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index b9b9912fe..64edaefb8 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -12,10 +12,10 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless -aircraft:design:fixed_reserves_fuel,4998,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves_fraction,0,unitless +aircraft:design:reserve_fuel_additional,4998,lbm +aircraft:design:reserve_fuel_fraction,0,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index f47ed1bfb..95fa07b07 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -12,10 +12,10 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless aircraft:design:drag_increment,0.0018,unitless aircraft:design:equipment_mass_coefficients,778,0.06,0.112,0.14,1349,1.65,397,9071,7.6,3,50,6,12,unitless -aircraft:design:fixed_reserves_fuel,0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves_fraction,0.125,unitless +aircraft:design:reserve_fuel_additional,0,lbm +aircraft:design:reserve_fuel_fraction,0.125,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat index 9ad297777..622fbf4d1 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat @@ -205,7 +205,7 @@ OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=0.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) + FRESF=-0.125, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) RF(1)=2.0, ! Reserve Fuel Input: Time for Missed Approach (min) RF(2)=100., ! Reserve Fuel Input: Range to alternate RF(3)=25000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index 01633dc49..de6223b33 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -25,7 +25,7 @@ aircraft:design:base_area,0.0,ft**2 aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:fixed_reserves_fuel,3000.,lbm +aircraft:design:reserve_fuel_additional,3000.,lbm aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index 3a4f5348e..b4a10d6ff 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -12,7 +12,7 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:fixed_reserves_fuel,3000.,lbm +aircraft:design:reserve_fuel_additional,3000.,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.025,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 01f9be0cc..b195ce6d1 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -39,7 +39,7 @@ aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:fixed_reserves_fuel,5000.,lbm +aircraft:design:reserve_fuel_additional,5000.,lbm aircraft:design:smooth_mass_discontinuities,False,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index c6c89e6f3..ef970f38b 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -13,7 +13,7 @@ aircraft:design:drag_increment,0.00175,unitless aircraft:design:equipment_mass_coefficients,928,0.0736,0.112,0.14,1959,1.65,551,11192,5,3,50,7.6,12,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:fixed_reserves_fuel,4998,lbm +aircraft:design:reserve_fuel_additional,4998,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index ee9f695ca..b11a4a4d6 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -12,10 +12,10 @@ aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,30,unitless aircraft:design:drag_increment,0.0014,unitless aircraft:design:equipment_mass_coefficients,1014,0.0736,0.085,0.105,1504,1.65,126,9114,5,3,0,10,12,unitless -aircraft:design:fixed_reserves_fuel,0,lbm aircraft:design:max_structural_speed,440,mi/h aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves_fraction,0.15,unitless +aircraft:design:reserve_fuel_additional,0,lbm +aircraft:design:reserve_fuel_fraction,0.15,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm aircraft:design:supercritical_drag_shift,0.033,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat index ce493357c..1ee358869 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat @@ -209,7 +209,7 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck OFEM=.78, ! off design specified mission Mach number ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) - FRESF=0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) + FRESF=-0.15, ! Reserve fuel fraction of mission fuel (negative sign trigger) RF(1)=.05, ! Reserve Fuel Input: Time for Missed Approach RF(2)=125., ! Reserve Fuel Input: Range to alternate RF(3)=20000., ! Reserve Fuel Input: Cruise altitude to alternate diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index ce0f09aae..512b596cf 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -434,12 +434,16 @@ def update_gasp_options(vehicle_data): input_values.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, [[.12, .23, .13, .23, .23, .1, .15][flap_ind]]) - res = input_values.get_val(Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm')[0] - if res <= 1.0: - input_values.set_val(Aircraft.Design.FIXED_RESERVES_FUEL, [0], units='lbm') - input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [res], units='unitless') + res = input_values.get_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm')[0] + if res <= 0: + input_values.set_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, [0], units='lbm') + input_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, + [-res], units='unitless') + elif res >= 10: + input_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, + [0], units='unitless') else: - input_values.set_val(Aircraft.Design.RESERVES_FRACTION, [0], units='unitless') + ValueError('"FRESF" is not valid between 0 and 10.') vehicle_data['input_values'] = input_values return vehicle_data diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 924d79214..4667a5a34 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -45,8 +45,8 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val('mass_defect', val=10000, units='lbm') aircraft_values.set_val('problem_type', val=ProblemType.SIZING) aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - aircraft_values.set_val(Aircraft.Design.FIXED_RESERVES_FUEL, val=4998, units='lbm') - aircraft_values.set_val(Aircraft.Design.RESERVES_FRACTION, val=0, units='unitless') + # aircraft_values.set_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, val=4998, units='lbm') + # aircraft_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, val=0, units='unitless') vehicle_deck = get_path(vehicle_deck) @@ -165,28 +165,24 @@ def update_dependent_options(aircraft_values: AviaryValues(), dependent_options) def initial_guessing(aircraft_values: AviaryValues()): problem_type = aircraft_values.get_val('problem_type') - if initial_guesses['reserves'] == 0: - reserves = aircraft_values.get_val( - Aircraft.Design.FIXED_RESERVES_FUEL, units='lbm') - reserves_option = "direct_val" - if reserves == 0: - reserves = aircraft_values.get_val( - Aircraft.Design.RESERVES_FRACTION, units='unitless') - reserves_option = "fraction_val" - else: - reserves = initial_guesses['reserves'] - if reserves < 0.0: - raise ValueError('initial_guesses["reserves"] must be greater than 0.') - elif reserves > 10: - reserves_option = "direct_val" - else: - reserves_option = "fraction_val" - num_pax = aircraft_values.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - - if reserves_option == "fraction_val": + reserve_val = aircraft_values.get_val( + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm') + reserve_frac = aircraft_values.get_val( + Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') + + reserves = initial_guesses['reserves'] + if reserves < 0.0: + raise ValueError( + 'initial_guesses["reserves"] must be greater than or equal to 0.') + elif reserves == 0: + reserves += reserve_val + reserves += (reserve_frac * (num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * + aircraft_values.get_val(Mission.Design.RANGE, units='NM'))) + elif reserves < 10: reserves *= (num_pax * initial_guesses['fuel_burn_per_passenger_mile'] * aircraft_values.get_val(Mission.Design.RANGE, units='NM')) + initial_guesses['reserves'] = reserves if Mission.Summary.GROSS_MASS in aircraft_values: diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index aabe458d1..912283e50 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -181,27 +181,3 @@ class Flap_Type(Enum): """ Double-slotted Fowler flaps """ - - -@unique -class Reserves_Type(Enum): - """ - Defines the type of reserves used. Currently, Set_by_Time is not implemented. - """ - - Set_None = 0 - """ - Do not set it and let initial_guess['reserves'] decide. - """ - Set_Direct = 1 - """ - Set required fuel reserves directly in lbm (must be larger than 10). - """ - Set_Fraction = 2 - """ - Set required fuel reserves as a proportion of mission fuel (must be btween -1 and 0). - """ - Set_by_Time = 3 - """ - Set required fuel reserves as a proportion of time (must be btween 0 and 1 which correspond to 0 and 45 minutes). - """ diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 966c4aa18..e2601e0cc 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1049,27 +1049,26 @@ ) add_meta_data( - Aircraft.Design.FIXED_RESERVES_FUEL, + Aircraft.Design.FIXED_USEFUL_LOAD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FRESF', + historical_name={"GASP": 'INGASP.WFUL', "FLOPS": None, "LEAPS1": None }, - option=True, - units="lbm", - desc='required fuel reserves: directly in lbm', - default_value=0, + units='lbm', + desc='total mass of fixed useful load: crew, service items, trapped oil, etc', ) add_meta_data( - Aircraft.Design.FIXED_USEFUL_LOAD, + Aircraft.Design.IJEFF, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WFUL', + historical_name={"GASP": 'INGASP.IJEFF', "FLOPS": None, "LEAPS1": None }, - units='lbm', - desc='total mass of fixed useful load: crew, service items, trapped oil, etc', + desc="A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. \ + This flag is planted here to thank him for his hard work and dedication, Aviary wouldn't be what it is today \ + without his help.", ) add_meta_data( @@ -1198,7 +1197,20 @@ ) add_meta_data( - Aircraft.Design.RESERVES_FRACTION, + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, + meta_data=_MetaData, + historical_name={"GASP": 'INGASP.FRESF', + "FLOPS": None, + "LEAPS1": None + }, + option=True, + units="lbm", + desc='required fuel reserves: directly in lbm', + default_value=0, +) + +add_meta_data( + Aircraft.Design.RESERVE_FUEL_FRACTION, meta_data=_MetaData, historical_name={"GASP": None, "FLOPS": None, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 84deaf290..64c623c93 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -131,8 +131,8 @@ class Design: EXTERNAL_SUBSYSTEMS_MASS = 'aircraft:design:external_subsystems_mass' FINENESS = 'aircraft:design:fineness' FIXED_EQUIPMENT_MASS = 'aircraft:design:fixed_equipment_mass' - FIXED_RESERVES_FUEL = 'aircraft:design:fixed_reserves_fuel' FIXED_USEFUL_LOAD = 'aircraft:design:fixed_useful_load' + IJEFF = 'ijeff' LAMINAR_FLOW_LOWER = 'aircraft:design:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:design:laminar_flow_upper' @@ -148,7 +148,8 @@ class Design: MAX_STRUCTURAL_SPEED = 'aircraft:design:max_structural_speed' OPERATING_MASS = 'aircraft:design:operating_mass' PART25_STRUCTURAL_CATEGORY = 'aircraft:design:part25_structural_category' - RESERVES_FRACTION = 'aircraft:design:reserves_fraction' + RESERVE_FUEL_ADDITIONAL = 'aircraft:design:reserve_fuel_additional' + RESERVE_FUEL_FRACTION = 'aircraft:design:reserve_fuel_fraction' SMOOTH_MASS_DISCONTINUITIES = 'aircraft:design:smooth_mass_discontinuities' STATIC_MARGIN = 'aircraft:design:static_margin' STRUCTURAL_MASS_INCREMENT = 'aircraft:design:structural_mass_increment' From 84a8d0e2398ffb282b405e9655fdee06eb321cb1 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 11:22:16 -0500 Subject: [PATCH 033/111] Added some more outputs to help debug --- aviary/interface/test/test_simple_mission.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 78ec4902c..403c8542e 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -126,7 +126,11 @@ def test_mission_basic_and_dashboard(self): try: subprocess.check_output(cmd.split()) except subprocess.CalledProcessError as err: - self.fail("Command '{}' failed. Return code: {}".format(cmd, err.returncode)) + self.fail("Command '{}' failed. Return code: {} \n output: {} \n stderr: {} \n stdout: {}".format(cmd, + err.returncode, + err.output, + err.stderr, + err.stdout)) @require_pyoptsparse(optimizer="IPOPT") def test_mission_basic_pyopt(self): From d1ba030a65bd787fe57a776ca056e5f2444fe3ca Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 12 Jan 2024 11:05:15 -0600 Subject: [PATCH 034/111] Merging --- .../test_workflow_no_dev_install.yml | 2 +- aviary/docs/examples/OAS_subsystem.ipynb | 2 +- ...oupled_aircraft_mission_optimization.ipynb | 10 +-- .../onboarding_ext_subsystem.ipynb | 10 +-- .../getting_started/onboarding_level2.ipynb | 19 ++--- .../getting_started/onboarding_level3.ipynb | 2 +- ..._same_mission_at_different_UI_levels.ipynb | 4 +- aviary/docs/user_guide/subsystems.md | 2 +- .../OAS_weight/run_simple_OAS_mission.py | 6 +- .../external_subsystems/battery/run_cruise.py | 2 +- .../battery/run_multiphase_mission.py | 8 +- aviary/examples/level2_shooting_traj.py | 6 +- aviary/examples/test/test_all_examples.py | 5 +- aviary/interface/methods_for_level1.py | 6 +- aviary/interface/methods_for_level2.py | 7 +- aviary/interface/test/test_interface_bugs.py | 6 +- aviary/interface/test/test_phase_info.py | 2 +- aviary/interface/test/test_reserve_support.py | 4 +- .../test/test_solved_aero_group.py | 73 +++++++++++++++++++ .../aerodynamics/gasp_based/table_based.py | 11 +-- .../test/test_custom_engine_model.py | 6 +- .../test/test_external_subsystem_bus.py | 5 +- .../benchmark_tests/test_0_iters.py | 2 +- .../test_full_mission_solved_level3.py | 6 +- .../test_subsystems_within_a_mission.py | 12 +-- 25 files changed, 142 insertions(+), 76 deletions(-) diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index 98f0eefe1..74c498830 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -65,7 +65,7 @@ jobs: echo "Install Aviary" echo "=============================================================" pip install packaging - pip install .[test] + pip install .[all] - name: Display conda environment info shell: bash -l {0} diff --git a/aviary/docs/examples/OAS_subsystem.ipynb b/aviary/docs/examples/OAS_subsystem.ipynb index 491b119ad..3e7db68f6 100644 --- a/aviary/docs/examples/OAS_subsystem.ipynb +++ b/aviary/docs/examples/OAS_subsystem.ipynb @@ -339,7 +339,7 @@ "prob = av.AviaryProblem()\n", "\n", "prob.load_inputs(aircraft_definition_file, phase_info)\n", - "prob.check_inputs()\n", + "prob.check_and_preprocess_inputs()\n", "prob.add_pre_mission_systems()\n", "prob.add_phases()\n", "prob.add_post_mission_systems()\n", diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index 68344b92a..850f8a627 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -208,9 +208,7 @@ "# Allow for user overrides here\n", "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", - "prob.check_inputs()\n", + "prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", @@ -328,10 +326,8 @@ "# Allow for user overrides here\n", "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", - "prob.check_inputs()\n", - "\n", + "prob.check_and_preprocess_inputs()\n", + "# Preprocess inputs\n", "prob.add_pre_mission_systems()\n", "\n", "prob.add_phases()\n", diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index bde8b897e..a8c11950b 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -64,7 +64,7 @@ "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", - "# prob.check_inputs()\n", + "# prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", @@ -123,7 +123,7 @@ "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", - "# prob.check_inputs()\n", + "# prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", @@ -170,7 +170,7 @@ "\n", "- **init**\n", "- **load_inputs**\n", - "- **check_inputs**\n", + "- **check_and_preprocess_inputs**\n", "- **add_pre_mission_systems**\n", "- **add_phases**\n", "- **add_post_mission_systems**\n", @@ -260,7 +260,7 @@ "source": [ "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on severity of the issues\n", - "prob.check_inputs()" + "prob.check_and_preprocess_inputs()" ] }, { @@ -630,7 +630,7 @@ "prob = av.AviaryProblem()\n", "\n", "prob.load_inputs(aircraft_definition_file, phase_info)\n", - "prob.check_inputs()\n", + "prob.check_and_preprocess_inputs()\n", "prob.add_pre_mission_systems()\n", "prob.add_phases()\n", "prob.add_post_mission_systems()\n", diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index 30d1e1c7c..e052fd842 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -42,7 +42,7 @@ "\n", "- `prob = AviaryProblem()`\n", "- `prob.load_inputs()`\n", - "- `prob.check_inputs()`\n", + "- `prob.check_and_preprocess_inputs()`\n", "- `prob.add_pre_mission_systems()`\n", "- `prob.add_phases()`\n", "- `prob.add_post_mission_systems()`\n", @@ -94,9 +94,8 @@ "# Allow for user overrides here\n", "prob.load_inputs(aircraft_filename, av.default_2DOF_phase_info)\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", - "prob.check_inputs()\n", + "# Preprocess inputs\n", + "prob.check_and_preprocess_inputs()\n", "\n", "# adds a pre-mission group (propulsion, geometry, static aerodynamics, and mass)\n", "prob.add_pre_mission_systems()\n", @@ -241,7 +240,7 @@ "metadata": {}, "outputs": [], "source": [ - "prob.check_inputs()" + "prob.check_and_preprocess_inputs()" ] }, { @@ -680,9 +679,8 @@ "# Allow for user overrides here\n", "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", - "prob.check_inputs()\n", + "# Preprocess inputs\n", + "prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", @@ -835,9 +833,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", - "prob.check_inputs()\n", + "# Preprocess inputs\n", + "prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index 1f185bb80..bb4141353 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -34,7 +34,7 @@ "In `aviary/validation_cases/benchmark_tests` folder, there is an N3CC aircraft full mission benchmark test `test_FLOPS_based_full_mission_N3CC.py`. Now, we will show how to create an N3CC example in level3. The key is that we follow the same steps:\n", "- init\n", "- load_inputs\n", - "- check_inputs (optional)\n", + "- check_and_preprocess_inputs (optional)\n", "- add_pre_mission_systems\n", "- add_phases\n", "- add_post_mission_systems\n", diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 9a20fd22f..ed3a90000 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -146,8 +146,8 @@ "# Allow for user overrides here\n", "prob.load_inputs(csv_path, phase_info)\n", "\n", - "# Have checks for clashing user inputs\n", - "prob.check_inputs()\n", + + "prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", "\n", diff --git a/aviary/docs/user_guide/subsystems.md b/aviary/docs/user_guide/subsystems.md index 0b19295ed..d5441dbac 100644 --- a/aviary/docs/user_guide/subsystems.md +++ b/aviary/docs/user_guide/subsystems.md @@ -12,7 +12,7 @@ In the following outline, the methods listed at the top-level are defined in `me Any sub-listed method is one that you can provide with your subsystem builder, showing where within the level 3 method hierarchy that subsystem method gets used. - `load_inputs` - loads the aviary_values inputs and options that the user specifies. -- `check_inputs` - checks the user-supplied input values for any potential problems. +- `check_and_preprocess_inputs` - checks the user-supplied input values for any potential problems. - `preprocess_inputs` - `add_pre_mission_systems` - adds pre-mission Systems to the Aviary problem - `get_mass_names` diff --git a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py index 8b8ac8949..064c86985 100644 --- a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py +++ b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py @@ -110,13 +110,13 @@ aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv' make_plots = False -max_iter = 100 -optimizer = 'IPOPT' +max_iter = 1 # set this to a higher number to fully run the optimization +optimizer = 'SLSQP' prob = av.AviaryProblem() prob.load_inputs(aircraft_definition_file, phase_info) -prob.check_inputs() +prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() prob.add_phases() prob.add_post_mission_systems() diff --git a/aviary/examples/external_subsystems/battery/run_cruise.py b/aviary/examples/external_subsystems/battery/run_cruise.py index a0463c89d..44882c487 100644 --- a/aviary/examples/external_subsystems/battery/run_cruise.py +++ b/aviary/examples/external_subsystems/battery/run_cruise.py @@ -16,7 +16,7 @@ # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) prob.add_pre_mission_systems() diff --git a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py index 1cae165e9..975dc7ef5 100644 --- a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py +++ b/aviary/examples/external_subsystems/battery/run_multiphase_mission.py @@ -24,9 +24,9 @@ # Allow for user overrides here prob.load_inputs(input_file, phase_info) -# Have checks for clashing user inputs -# Raise warnings or errors depending on how clashing the issues are -prob.check_inputs() + +# Preprocess inputs +prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() @@ -37,7 +37,7 @@ # Link phases and variables prob.link_phases() -prob.add_driver("SNOPT") +prob.add_driver("SLSQP") prob.add_design_variables() diff --git a/aviary/examples/level2_shooting_traj.py b/aviary/examples/level2_shooting_traj.py index 983f42d6f..0bbd323b5 100644 --- a/aviary/examples/level2_shooting_traj.py +++ b/aviary/examples/level2_shooting_traj.py @@ -36,9 +36,9 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, analysis_scheme=An # Allow for user overrides here prob.load_inputs(aircraft_filename, phase_info) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/examples/test/test_all_examples.py b/aviary/examples/test/test_all_examples.py index 387654108..8393a27c7 100644 --- a/aviary/examples/test/test_all_examples.py +++ b/aviary/examples/test/test_all_examples.py @@ -45,8 +45,9 @@ def setUpClass(cls): This method is called once before starting the tests and is used to populate the 'run_files' attribute with a list of run scripts. """ - cls.base_directory = "../external_subsystems" # Adjust the path as necessary - cls.run_files = cls.find_run_files(cls.base_directory) + base_directory = os.path.join(os.path.dirname( + os.path.dirname(os.path.abspath(__file__))), ".") + cls.run_files = cls.find_run_files(base_directory) @staticmethod def find_run_files(base_dir): diff --git a/aviary/interface/methods_for_level1.py b/aviary/interface/methods_for_level1.py index 0bb4d810c..d5c04a1e9 100644 --- a/aviary/interface/methods_for_level1.py +++ b/aviary/interface/methods_for_level1.py @@ -66,9 +66,9 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, # Allow for user overrides here prob.load_inputs(aircraft_filename, phase_info) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 5227a27ed..8254984e0 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -342,11 +342,10 @@ def _update_metadata_from_subsystems(self): if variable in self.meta_data: self.meta_data.pop(variable) - def check_inputs(self): + def check_and_preprocess_inputs(self): """ - This method checks the user-supplied input values for any potential problems. - These problems include variable names that are not recognized in Aviary, - conflicting options or values, or units mismatching. + This method checks the user-supplied input values for any potential problems + and preprocesses the inputs to prepare them for use in the Aviary problem. """ check_phase_info(self.phase_info, self.mission_method) diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index 59f614e3d..4c5d1bed4 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -74,9 +74,9 @@ def test_post_mission_promotion(self): prob.load_inputs(csv_path, phase_info) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - # prob.check_inputs() + +# Preprocess inputs + # prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index 812410958..cc49d51f9 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -92,7 +92,7 @@ def test_phase_info_parameterization_gasp(self): prob.load_inputs( "models/small_single_aisle/small_single_aisle_GwGm.csv", phase_info) - prob.check_inputs() + prob.check_and_preprocess_inputs() # We can set some crazy vals, since we aren't going to optimize. prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000, 'km') diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 0f0fce3b5..d3e41caf2 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -19,7 +19,7 @@ def test_post_mission_promotion(self): prob = AviaryProblem() prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) - prob.check_inputs() + prob.check_and_preprocess_inputs() # TODO: This needs to be converted into a reserve and a scaler so that it can # be given proper units. @@ -52,7 +52,7 @@ def test_gasp_relative_reserve(self): prob.load_inputs( "models/small_single_aisle/small_single_aisle_GwGm.csv", phase_info) - prob.check_inputs() + prob.check_and_preprocess_inputs() prob.aviary_inputs.set_val(Mission.Summary.GROSS_MASS, 140000.0, units='lbm') diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index ac78f16d8..40f7a9393 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -114,6 +114,79 @@ def test_solved_aero_pass_polar(self): assert_near_equal(CL_pass, CL_base, 1e-6) assert_near_equal(CD_pass, CD_base, 1e-6) + def test_solved_aero_pass_polar_unique_abscissa(self): + # Solved Aero with shortened lists of table abscissa. + local_phase_info = deepcopy(phase_info) + + prob = AviaryProblem() + + csv_path = "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv" + prob.load_inputs(csv_path, local_phase_info) + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + prob.link_phases() + + prob.setup() + + prob.set_initial_guesses() + + prob.run_model() + + CL_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") + CD_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") + + # Lift and Drag polars passed from external component in static. + + ph_in = deepcopy(phase_info) + + alt = np.array([0., 3000., 6000., 9000., 12000., 15000., 18000., 21000., + 24000., 27000., 30000., 33000., 36000., 38000., 42000.]) + mach = np.array([0., 0.2, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8, 0.85, 0.9]) + alpha = np.array([-2., 0., 2., 4., 6., 8., 10.]) + + polar_builder = FakeDragPolarBuilder(name="aero", altitude=alt, mach=mach, + alpha=alpha) + aero_data = NamedValues() + aero_data.set_val('altitude', alt, 'ft') + aero_data.set_val('mach', mach, 'unitless') + aero_data.set_val('angle_of_attack', alpha, 'deg') + + subsystem_options = {'method': 'solved_alpha', + 'aero_data': aero_data, + 'training_data': True} + ph_in['pre_mission']['external_subsystems'] = [polar_builder] + + ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} + + prob = AviaryProblem() + + prob.load_inputs(csv_path, ph_in) + + prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, + np.zeros_like(CL), units='unitless') + prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, + np.zeros_like(CD), units='unitless') + + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + prob.link_phases() + + prob.setup() + + prob.set_initial_guesses() + + prob.run_model() + + CL_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") + CD_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") + + assert_near_equal(CL_pass, CL_base, 1e-6) + assert_near_equal(CD_pass, CD_base, 1e-6) + class FakeCalcDragPolar(om.ExplicitComponent): """ diff --git a/aviary/subsystems/aerodynamics/gasp_based/table_based.py b/aviary/subsystems/aerodynamics/gasp_based/table_based.py index c9fc4d397..d333fe16f 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/table_based.py +++ b/aviary/subsystems/aerodynamics/gasp_based/table_based.py @@ -588,11 +588,12 @@ def _structure_special_grid(aero_data): # units don't matter, not using values aoa = aero_data.get_val('angle_of_attack', 'deg') - # special case alpha - this format saturates alpha at its max - # get unique alphas at zero alt mach 0, should cover the full range - # TODO this does not work with data that is already in structured grid format - mask = (data[0] == x0[0]) & (data[1] == x1[0]) - aoa = np.unique(aoa[mask]) + if data[0].shape[0] > x0.shape[0]: + # special case alpha - this format saturates alpha at its max + # get unique alphas at zero alt mach 0, should cover the full range + mask = (data[0] == x0[0]) & (data[1] == x1[0]) + aoa = np.unique(aoa[mask]) + _, _, aoa = np.meshgrid(x0, x1, aoa) # put the aoa data back in the NamedValues object diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index 93464c6f8..c1756d749 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -167,9 +167,9 @@ def test_custom_engine(self): prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info, engine_builder=SimpleTestEngine()) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/subsystems/test/test_external_subsystem_bus.py b/aviary/subsystems/test/test_external_subsystem_bus.py index 24f9dd4ba..68f3f82b0 100644 --- a/aviary/subsystems/test/test_external_subsystem_bus.py +++ b/aviary/subsystems/test/test_external_subsystem_bus.py @@ -90,9 +90,8 @@ def test_external_subsystem_bus(self): prob = AviaryProblem() - prob.load_inputs( - "models/test_aircraft/aircraft_for_bench_FwFm_simple.csv", phase_info) - prob.check_inputs() + prob.load_inputs("models/test_aircraft/aircraft_for_bench_FwFm.csv", phase_info) + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() prob.add_phases() diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 0423ac7de..d8fe2c56e 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -18,7 +18,7 @@ def build_and_run_problem(self, input_filename, phase_info, objective_type=None) prob.load_inputs(input_filename, phase_info) - prob.check_inputs() + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() prob.add_phases() prob.add_post_mission_systems() diff --git a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py index a479d8077..d194d8c5c 100644 --- a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py +++ b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_level3.py @@ -26,9 +26,9 @@ def bench_test_solved_full_mission(self): prob.load_inputs(input_file, local_phase_info) prob.aviary_inputs.set_val(Mission.Design.RANGE, 2000.0, units="NM") - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index cd760af1f..2b9c8ab3a 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -58,9 +58,9 @@ def test_subsystems_in_a_mission(self): prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() @@ -106,9 +106,9 @@ def test_bad_initial_guess_key(self): prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) - # Have checks for clashing user inputs - # Raise warnings or errors depending on how clashing the issues are - prob.check_inputs() + +# Preprocess inputs + prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() From 8b61a46bd4e60799c0b3d3094bd4817ab436a991 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 12 Jan 2024 11:19:04 -0600 Subject: [PATCH 035/111] Filter out Dymos solver warnings --- aviary/interface/methods_for_level2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 8254984e0..8a710ea6e 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -1841,6 +1841,7 @@ def setup(self, **kwargs): set_aviary_initial_values( self.model, self.aviary_inputs, meta_data=self.meta_data) + warnings.simplefilter("ignore", om.OpenMDAOWarning) warnings.simplefilter("ignore", om.PromotionWarning) super().setup(**kwargs) From ffd4a6e5b19a3a1d882918b204c6dc771edc2b61 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 12:58:06 -0500 Subject: [PATCH 036/111] More print statements to help debug --- aviary/visualization/dashboard.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index aa1ebf8e2..af53b6dd1 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -311,6 +311,12 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): """ reports_dir = f"reports/{script_name}/" + print("reports contents") + reports_dir_contents = os.listdir("reports") + for item in reports_dir_contents: + print(item) + print("end reports contents") + if not Path(reports_dir).is_dir(): raise ValueError( f"The script name, '{script_name}', does not have a reports folder associated with it. " From ebbaea637f5d6b62a4b8c6d42a094a51cde83fa1 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 13:20:14 -0500 Subject: [PATCH 037/111] More debug prints --- aviary/interface/test/test_simple_mission.py | 6 ++++++ aviary/visualization/dashboard.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 403c8542e..d78a8dfeb 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -116,6 +116,12 @@ def run_mission(self, phase_info, optimizer): def test_mission_basic_and_dashboard(self): prob = self.run_mission(self.phase_info, "SLSQP") + import os + print(f"pwd = {os.pwd()}") + files = os.listdir() + for file in files: + print(file) + self.assertIsNotNone(prob) self.assertFalse(prob.failed) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index af53b6dd1..49ea7f207 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -311,6 +311,9 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): """ reports_dir = f"reports/{script_name}/" + import os + print(f"pwd = {os.pwd()}") + print("reports contents") reports_dir_contents = os.listdir("reports") for item in reports_dir_contents: From f554b104b477b39ff91d799cd549c80260fdbc01 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 13:29:57 -0500 Subject: [PATCH 038/111] used wrong os function --- aviary/interface/test/test_simple_mission.py | 2 +- aviary/visualization/dashboard.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index d78a8dfeb..a011641de 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -117,7 +117,7 @@ def run_mission(self, phase_info, optimizer): def test_mission_basic_and_dashboard(self): prob = self.run_mission(self.phase_info, "SLSQP") import os - print(f"pwd = {os.pwd()}") + print(f"pwd = {os.cwd()}") files = os.listdir() for file in files: print(file) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index 49ea7f207..a500b2992 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -312,7 +312,7 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): reports_dir = f"reports/{script_name}/" import os - print(f"pwd = {os.pwd()}") + print(f"pwd = {os.cwd()}") print("reports contents") reports_dir_contents = os.listdir("reports") From 3ac6247ac28be3a41f22f7aff67f94414a47fe8b Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 13:48:11 -0500 Subject: [PATCH 039/111] used wrong os function --- aviary/interface/test/test_simple_mission.py | 2 +- aviary/visualization/dashboard.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index a011641de..fbe7e66ca 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -117,7 +117,7 @@ def run_mission(self, phase_info, optimizer): def test_mission_basic_and_dashboard(self): prob = self.run_mission(self.phase_info, "SLSQP") import os - print(f"pwd = {os.cwd()}") + print(f"pwd = {os.getcwd()}") files = os.listdir() for file in files: print(file) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index a500b2992..27137ccfd 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -312,7 +312,7 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): reports_dir = f"reports/{script_name}/" import os - print(f"pwd = {os.cwd()}") + print(f"pwd = {os.getcwd()}") print("reports contents") reports_dir_contents = os.listdir("reports") From 4dfbc2b14e671ddbff09b8c8fe5ed198880d2bf6 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 12 Jan 2024 12:56:36 -0600 Subject: [PATCH 040/111] Tests and benches pass --- aviary/interface/methods_for_level2.py | 32 ++++++++++++++----- .../flops_based/phases/simplified_landing.py | 4 +-- .../flops_based/phases/simplified_takeoff.py | 10 +++++- .../benchmark_tests/test_bench_FwFm.py | 8 ++--- .../benchmark_tests/test_bench_GwFm.py | 5 +-- aviary/variable_info/variable_meta_data.py | 12 +++++++ aviary/variable_info/variables.py | 1 + 7 files changed, 52 insertions(+), 20 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 8a710ea6e..70bbfb7d3 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2382,17 +2382,33 @@ def _add_flops_landing_systems(self): 'traj.climb.initial_states:mass') self.model.connect(Mission.Takeoff.GROUND_DISTANCE, 'traj.climb.initial_states:range') - # TODO: connect this correctly - # mass is the most important to connect but these others should - # be connected as well - # self.model.connect(Mission.Takeoff.FINAL_VELOCITY, - # 'traj.climb.initial_states:mach') - # self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - # 'traj.climb.controls:altitude') + + # Create an ExecComp to compute the difference in mach + mach_diff_comp = om.ExecComp('mach_difference = final_mach - initial_mach') + self.model.add_subsystem('mach_diff_comp', mach_diff_comp) + + # Connect the inputs to the mach difference component + self.model.connect(Mission.Takeoff.FINAL_MACH, 'mach_diff_comp.final_mach') + self.model.connect('traj.climb.control_values:mach', + 'mach_diff_comp.initial_mach', src_indices=[0]) + + # Add constraint for mach difference + self.model.add_constraint('mach_diff_comp.mach_difference', equals=0.0) + + # Similar steps for altitude difference + alt_diff_comp = om.ExecComp( + 'altitude_difference = final_altitude - initial_altitude', units='ft') + self.model.add_subsystem('alt_diff_comp', alt_diff_comp) + + self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, + 'alt_diff_comp.final_altitude') + self.model.connect('traj.climb.control_values:altitude', + 'alt_diff_comp.initial_altitude', src_indices=[0]) + + self.model.add_constraint('alt_diff_comp.altitude_difference', equals=0.0) self.model.connect('traj.descent.states:mass', Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - # TODO: approach velocity should likely be connected self.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE, src_indices=[0]) diff --git a/aviary/mission/flops_based/phases/simplified_landing.py b/aviary/mission/flops_based/phases/simplified_landing.py index 07391f77a..5e893b693 100644 --- a/aviary/mission/flops_based/phases/simplified_landing.py +++ b/aviary/mission/flops_based/phases/simplified_landing.py @@ -117,10 +117,10 @@ def setup(self): self.add_subsystem( "calcs", LandingCalc(), + promotes_inputs=[Mission.Landing.TOUCHDOWN_MASS, "rho", + Aircraft.Wing.AREA, Mission.Landing.LIFT_COEFFICIENT_MAX], promotes_outputs=[ Mission.Landing.GROUND_DISTANCE, Mission.Landing.INITIAL_VELOCITY, ], - promotes_inputs=[Mission.Landing.TOUCHDOWN_MASS, "rho", - Aircraft.Wing.AREA, Mission.Landing.LIFT_COEFFICIENT_MAX], ) diff --git a/aviary/mission/flops_based/phases/simplified_takeoff.py b/aviary/mission/flops_based/phases/simplified_takeoff.py index 2f7848a8c..95d761a2d 100644 --- a/aviary/mission/flops_based/phases/simplified_takeoff.py +++ b/aviary/mission/flops_based/phases/simplified_takeoff.py @@ -379,7 +379,7 @@ def setup(self): "USatm", USatm1976Comp(num_nodes=1), promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], - promotes_outputs=["rho"], + promotes_outputs=["rho", ("sos", "speed_of_sound")], ) self.add_subsystem( @@ -417,3 +417,11 @@ def setup(self): Mission.Takeoff.FINAL_ALTITUDE, ], ) + + self.add_subsystem('compute_mach', om.ExecComp('final_mach = final_velocity / speed_of_sound', + final_mach={'units': 'unitless'}, + final_velocity={'units': 'm/s'}, + speed_of_sound={'units': 'm/s'}), + promotes_inputs=[('speed_of_sound', 'speed_of_sound'), + ('final_velocity', Mission.Takeoff.FINAL_VELOCITY)], + promotes_outputs=[('final_mach', Mission.Takeoff.FINAL_MACH)]) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 22aa5a384..803449af0 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -1,4 +1,3 @@ -from copy import deepcopy import unittest import numpy as np @@ -7,7 +6,6 @@ from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values -from aviary.variable_info.variables import Dynamic @use_tempdirs @@ -268,7 +266,7 @@ def bench_test_swap_4_FwFm(self): "climb": { "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, "user_options": { - 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.RANGE: False}, + 'fix_initial': False, 'input_initial': True, "optimize_mach": True, "optimize_altitude": True, @@ -279,7 +277,7 @@ def bench_test_swap_4_FwFm(self): "initial_mach": (0.2, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.1, 0.8), "unitless"), - "initial_altitude": (0.0, "ft"), + "initial_altitude": (35., "ft"), "final_altitude": (35000.0, "ft"), "altitude_bounds": ((0.0, 36000.0), "ft"), "throttle_enforcement": "path_constraint", @@ -350,7 +348,7 @@ def bench_test_swap_4_FwFm(self): } prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) + 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info, max_iter=100) compare_against_expected_values(prob, self.expected_dict) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index ad785f4d8..166e19ca4 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -5,7 +5,6 @@ Computed Aero Large Single Aisle 1 data ''' -from copy import deepcopy import unittest import numpy as np @@ -14,8 +13,6 @@ from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ compare_against_expected_values -from aviary.variable_info.variables import Dynamic -from aviary.interface.default_phase_info.height_energy import phase_info @use_tempdirs @@ -275,7 +272,7 @@ def bench_test_swap_1_GwFm(self): "climb": { "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, "user_options": { - 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.RANGE: False}, + 'fix_initial': False, 'input_initial': True, "optimize_mach": True, "optimize_altitude": True, diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 94d66ccdc..12bd99eee 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -7067,6 +7067,18 @@ default_value=35.0, ) +add_meta_data( + Mission.Takeoff.FINAL_MACH, + meta_data=_MetaData, + historical_name={"GASP": None, + "FLOPS": None, + "LEAPS1": None, + }, + units='unitless', + desc='Mach number of aircraft after taking off and ' + 'clearing a 35 foot obstacle' +) + add_meta_data( Mission.Takeoff.FINAL_MASS, meta_data=_MetaData, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index a64d774f4..35efb7501 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -709,6 +709,7 @@ class Takeoff: DRAG_COEFFICIENT_MIN = 'mission:takeoff:drag_coefficient_min' FIELD_LENGTH = 'mission:takeoff:field_length' FINAL_ALTITUDE = 'mission:takeoff:final_altitude' + FINAL_MACH = 'mission:takeoff:final_mach' FINAL_MASS = 'mission:takeoff:final_mass' FINAL_VELOCITY = 'mission:takeoff:final_velocity' FUEL_SIMPLE = 'mission:takeoff:fuel_simple' From bf53319aaf7152c28663781da59b60970473fb79 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 12 Jan 2024 12:59:55 -0600 Subject: [PATCH 041/111] Removed defunct variable in takeoff --- .../mission/flops_based/phases/simplified_takeoff.py | 12 ------------ .../phases/test/test_simplified_takeoff.py | 4 ---- .../models/test_aircraft/aircraft_for_bench_FwFm.csv | 1 - .../models/test_aircraft/aircraft_for_bench_GwFm.csv | 1 - 4 files changed, 18 deletions(-) diff --git a/aviary/mission/flops_based/phases/simplified_takeoff.py b/aviary/mission/flops_based/phases/simplified_takeoff.py index 95d761a2d..5060f0c04 100644 --- a/aviary/mission/flops_based/phases/simplified_takeoff.py +++ b/aviary/mission/flops_based/phases/simplified_takeoff.py @@ -103,12 +103,6 @@ def setup(self): add_aviary_input(self, Mission.Takeoff.LIFT_OVER_DRAG, val=2) - # we don't actually need this? It seems like we should from the equation in the - # paper, but we are using the equation from LEAPS1 because it doesn't require L - # or D - add_aviary_input(self, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, - val=0.00175) - add_aviary_output(self, Mission.Takeoff.GROUND_DISTANCE, val=0) add_aviary_output(self, Mission.Takeoff.FINAL_VELOCITY, @@ -133,7 +127,6 @@ def setup_partials(self): Aircraft.Wing.AREA, Mission.Takeoff.LIFT_COEFFICIENT_MAX, Mission.Design.THRUST_TAKEOFF_PER_ENG, - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, Mission.Takeoff.LIFT_OVER_DRAG, ], ) @@ -160,7 +153,6 @@ def compute(self, inputs, outputs): Cl_max = inputs[Mission.Takeoff.LIFT_COEFFICIENT_MAX] thrust = inputs[Mission.Design.THRUST_TAKEOFF_PER_ENG] L_over_D = inputs[Mission.Takeoff.LIFT_OVER_DRAG] - mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] num_engines = self.options['num_engines'] rho_ratio = rho / rho_SL @@ -205,17 +197,14 @@ def compute(self, inputs, outputs): outputs[Mission.Takeoff.FINAL_ALTITUDE] = 35 def compute_partials(self, inputs, J): - rho_SL = RHO_SEA_LEVEL_METRIC - v_stall = inputs["v_stall"] ramp_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM rho = inputs["rho"] S = inputs[Aircraft.Wing.AREA] Cl_max = inputs[Mission.Takeoff.LIFT_COEFFICIENT_MAX] thrust = inputs[Mission.Design.THRUST_TAKEOFF_PER_ENG] L_over_D = inputs[Mission.Takeoff.LIFT_OVER_DRAG] - mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] num_engines = self.options['num_engines'] rho_ratio = rho / rho_SL @@ -408,7 +397,6 @@ def setup(self): Mission.Takeoff.LIFT_COEFFICIENT_MAX, Mission.Design.THRUST_TAKEOFF_PER_ENG, Mission.Takeoff.LIFT_OVER_DRAG, - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, ], promotes_outputs=[ Mission.Takeoff.GROUND_DISTANCE, diff --git a/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py b/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py index c011af727..472a5bcc0 100644 --- a/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py +++ b/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py @@ -91,8 +91,6 @@ def setUp(self): Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units="lbf") # check self.prob.model.set_input_defaults( Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless') # check - self.prob.model.set_input_defaults( - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=0.0175, units='unitless') # check self.prob.setup(check=False, force_alloc_complex=True) @@ -145,8 +143,6 @@ def setUp(self): Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units="lbf") # check self.prob.model.set_input_defaults( Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless') # check - self.prob.model.set_input_defaults( - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=0.0175, units='unitless') # check self.prob.model.set_input_defaults( Dynamic.Mission.ALTITUDE, val=0, units="ft") # check diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv index 2d4ea4703..925e6aed6 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv @@ -154,6 +154,5 @@ mission:summary:fuel_flow_scaler,1.0,unitless mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless settings:equations_of_motion,height_energy settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 5c0d0b8a0..c59731257 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -268,6 +268,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless settings:equations_of_motion,height_energy settings:mass_method,GASP \ No newline at end of file From 677cfce633f214831fb2924ada122bec8ae21d0d Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 14:30:26 -0500 Subject: [PATCH 042/111] Added more prints --- aviary/interface/test/test_simple_mission.py | 6 +++++- aviary/visualization/dashboard.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index fbe7e66ca..f1b3b6f81 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -117,10 +117,14 @@ def run_mission(self, phase_info, optimizer): def test_mission_basic_and_dashboard(self): prob = self.run_mission(self.phase_info, "SLSQP") import os - print(f"pwd = {os.getcwd()}") + import sys + print( + f"in test_mission_basic_and_dashboard pwd = {os.getcwd()}", file=sys.stderr) + print("in current directory these are the files") files = os.listdir() for file in files: print(file) + print("end of current directory files") self.assertIsNotNone(prob) self.assertFalse(prob.failed) diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index 27137ccfd..7b1a49b52 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -312,7 +312,7 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): reports_dir = f"reports/{script_name}/" import os - print(f"pwd = {os.getcwd()}") + print(f"in dashboard pwd = {os.getcwd()}") print("reports contents") reports_dir_contents = os.listdir("reports") From e5cdf1a5b3b261424b3ccbb975ae2e5e58168241 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 14:38:46 -0500 Subject: [PATCH 043/111] Added tmate session to workflow temporarily --- .github/workflows/test_workflow.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 3edbe2f3e..436b1947c 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,6 +213,10 @@ jobs: python run_all.py cd ../.. + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + + - name: Run tests if: matrix.MAKE_DOCS == 0 shell: bash -l {0} From 3c80a2400084442612746e9c7f067923b0c06bb4 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 12 Jan 2024 15:54:14 -0500 Subject: [PATCH 044/111] allow L2 interface to accept AviaryValues objects --- aviary/api.py | 1 + aviary/interface/methods_for_level2.py | 17 +++++++--- aviary/utils/process_input_decks.py | 46 ++++++++++++++++---------- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/aviary/api.py b/aviary/api.py index 9bd1e7104..81b1fafc0 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -149,5 +149,6 @@ from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder # Testing +# NOTE these load every FLOPS validation test case, every Avairy run from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import FLOPS_Test_Data diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 9285db939..cf76e4326 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -42,7 +42,7 @@ from aviary.subsystems.premission import CorePreMission from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution from aviary.utils.functions import set_aviary_initial_values, Null, create_opts2vals, add_opts2vals, promote_aircraft_and_mission_vars -from aviary.utils.process_input_decks import create_vehicle +from aviary.utils.process_input_decks import create_vehicle, update_GASP_options from aviary.utils.preprocessors import preprocess_crewpayload from aviary.interface.utils.check_phase_info import check_phase_info from aviary.utils.aviary_values import AviaryValues @@ -150,7 +150,7 @@ def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): self.analysis_scheme = analysis_scheme - def load_inputs(self, input_filename, phase_info=None, engine_builder=None): + def load_inputs(self, aviary_inputs, phase_info=None, engine_builder=None): """ This method loads the aviary_values inputs and options that the user specifies. They could specify files to load and values to @@ -163,14 +163,23 @@ def load_inputs(self, input_filename, phase_info=None, engine_builder=None): """ ## LOAD INPUT FILE ### self.engine_builder = engine_builder - self.aviary_inputs, self.initial_guesses = create_vehicle(input_filename) - aviary_inputs = self.aviary_inputs + # Create AviaryValues object from file (or process existing AviaryValues object + # with default values from metadata) and generate initial guesses + aviary_inputs, initial_guesses = create_vehicle(aviary_inputs) + # aviary_inputs = self.aviary_inputs + # pull which methods will be used for subsystems and mission self.mission_method = mission_method = aviary_inputs.get_val( Settings.EQUATIONS_OF_MOTION) self.mass_method = mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) + if mission_method is TWO_DEGREES_OF_FREEDOM or mass_method is GASP: + aviary_inputs, initial_guesses = update_GASP_options(aviary_inputs, + initial_guesses) + self.aviary_inputs = aviary_inputs + self.initial_guesses = initial_guesses + if mission_method is TWO_DEGREES_OF_FREEDOM: aviary_inputs.set_val(Mission.Summary.CRUISE_MASS_FINAL, val=self.initial_guesses['cruise_mass_final'], units='lbm') diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 3705f18c7..840d254f6 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -51,21 +51,14 @@ def create_vehicle(vehicle_deck=''): """ aircraft_values = get_option_defaults(engine=False) - # TODO remove all hardcoded GASP values here, find appropriate place for them + # TODO temporary, needed until debug_mode retired in favor of new verbosity flag aircraft_values.set_val('debug_mode', val=False) - aircraft_values.set_val('INGASP.JENGSZ', val=4) - aircraft_values.set_val('test_mode', val=False) - aircraft_values.set_val('use_surrogates', val=True) - aircraft_values.set_val('mass_defect', val=10000, units='lbm') - aircraft_values.set_val('problem_type', val=ProblemType.SIZING) - aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - aircraft_values.set_val(Aircraft.Design.RESERVES, val=4998) - vehicle_deck = get_path(vehicle_deck) - - parse_inputs(vehicle_deck, aircraft_values) - # update the dependent options with the current values - update_options(aircraft_values, initial_guesses) + if isinstance(vehicle_deck, AviaryValues): + aircraft_values.update(vehicle_deck) + else: + vehicle_deck = get_path(vehicle_deck) + parse_inputs(vehicle_deck, aircraft_values) return aircraft_values, initial_guesses @@ -120,7 +113,7 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues(), meta_data=_MetaD aircraft_values = set_value(var_name, var_values, aircraft_values) continue - elif var_name in meta_data.keys(): + if var_name in meta_data.keys(): aircraft_values = set_value( var_name, var_values, aircraft_values, units=data_units, is_array=is_array, meta_data=meta_data) continue @@ -135,8 +128,11 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues(), meta_data=_MetaD return aircraft_values, initial_guesses +# TODO this should be a preprocessor, and tasks split to be specific to subsystem +# e.g. aero preprocessor, mass preprocessor, 2DOF preprocessor, etc. -def update_options(aircraft_values: AviaryValues(), initial_guesses): + +def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): """ Updates options based on the current values in aircraft_values. This function also handles special cases and prints debug information if the debug mode is active. @@ -150,11 +146,27 @@ def update_options(aircraft_values: AviaryValues(), initial_guesses): ------- tuple: Updated aircraft values and initial guesses. """ + GASP_defaults = AviaryValues() + GASP_defaults.set_val('INGASP.JENGSZ', val=4) + GASP_defaults.set_val('test_mode', val=False) + GASP_defaults.set_val('use_surrogates', val=True) + GASP_defaults.set_val('mass_defect', val=10000, units='lbm') + GASP_defaults.set_val('problem_type', val=ProblemType.SIZING) + GASP_defaults.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) + GASP_defaults.set_val(Aircraft.Design.RESERVES, val=4998) + + # overwrite GASP_defaults with values from aircraft_values, then replace + # aircraft_values with this merged set + GASP_defaults.update(aircraft_values) + aircraft_values = GASP_defaults + + for var in initial_guesses: + if var in aircraft_values: + initial_guesses[var], _ = aircraft_values.get_item(var) + # update the options that depend on variables update_dependent_options(aircraft_values, dependent_options) - # TODO this is GASP only, don't always run it! These should go in a GASP-only options - # preprocessor ## STRUT AND FOLD ## if not aircraft_values.get_val(Aircraft.Wing.HAS_STRUT): aircraft_values.set_val( From 83c3575d6fe546b8ac76dcb3c0d4676a528c27e7 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 17:41:52 -0500 Subject: [PATCH 045/111] remove the tmate session --- .github/workflows/test_workflow.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 436b1947c..3edbe2f3e 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,10 +213,6 @@ jobs: python run_all.py cd ../.. - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - - - name: Run tests if: matrix.MAKE_DOCS == 0 shell: bash -l {0} From 65c0876561c3d251740febf8d0930f0f7cfce9d8 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 12 Jan 2024 17:42:52 -0500 Subject: [PATCH 046/111] removed TESTFLO_RUNNING from the environment when running the dashboard test so the reports would be generated --- aviary/interface/test/test_simple_mission.py | 26 +++++++++----------- aviary/visualization/dashboard.py | 9 ------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index f1b3b6f81..5c951b0ed 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -1,3 +1,4 @@ +import os import unittest from aviary.interface.methods_for_level1 import run_aviary from aviary.subsystems.test.test_dummy_subsystem import ArrayGuessSubsystemBuilder @@ -9,6 +10,7 @@ class AircraftMissionTestSuite(unittest.TestCase): def setUp(self): + # Load the phase_info and other common setup tasks self.phase_info = { "pre_mission": {"include_takeoff": False, "optimize_mass": True}, @@ -115,16 +117,16 @@ def run_mission(self, phase_info, optimizer): optimization_history_filename="driver_test.db") def test_mission_basic_and_dashboard(self): + # We need to remove the TESTFLO_RUNNING environment variable for this test to run. + # The reports code checks to see if TESTFLO_RUNNING is set and will not do anything if set + # But we need to remember whether it was set so we can restore it + testflo_running = os.environ.pop('TESTFLO_RUNNING', None) + prob = self.run_mission(self.phase_info, "SLSQP") - import os - import sys - print( - f"in test_mission_basic_and_dashboard pwd = {os.getcwd()}", file=sys.stderr) - print("in current directory these are the files") - files = os.listdir() - for file in files: - print(file) - print("end of current directory files") + + # restore what was there before running the test + if testflo_running is not None: + os.environ['TESTFLO_RUNNING'] = testflo_running self.assertIsNotNone(prob) self.assertFalse(prob.failed) @@ -136,11 +138,7 @@ def test_mission_basic_and_dashboard(self): try: subprocess.check_output(cmd.split()) except subprocess.CalledProcessError as err: - self.fail("Command '{}' failed. Return code: {} \n output: {} \n stderr: {} \n stdout: {}".format(cmd, - err.returncode, - err.output, - err.stderr, - err.stdout)) + self.fail("Command '{}' failed. Return code: {}".format(cmd, err.returncode)) @require_pyoptsparse(optimizer="IPOPT") def test_mission_basic_pyopt(self): diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index 7b1a49b52..aa1ebf8e2 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -311,15 +311,6 @@ def dashboard(script_name, problem_recorder, driver_recorder, port): """ reports_dir = f"reports/{script_name}/" - import os - print(f"in dashboard pwd = {os.getcwd()}") - - print("reports contents") - reports_dir_contents = os.listdir("reports") - for item in reports_dir_contents: - print(item) - print("end reports contents") - if not Path(reports_dir).is_dir(): raise ValueError( f"The script name, '{script_name}', does not have a reports folder associated with it. " From ddf590761306c0fa491626ad4493dc99a0e7169d Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Tue, 16 Jan 2024 13:22:58 -0500 Subject: [PATCH 047/111] first, tests running as expected --- aviary/interface/methods_for_level2.py | 17 +++++++++-------- aviary/mission/gasp_based/ode/accel_eom.py | 7 ++++--- aviary/mission/gasp_based/ode/accel_ode.py | 2 +- aviary/mission/gasp_based/ode/ascent_eom.py | 11 ++++++----- aviary/mission/gasp_based/ode/climb_eom.py | 15 ++++++++------- aviary/mission/gasp_based/ode/climb_ode.py | 2 +- aviary/mission/gasp_based/ode/descent_eom.py | 16 +++++++++------- aviary/mission/gasp_based/ode/descent_ode.py | 2 +- .../mission/gasp_based/ode/flight_path_eom.py | 11 ++++++----- .../mission/gasp_based/ode/flight_path_ode.py | 2 +- aviary/mission/gasp_based/ode/groundroll_eom.py | 11 ++++++----- aviary/mission/gasp_based/ode/rotation_eom.py | 11 ++++++----- .../gasp_based/ode/test/test_accel_eom.py | 3 ++- .../gasp_based/ode/test/test_climb_eom.py | 3 ++- .../gasp_based/ode/test/test_climb_ode.py | 4 ++-- .../gasp_based/ode/test/test_descent_eom.py | 3 ++- .../gasp_based/ode/test/test_descent_ode.py | 4 ++-- .../gasp_based/phases/2DOF_phase_builder.py | 5 +++-- aviary/mission/gasp_based/phases/accel_phase.py | 2 +- .../mission/gasp_based/phases/ascent_phase.py | 2 +- aviary/mission/gasp_based/phases/climb_phase.py | 2 +- aviary/mission/gasp_based/phases/desc_phase.py | 2 +- .../gasp_based/phases/groundroll_phase.py | 2 +- .../mission/gasp_based/phases/rotation_phase.py | 2 +- .../gasp_based/phases/run_phases/run_accel.py | 3 ++- .../gasp_based/phases/run_phases/run_climb.py | 2 +- .../run_phases/run_climb_test_FLOPS_prop.py | 2 +- .../phases/run_phases/run_groundroll.py | 2 +- .../phases/run_phases/run_rotation.py | 2 +- .../gasp_based/phases/run_phases/run_takeoff.py | 11 ++++++----- .../test_FLOPS_based_sizing_N3CC.py | 6 +++--- aviary/xdsm/accel_xdsm.py | 2 +- aviary/xdsm/climb_xdsm.py | 2 +- aviary/xdsm/descent1_xdsm.py | 2 +- aviary/xdsm/descent2_xdsm.py | 2 +- aviary/xdsm/groundroll_xdsm.py | 2 +- aviary/xdsm/statics_xdsm.py | 16 ++++++++-------- 37 files changed, 105 insertions(+), 90 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index cb9818663..62fee7599 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -1400,7 +1400,7 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): elif self.mission_method is TWO_DEGREES_OF_FREEDOM: if self.analysis_scheme is AnalysisScheme.COLLOCATION: self.traj.link_phases(["groundroll", "rotation", "ascent"], [ - "time", "TAS", "mass", "distance"], connected=True) + "time", "TAS", "mass", Dynamic.Mission.DISTANCE], connected=True) self.traj.link_phases( ["rotation", "ascent"], ["alpha"], connected=False, ref=5e1, @@ -1408,8 +1408,8 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): self.traj.add_linkage_constraint( "ascent", "accel", - "distance", - "distance", + Dynamic.Mission.DISTANCE, + Dynamic.Mission.DISTANCE, "final", "initial", connected=False, @@ -1422,13 +1422,14 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): "time", "mass", "TAS"], connected=True) self.traj.link_phases( phases=["accel", "climb1", "climb2"], - vars=["time", Dynamic.Mission.ALTITUDE, "mass", "distance"], + vars=["time", Dynamic.Mission.ALTITUDE, + "mass", Dynamic.Mission.DISTANCE], connected=True, ) self.traj.link_phases( phases=["desc1", "desc2"], - vars=["time", "mass", "distance"], + vars=["time", "mass", Dynamic.Mission.DISTANCE], connected=True, ) @@ -2063,11 +2064,11 @@ def _add_guesses(self, phase_name, phase, guesses): if self.mission_method is SIMPLE: control_keys = ["mach", "altitude"] - state_keys = ["mass", "range"] + state_keys = ["mass", Dynamic.Mission.RANGE] else: control_keys = ["velocity_rate", "throttle"] state_keys = ["altitude", "velocity", "mass", - "range", "TAS", "distance", "flight_path_angle", "alpha"] + Dynamic.Mission.RANGE, "TAS", Dynamic.Mission.DISTANCE, "flight_path_angle", "alpha"] if self.mission_method is TWO_DEGREES_OF_FREEDOM and phase_name == 'ascent': # Alpha is a control for ascent. control_keys.append('alpha') @@ -2171,7 +2172,7 @@ def _add_guesses(self, phase_name, phase, guesses): # Set the distance guesses as the initial values for the distance state variable self.set_val( f"traj.{phase_name}.states:distance", phase.interp( - "distance", ys=ys) + Dynamic.Mission.DISTANCE, ys=ys) ) def _add_solved_guesses(self, idx, phase_name, phase): diff --git a/aviary/mission/gasp_based/ode/accel_eom.py b/aviary/mission/gasp_based/ode/accel_eom.py index ca8939964..db3adba94 100644 --- a/aviary/mission/gasp_based/ode/accel_eom.py +++ b/aviary/mission/gasp_based/ode/accel_eom.py @@ -56,7 +56,7 @@ def setup(self): desc="rate of change of true air speed", ) self.add_output( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units="ft/s", desc="rate of change of horizontal distance covered", @@ -65,7 +65,8 @@ def setup(self): self.declare_partials( "TAS_rate", [ Dynamic.Mission.MASS, Dynamic.Mission.DRAG, Dynamic.Mission.THRUST_TOTAL], rows=arange, cols=arange) - self.declare_partials("distance_rate", ["TAS"], rows=arange, cols=arange, val=1.) + self.declare_partials(Dynamic.Mission.DISTANCE_RATE, [ + "TAS"], rows=arange, cols=arange, val=1.) if analysis_scheme is AnalysisScheme.SHOOTING: self.add_input("t_curr", val=np.ones(nn), desc="time", units="s") @@ -83,7 +84,7 @@ def compute(self, inputs, outputs): TAS = inputs["TAS"] outputs["TAS_rate"] = (GRAV_ENGLISH_GASP / weight) * (thrust - drag) - outputs["distance_rate"] = TAS + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS if analysis_scheme is AnalysisScheme.SHOOTING: outputs[Dynamic.Mission.ALTITUDE_RATE] = 0 diff --git a/aviary/mission/gasp_based/ode/accel_ode.py b/aviary/mission/gasp_based/ode/accel_ode.py index eae09fe28..4eac3fe2a 100644 --- a/aviary/mission/gasp_based/ode/accel_ode.py +++ b/aviary/mission/gasp_based/ode/accel_ode.py @@ -89,7 +89,7 @@ def setup(self): + sgm_inputs, promotes_outputs=[ "TAS_rate", - "distance_rate", ] + Dynamic.Mission.DISTANCE_RATE, ] + sgm_outputs, ) diff --git a/aviary/mission/gasp_based/ode/ascent_eom.py b/aviary/mission/gasp_based/ode/ascent_eom.py index aea1ab632..212354599 100644 --- a/aviary/mission/gasp_based/ode/ascent_eom.py +++ b/aviary/mission/gasp_based/ode/ascent_eom.py @@ -49,7 +49,7 @@ def setup(self): desc="altitude rate", units="ft/s") self.add_output( - "distance_rate", val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" ) self.add_output( "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" @@ -102,7 +102,7 @@ def setup_partials(self): Dynamic.Mission.ALTITUDE_RATE, [ "TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) self.declare_partials( - "distance_rate", ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange ) self.declare_partials( "normal_force", @@ -156,7 +156,7 @@ def compute(self, inputs, outputs): ) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["normal_force"] = normal_force outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha @@ -281,8 +281,9 @@ def compute_partials(self, inputs, J): J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift diff --git a/aviary/mission/gasp_based/ode/climb_eom.py b/aviary/mission/gasp_based/ode/climb_eom.py index 436fd6fc2..50a06bab6 100644 --- a/aviary/mission/gasp_based/ode/climb_eom.py +++ b/aviary/mission/gasp_based/ode/climb_eom.py @@ -53,7 +53,7 @@ def setup(self): desc="rate of change of altitude", ) self.add_output( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units="ft/s", desc="rate of change of horizontal distance covered", @@ -79,7 +79,7 @@ def setup(self): rows=arange, cols=arange) self.declare_partials( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, Dynamic.Mission.MASS], rows=arange, cols=arange, @@ -113,7 +113,7 @@ def compute(self, inputs, outputs): gamma = np.arcsin((thrust - drag) / weight) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["required_lift"] = weight * np.cos(gamma) outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = gamma @@ -142,11 +142,12 @@ def compute_partials(self, inputs, J): J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.MASS] = \ TAS * np.cos(gamma) * dGamma_dWeight * GRAV_ENGLISH_LBM - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.THRUST_TOTAL] = - \ + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.THRUST_TOTAL] = - \ TAS * np.sin(gamma) * dGamma_dThrust - J["distance_rate", Dynamic.Mission.DRAG] = -TAS * np.sin(gamma) * dGamma_dDrag - J["distance_rate", Dynamic.Mission.MASS] = \ + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.DRAG] = - \ + TAS * np.sin(gamma) * dGamma_dDrag + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.MASS] = \ -TAS * np.sin(gamma) * dGamma_dWeight * GRAV_ENGLISH_LBM J["required_lift", Dynamic.Mission.MASS] = ( diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index e9182e92b..da51cccba 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -191,7 +191,7 @@ def setup(self): integration_states, promotes_outputs=[ Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "required_lift", Dynamic.Mission.FLIGHT_PATH_ANGLE, ], diff --git a/aviary/mission/gasp_based/ode/descent_eom.py b/aviary/mission/gasp_based/ode/descent_eom.py index 32a37c0bc..02e9ee5bc 100644 --- a/aviary/mission/gasp_based/ode/descent_eom.py +++ b/aviary/mission/gasp_based/ode/descent_eom.py @@ -51,7 +51,7 @@ def setup(self): desc="rate of change of altitude", ) self.add_output( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units="ft/s", desc="rate of change of horizontal distance covered", @@ -77,7 +77,7 @@ def setup(self): rows=arange, cols=arange) self.declare_partials( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, Dynamic.Mission.MASS], rows=arange, cols=arange, @@ -112,7 +112,7 @@ def compute(self, inputs, outputs): gamma = (thrust - drag) / weight outputs[Dynamic.Mission.ALTITUDE_RATE] = alt_rate = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["required_lift"] = weight * np.cos(gamma) - thrust * np.sin(alpha) outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = gamma @@ -134,10 +134,12 @@ def compute_partials(self, inputs, J): J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.MASS] = TAS * \ np.cos(gamma) * (-(thrust - drag) / weight**2) * GRAV_ENGLISH_LBM - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.THRUST_TOTAL] = -TAS * np.sin(gamma) / weight - J["distance_rate", Dynamic.Mission.DRAG] = -TAS * np.sin(gamma) * (-1 / weight) - J["distance_rate", Dynamic.Mission.MASS] = ( + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.THRUST_TOTAL] = - \ + TAS * np.sin(gamma) / weight + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.DRAG] = - \ + TAS * np.sin(gamma) * (-1 / weight) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.MASS] = ( -TAS * np.sin(gamma) * (-(thrust - drag) / weight**2) * GRAV_ENGLISH_LBM ) diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index 3257fbb14..1e8eac07d 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -181,7 +181,7 @@ def setup(self): integration_states, promotes_outputs=[ Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "required_lift", Dynamic.Mission.FLIGHT_PATH_ANGLE, ], diff --git a/aviary/mission/gasp_based/ode/flight_path_eom.py b/aviary/mission/gasp_based/ode/flight_path_eom.py index 7eb2e7624..57f1ae6a2 100644 --- a/aviary/mission/gasp_based/ode/flight_path_eom.py +++ b/aviary/mission/gasp_based/ode/flight_path_eom.py @@ -80,7 +80,7 @@ def setup(self): self.add_input("alpha", val=np.ones(nn), desc="angle of attack", units="deg") self.add_output( - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s", @@ -157,7 +157,7 @@ def setup_partials(self): ) self.declare_partials( - "distance_rate", ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange ) # self.declare_partials("alpha_rate", ["*"], val=0.0) self.declare_partials( @@ -211,7 +211,7 @@ def compute(self, inputs, outputs): ) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["normal_force"] = normal_force @@ -343,8 +343,9 @@ def compute_partials(self, inputs, J): J["load_factor", Aircraft.Wing.INCIDENCE] = dTAcF_dIwing / \ (weight * np.cos(gamma)) - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift diff --git a/aviary/mission/gasp_based/ode/flight_path_ode.py b/aviary/mission/gasp_based/ode/flight_path_ode.py index 64542100b..e70ddb8d0 100644 --- a/aviary/mission/gasp_based/ode/flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/flight_path_ode.py @@ -198,7 +198,7 @@ def setup(self): promotes_inputs=EOM_inputs, promotes_outputs=[ "TAS_rate", - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "normal_force", "fuselage_pitch", "load_factor", diff --git a/aviary/mission/gasp_based/ode/groundroll_eom.py b/aviary/mission/gasp_based/ode/groundroll_eom.py index 34643768e..610c818b6 100644 --- a/aviary/mission/gasp_based/ode/groundroll_eom.py +++ b/aviary/mission/gasp_based/ode/groundroll_eom.py @@ -39,7 +39,7 @@ def setup(self): self.add_output(Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), desc="altitude rate", units="ft/s") self.add_output( - "distance_rate", val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" ) self.add_output( "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" @@ -60,7 +60,7 @@ def setup(self): self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, [ "TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) self.declare_partials( - "distance_rate", ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange ) self.declare_partials( "normal_force", @@ -121,7 +121,7 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = np.zeros(nn) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["normal_force"] = normal_force outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha @@ -204,8 +204,9 @@ def compute_partials(self, inputs, J): J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift diff --git a/aviary/mission/gasp_based/ode/rotation_eom.py b/aviary/mission/gasp_based/ode/rotation_eom.py index c42d922e7..f721a86e0 100644 --- a/aviary/mission/gasp_based/ode/rotation_eom.py +++ b/aviary/mission/gasp_based/ode/rotation_eom.py @@ -39,7 +39,7 @@ def setup(self): self.add_output(Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), desc="altitude rate", units="ft/s") self.add_output( - "distance_rate", val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" ) self.add_output( "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" @@ -74,7 +74,7 @@ def setup_partials(self): self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, [ "TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) self.declare_partials( - "distance_rate", ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, ["TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange ) self.declare_partials( @@ -125,7 +125,7 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = np.zeros(nn) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) - outputs["distance_rate"] = TAS * np.cos(gamma) + outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) outputs["normal_force"] = normal_force outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha @@ -209,8 +209,9 @@ def compute_partials(self, inputs, J): J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) - J["distance_rate", "TAS"] = np.cos(gamma) - J["distance_rate", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + J[Dynamic.Mission.DISTANCE_RATE, "TAS"] = np.cos(gamma) + J[Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift diff --git a/aviary/mission/gasp_based/ode/test/test_accel_eom.py b/aviary/mission/gasp_based/ode/test/test_accel_eom.py index b1f42e91a..61950cbc4 100644 --- a/aviary/mission/gasp_based/ode/test/test_accel_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_accel_eom.py @@ -48,7 +48,8 @@ def test_case1(self): # note: this was finite differenced from GASP. The fd value is: np.array([5.2353365, 5.2353365]) ) assert_near_equal( - self.prob["distance_rate"], np.array([425.32808399, 425.32808399]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( + [425.32808399, 425.32808399]), tol # note: this was finite differenced from GASP. The fd value is: np.array([441.6439, 441.6439]) ) diff --git a/aviary/mission/gasp_based/ode/test/test_climb_eom.py b/aviary/mission/gasp_based/ode/test/test_climb_eom.py index d9539a24e..940f0a7cb 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_eom.py @@ -45,7 +45,8 @@ def test_case1(self): [6.24116612, 6.24116612]), tol ) # note: values from GASP are: np.array([5.9667, 5.9667]) assert_near_equal( - self.prob["distance_rate"], np.array([774.679584, 774.679584]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( + [774.679584, 774.679584]), tol # note: these values are finite differenced and lose accuracy. Fd values are: np.array([799.489, 799.489]) ) assert_near_equal( diff --git a/aviary/mission/gasp_based/ode/test/test_climb_ode.py b/aviary/mission/gasp_based/ode/test/test_climb_ode.py index 9094977a5..5a895cd11 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_ode.py @@ -48,7 +48,7 @@ def test_start_of_climb(self): "CD": 0.0307, Dynamic.Mission.ALTITUDE_RATE: 3186 / 60, # TAS (kts -> ft/s) * cos(gamma) - "distance_rate": (254 * 1.68781) * np.cos(np.deg2rad(7.12)), + Dynamic.Mission.DISTANCE_RATE: (254 * 1.68781) * np.cos(np.deg2rad(7.12)), Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -13505, # lbm/h "theta": np.deg2rad(12.31), Dynamic.Mission.FLIGHT_PATH_ANGLE: np.deg2rad(7.12), @@ -84,7 +84,7 @@ def test_end_of_climb(self): "CD": [0.0270, 0.0326], Dynamic.Mission.ALTITUDE_RATE: [3054 / 60, 453 / 60], # TAS (kts -> ft/s) * cos(gamma) - "distance_rate": [ + Dynamic.Mission.DISTANCE_RATE: [ (319 * 1.68781) * np.cos(np.deg2rad(5.42)), (459 * 1.68781) * np.cos(np.deg2rad(0.56)), ], diff --git a/aviary/mission/gasp_based/ode/test/test_descent_eom.py b/aviary/mission/gasp_based/ode/test/test_descent_eom.py index 00dfc13c9..b1885749a 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_eom.py @@ -47,7 +47,8 @@ def test_case1(self): [-39.41011217, -39.41011217]), tol ) # note: values from GASP are: np.array([-39.75, -39.75]) assert_near_equal( - self.prob["distance_rate"], np.array([773.70165638, 773.70165638]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( + [773.70165638, 773.70165638]), tol # note: these values are finite differenced and lose accuracy. Fd values are:np.array([964.4634921, 964.4634921]) ) assert_near_equal( diff --git a/aviary/mission/gasp_based/ode/test/test_descent_ode.py b/aviary/mission/gasp_based/ode/test/test_descent_ode.py index b7a64e408..262871768 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_ode.py @@ -48,7 +48,7 @@ def test_high_alt(self): "CD": np.array([0.0279, 0.0197]), Dynamic.Mission.ALTITUDE_RATE: np.array([-2385, -3076]) / 60, # TAS (ft/s) * cos(gamma) - "distance_rate": [ + Dynamic.Mission.DISTANCE_RATE: [ (459 * 1.68781) * np.cos(np.deg2rad(-2.94)), (437 * 1.68781) * np.cos(np.deg2rad(-3.98)), ], @@ -85,7 +85,7 @@ def test_low_alt(self): "CD": 0.0271, Dynamic.Mission.ALTITUDE_RATE: -1158 / 60, # TAS (ft/s) * cos(gamma) - "distance_rate": (255 * 1.68781) * np.cos(np.deg2rad(-2.56)), + Dynamic.Mission.DISTANCE_RATE: (255 * 1.68781) * np.cos(np.deg2rad(-2.56)), Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -1294, Dynamic.Mission.FLIGHT_PATH_ANGLE: np.deg2rad(-2.56), } diff --git a/aviary/mission/gasp_based/phases/2DOF_phase_builder.py b/aviary/mission/gasp_based/phases/2DOF_phase_builder.py index 1951b48ad..d8f0435c2 100644 --- a/aviary/mission/gasp_based/phases/2DOF_phase_builder.py +++ b/aviary/mission/gasp_based/phases/2DOF_phase_builder.py @@ -108,7 +108,7 @@ def build_phase(self): lower=self.bounds.get_val("distance_bounds")["value"][0], upper=self.bounds.get_val("distance_bounds")["value"][1], units=self.bounds.get_val("distance_bounds")["units"], - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, targets=Dynamic.Mission.DISTANCE, ref=self.scalers.get_val("distance_ref")["value"], ref0=self.scalers.get_val("distance_ref0")["value"], @@ -254,7 +254,8 @@ def linked_vars(phase1, phase2): # TODO: add other combinations of phases elif type1 == "cruise" and type2 == "descent": linked_vars = [] # TODO: update this elif type1 == "descent" and type2 == "descent": - linked_vars = ["time", Dynamic.Mission.ALTITUDE, "mass", "distance"] + linked_vars = ["time", Dynamic.Mission.ALTITUDE, + "mass", Dynamic.Mission.DISTANCE] else: raise om.AnalysisError( "You have provided a phase order which is not yet supported." diff --git a/aviary/mission/gasp_based/phases/accel_phase.py b/aviary/mission/gasp_based/phases/accel_phase.py index ed938768a..35cdec823 100644 --- a/aviary/mission/gasp_based/phases/accel_phase.py +++ b/aviary/mission/gasp_based/phases/accel_phase.py @@ -78,7 +78,7 @@ def get_accel( lower=distance_lower, upper=distance_upper, units="NM", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, ref0=distance_ref0, defect_ref=distance_defect_ref, diff --git a/aviary/mission/gasp_based/phases/ascent_phase.py b/aviary/mission/gasp_based/phases/ascent_phase.py index 6b9ed6747..28a2fa706 100644 --- a/aviary/mission/gasp_based/phases/ascent_phase.py +++ b/aviary/mission/gasp_based/phases/ascent_phase.py @@ -116,7 +116,7 @@ def get_ascent( lower=distance_lower, upper=distance_upper, units="ft", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, defect_ref=distance_defect_ref, ref0=distance_ref0, diff --git a/aviary/mission/gasp_based/phases/climb_phase.py b/aviary/mission/gasp_based/phases/climb_phase.py index 08a28330f..026ece771 100644 --- a/aviary/mission/gasp_based/phases/climb_phase.py +++ b/aviary/mission/gasp_based/phases/climb_phase.py @@ -90,7 +90,7 @@ def get_climb( lower=distance_lower, upper=distance_upper, units="NM", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, ref0=distance_ref0, defect_ref=distance_defect_ref, diff --git a/aviary/mission/gasp_based/phases/desc_phase.py b/aviary/mission/gasp_based/phases/desc_phase.py index 6f2eab9aa..0ace98f27 100644 --- a/aviary/mission/gasp_based/phases/desc_phase.py +++ b/aviary/mission/gasp_based/phases/desc_phase.py @@ -101,7 +101,7 @@ def get_descent( lower=distance_lower, upper=distance_upper, units="NM", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, ref0=distance_ref0, defect_ref=distance_defect_ref, diff --git a/aviary/mission/gasp_based/phases/groundroll_phase.py b/aviary/mission/gasp_based/phases/groundroll_phase.py index aa5a61df2..8b624b348 100644 --- a/aviary/mission/gasp_based/phases/groundroll_phase.py +++ b/aviary/mission/gasp_based/phases/groundroll_phase.py @@ -77,7 +77,7 @@ def get_groundroll( lower=distance_lower, upper=distance_upper, units="ft", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, defect_ref=distance_defect_ref, ref0=distance_ref0, diff --git a/aviary/mission/gasp_based/phases/rotation_phase.py b/aviary/mission/gasp_based/phases/rotation_phase.py index a0c4441db..c4997270e 100644 --- a/aviary/mission/gasp_based/phases/rotation_phase.py +++ b/aviary/mission/gasp_based/phases/rotation_phase.py @@ -97,7 +97,7 @@ def get_rotation( lower=distance_lower, upper=distance_upper, units="ft", - rate_source="distance_rate", + rate_source=Dynamic.Mission.DISTANCE_RATE, ref=distance_ref, ref0=distance_ref0, defect_ref=distance_defect_ref, diff --git a/aviary/mission/gasp_based/phases/run_phases/run_accel.py b/aviary/mission/gasp_based/phases/run_phases/run_accel.py index ce26a879e..ad1e5efd9 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_accel.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_accel.py @@ -68,7 +68,8 @@ def run_accel(): accel.add_timeseries_output("EAS", output_name="EAS", units="kn") accel.add_timeseries_output("TAS", output_name="TAS", units="kn") accel.add_timeseries_output("mass", output_name="mass", units="lbm") - accel.add_timeseries_output("distance", output_name="distance", units="NM") + accel.add_timeseries_output(Dynamic.Mission.DISTANCE, + output_name=Dynamic.Mission.DISTANCE, units="NM") accel.timeseries_options['use_prefix'] = True accel.add_objective("time", loc="final") diff --git a/aviary/mission/gasp_based/phases/run_phases/run_climb.py b/aviary/mission/gasp_based/phases/run_phases/run_climb.py index 90d3a5376..fadcd2155 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_climb.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_climb.py @@ -28,7 +28,7 @@ "time": ("TIME", "time", "s"), Dynamic.Mission.ALTITUDE: ("ALT", "states:altitude", "ft"), "mass": ("MASS", "states:mass", "lbm"), - Dynamic.Mission.DISTANCE: ("RANGE", "states:distance", "NM"), + Dynamic.Mission.DISTANCE: (Dynamic.Mission.RANGE, "states:distance", "NM"), Dynamic.Mission.MACH: ("MACH", Dynamic.Mission.MACH, None), "EAS": ("EAS", "EAS", "kn"), "alpha": ("ALPHA", "alpha", "deg"), diff --git a/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py b/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py index d9197c50b..fc3283d4c 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py @@ -30,7 +30,7 @@ "time": ("TIME", "time", "s"), Dynamic.Mission.ALTITUDE: ("ALT", "states:altitude", "ft"), "mass": ("MASS", "states:mass", "lbm"), - Dynamic.Mission.DISTANCE: ("RANGE", "states:distance", "NM"), + Dynamic.Mission.DISTANCE: (Dynamic.Mission.RANGE, "states:distance", "NM"), Dynamic.Mission.MACH: ("MACH", Dynamic.Mission.MACH, None), "EAS": ("EAS", "EAS", "kn"), "alpha": ("ALPHA", "alpha", "deg"), diff --git a/aviary/mission/gasp_based/phases/run_phases/run_groundroll.py b/aviary/mission/gasp_based/phases/run_phases/run_groundroll.py index 3f57333d4..f71e699ea 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_groundroll.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_groundroll.py @@ -124,7 +124,7 @@ def run_groundroll(): p.set_val( "traj.groundroll.states:distance", - groundroll.interp("distance", [0, 1000]), + groundroll.interp(Dynamic.Mission.DISTANCE, [0, 1000]), units="ft", ) diff --git a/aviary/mission/gasp_based/phases/run_phases/run_rotation.py b/aviary/mission/gasp_based/phases/run_phases/run_rotation.py index ce2fb8130..ef6bd5b49 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_rotation.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_rotation.py @@ -43,7 +43,7 @@ def run_rotation(make_plots=False): ) p.set_val( "traj.rotation.states:distance", - rotation.interp("distance", [3680.37217765, 4000]), + rotation.interp(Dynamic.Mission.DISTANCE, [3680.37217765, 4000]), units="ft", ) p.set_val("traj.rotation.t_duration", 50.0) diff --git a/aviary/mission/gasp_based/phases/run_phases/run_takeoff.py b/aviary/mission/gasp_based/phases/run_phases/run_takeoff.py index 1b859eb1c..41c33ddfe 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_takeoff.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_takeoff.py @@ -53,7 +53,8 @@ def run_takeoff(make_plots=False): transcription=rotation_trans, ) traj.add_phase("rotation", rotation) - traj.link_phases(["groundroll", "rotation"], ["time", "TAS", "mass", "distance"]) + traj.link_phases(["groundroll", "rotation"], [ + "time", "TAS", "mass", Dynamic.Mission.DISTANCE]) ascent_trans = dm.Radau( num_segments=2, order=5, compressed=True, solve_segments=False @@ -66,7 +67,7 @@ def run_takeoff(make_plots=False): ) traj.add_phase("ascent", ascent) traj.link_phases( - ["rotation", "ascent"], ["time", "TAS", "mass", "distance", "alpha"] + ["rotation", "ascent"], ["time", "TAS", "mass", Dynamic.Mission.DISTANCE, "alpha"] ) p.model.promotes( "traj", @@ -142,7 +143,7 @@ def run_takeoff(make_plots=False): ) p.set_val( "traj.groundroll.states:distance", - groundroll.interp("distance", [0, 1000]), + groundroll.interp(Dynamic.Mission.DISTANCE, [0, 1000]), units="ft", ) p.set_val("traj.groundroll.t_duration", 50.0) @@ -158,7 +159,7 @@ def run_takeoff(make_plots=False): ) p.set_val( "traj.rotation.states:distance", - rotation.interp("distance", [3680.37217765, 4000]), + rotation.interp(Dynamic.Mission.DISTANCE, [3680.37217765, 4000]), units="ft", ) p.set_val("traj.rotation.t_duration", 50.0) @@ -179,7 +180,7 @@ def run_takeoff(make_plots=False): ) p.set_val( "traj.ascent.states:distance", - ascent.interp("distance", [4330.83393029, 5000]), + ascent.interp(Dynamic.Mission.DISTANCE, [4330.83393029, 5000]), units="ft", ) p.set_val("traj.ascent.t_initial", 31.2) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index ef2a355a1..042f00fc1 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -27,7 +27,7 @@ from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables_in import VariablesIn -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Mission, Dynamic from aviary.subsystems.premission import CorePreMission from aviary.interface.default_phase_info.height_energy import default_premission_subsystems, default_mission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload @@ -292,9 +292,9 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise"], ["time", "altitude", - "velocity", "mass", "range"], connected=strong_couple) + "velocity", "mass", Dynamic.Mission.RANGE], connected=strong_couple) traj.link_phases(["cruise", "descent"], ["time", "altitude", - "velocity", "mass", "range"], connected=strong_couple) + "velocity", "mass", Dynamic.Mission.RANGE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) diff --git a/aviary/xdsm/accel_xdsm.py b/aviary/xdsm/accel_xdsm.py index e833e5263..f407abc9c 100644 --- a/aviary/xdsm/accel_xdsm.py +++ b/aviary/xdsm/accel_xdsm.py @@ -33,7 +33,7 @@ x.add_output("fc", ["EAS"], side="right") x.add_output("aero", [Dynamic.Mission.LIFT, Dynamic.Mission.DRAG, "alpha"], side="right") # for accel_ode, CruiseAero(output_alpha=True). So alpha is not an input. -x.add_output("eom", ["TAS_rate", "distance_rate"], side="right") +x.add_output("eom", ["TAS_rate", Dynamic.Mission.DISTANCE_RATE], side="right") # make connections x.add_input("atmos", [Dynamic.Mission.ALTITUDE]) diff --git a/aviary/xdsm/climb_xdsm.py b/aviary/xdsm/climb_xdsm.py index 1e9dddadf..764ad79ca 100644 --- a/aviary/xdsm/climb_xdsm.py +++ b/aviary/xdsm/climb_xdsm.py @@ -75,7 +75,7 @@ # create outputs x.add_output("eom", [ Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "required_lift", ], side="right") x.add_output("constraints", ["theta", "TAS_violation"], side="right") diff --git a/aviary/xdsm/descent1_xdsm.py b/aviary/xdsm/descent1_xdsm.py index 277268f2c..74e3b0f02 100644 --- a/aviary/xdsm/descent1_xdsm.py +++ b/aviary/xdsm/descent1_xdsm.py @@ -66,7 +66,7 @@ # create outputs x.add_output("eom", [ Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "required_lift" ], side="right") diff --git a/aviary/xdsm/descent2_xdsm.py b/aviary/xdsm/descent2_xdsm.py index 99e0dfa6a..20ba3f889 100644 --- a/aviary/xdsm/descent2_xdsm.py +++ b/aviary/xdsm/descent2_xdsm.py @@ -54,7 +54,7 @@ # create outputs x.add_output("eom", [ Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "required_lift" ], side="right") diff --git a/aviary/xdsm/groundroll_xdsm.py b/aviary/xdsm/groundroll_xdsm.py index b86d086d9..c032279f2 100644 --- a/aviary/xdsm/groundroll_xdsm.py +++ b/aviary/xdsm/groundroll_xdsm.py @@ -72,7 +72,7 @@ eom_output_list = [ Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.ALTITUDE_RATE, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "alpha_rate", "normal_force", "fuselage_pitch", diff --git a/aviary/xdsm/statics_xdsm.py b/aviary/xdsm/statics_xdsm.py index 761845370..e10333dee 100644 --- a/aviary/xdsm/statics_xdsm.py +++ b/aviary/xdsm/statics_xdsm.py @@ -411,32 +411,32 @@ # Connect State Rates x.connect( "groundroll", "dymos", [ - "TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + "TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.connect("rotation", "dymos", ["TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, "alpha_rate"]) x.connect("ascent", "dymos", ["TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - "distance_rate", + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], ) x.connect( "accelerate", "dymos", [ - "TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + "TAS_rate", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.connect("climb1", "dymos", [Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.connect("climb2", "dymos", [Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.connect("descent1", "dymos", [Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.connect("descent2", "dymos", [Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "distance_rate"]) + Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, Dynamic.Mission.DISTANCE_RATE]) x.write("statics_xdsm") x.write_sys_specs("statics_specs") From 8d383bc61004698f2bc00986a55fa90c5c81c9da Mon Sep 17 00:00:00 2001 From: Gregory Wrenn Date: Tue, 16 Jan 2024 15:51:02 -0500 Subject: [PATCH 048/111] [no ci] Changed the passenger count for the large single aisle models to 169 from 180. If appears the 180 was inadvertently taken from the passenger mass value. Reinstated the preprocessor.py check for consistency between total passengers and individual passenger class data. --- aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py | 2 +- .../large_single_aisle_1/large_single_aisle_1_GwGm.csv | 2 +- .../large_single_aisle_1/large_single_aisle_1_GwGm.dat | 2 +- aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv | 2 +- .../test_aircraft/aircraft_for_bench_GwGm_solved.csv | 2 +- aviary/utils/preprocessors.py | 7 ++++--- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py index 113fc4748..0809183c3 100644 --- a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py +++ b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py @@ -13,7 +13,7 @@ V3_bug_fixed_options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') + Aircraft.CrewPayload.NUM_PASSENGERS, val=169, units='unitless') V3_bug_fixed_options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') V3_bug_fixed_options.set_val( Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index f2492d9fb..fd0946733 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -6,7 +6,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_passengers,169,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat index f23fff285..633061c3c 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat @@ -18,7 +18,7 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck HCK=4.5, ! mean fuselage cabin diameter minus mean fuselage nose diameter in feet (2.47) HTG=8., ! wing height about ground during ground run in feet (3.0) HWING=0.0, ! wing location on fuselage =0, low wing; =1 high wing - PAX=180., ! number of passenger seats excluding crew + PAX=169., ! number of passenger seats excluding crew PS=29.0, ! seat pitch in inches RELR=0.4524, ! cg of fuselage and contents, fraction fuselage(.4) if LCWING <> 0 SAB=6., ! seats abreast in fuselage diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 5c0d0b8a0..92d47e871 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -21,7 +21,7 @@ aircraft:crew_and_payload:num_flight_attendants,3,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,0,unitless aircraft:crew_and_payload:num_non_flight_crew,3,unitless -aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_passengers,169,unitless aircraft:crew_and_payload:num_tourist_class,158,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index a71a6e26f..4789a1e54 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -5,7 +5,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_passengers,169,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv index 720764ca5..ba578e05d 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv @@ -5,7 +5,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_passengers,169,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 28f222f7b..c2cce0604 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -55,9 +55,10 @@ def preprocess_crewpayload(aviary_options: AviaryValues): passenger_check += aviary_options.get_val( Aircraft.CrewPayload.NUM_BUSINESS_CLASS) passenger_check += aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS) - # if passenger_count != passenger_check: - # raise om.AnalysisError( - # "ERROR: In preprocesssors.py: passenger_count does not equal the sum of firt class + business class + tourist class passengers.") + # only perform check if at least one passenger class is entered + if passenger_check > 0 and passenger_count != passenger_check: + raise om.AnalysisError( + "ERROR: In preprocesssors.py: passenger_count does not equal the sum of firt class + business class + tourist class passengers.") if Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS not in aviary_options: flight_attendants_count = 0 # assume no passengers From 0856cd846e448d8edee99cda28890a5d4084ec70 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Tue, 16 Jan 2024 16:20:13 -0500 Subject: [PATCH 049/111] all tests as expected --- .../getting_started/onboarding_level2.ipynb | 2 +- .../getting_started/onboarding_level3.ipynb | 52 +-- ...S_based_detailed_takeoff_and_landing.ipynb | 4 +- ..._same_mission_at_different_UI_levels.ipynb | 22 +- .../default_phase_info/height_energy.py | 16 +- aviary/interface/methods_for_level2.py | 20 +- aviary/interface/test/test_phase_info.py | 2 +- aviary/mission/flops_based/ode/landing_eom.py | 159 +++++---- aviary/mission/flops_based/ode/landing_ode.py | 32 +- aviary/mission/flops_based/ode/mission_EOM.py | 2 +- aviary/mission/flops_based/ode/mission_ODE.py | 2 +- aviary/mission/flops_based/ode/range_rate.py | 10 +- .../flops_based/ode/simple_mission_EOM.py | 2 +- .../flops_based/ode/simple_mission_ODE.py | 2 +- aviary/mission/flops_based/ode/takeoff_eom.py | 237 ++++++------- aviary/mission/flops_based/ode/takeoff_ode.py | 32 +- .../flops_based/ode/test/test_landing_eom.py | 20 +- .../flops_based/ode/test/test_landing_ode.py | 20 +- .../flops_based/ode/test/test_mission_EOM.py | 2 +- .../flops_based/ode/test/test_range_rate.py | 4 +- .../flops_based/ode/test/test_takeoff_eom.py | 41 ++- .../flops_based/ode/test/test_takeoff_ode.py | 45 ++- .../test_bench_climb_large_single_aisle_1.py | 6 +- .../test_bench_climb_large_single_aisle_2.py | 6 +- ...bench_cruise_climb_large_single_aisle_1.py | 6 +- .../test_bench_cruise_large_single_aisle_1.py | 6 +- .../test_bench_cruise_large_single_aisle_2.py | 6 +- ...test_bench_descent_large_single_aisle_1.py | 8 +- ...test_bench_descent_large_single_aisle_2.py | 8 +- .../flops_based/phases/cruise_phase.py | 12 +- .../phases/detailed_landing_phases.py | 165 +++++---- .../phases/detailed_takeoff_phases.py | 319 +++++++++--------- .../flops_based/phases/energy_phase.py | 12 +- .../flops_based/phases/simple_energy_phase.py | 12 +- .../gasp_based/phases/run_phases/run_climb.py | 2 +- .../run_phases/run_climb_test_FLOPS_prop.py | 2 +- aviary/models/N3CC/N3CC_data.py | 136 ++++---- .../aerodynamics/flops_based/ground_effect.py | 36 +- .../flops_based/takeoff_aero_group.py | 12 +- .../flops_based/test/test_ground_effect.py | 9 +- .../test/test_takeoff_aero_group.py | 31 +- .../test/test_custom_engine_model.py | 6 +- aviary/utils/report.py | 2 +- .../test_FLOPS_balanced_field_length.py | 8 +- .../test_FLOPS_based_full_mission_N3CC.py | 27 +- ...based_full_mission_large_single_aisle_1.py | 27 +- ...based_full_mission_large_single_aisle_2.py | 27 +- .../test_FLOPS_based_sizing_N3CC.py | 27 +- .../test_FLOPS_detailed_landing.py | 10 +- .../test_FLOPS_detailed_takeoff.py | 9 +- .../test_full_mission_solved_ode.py | 12 +- .../test_subsystems_within_a_mission.py | 2 +- aviary/validation_cases/benchmark_utils.py | 2 +- .../flops_data/full_mission_test_data.py | 2 +- aviary/variable_info/variable_meta_data.py | 27 +- aviary/xdsm/statics_xdsm.py | 8 +- 56 files changed, 838 insertions(+), 880 deletions(-) diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index 0d47cdf7f..5bb5fb516 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -658,7 +658,7 @@ " 'altitude': ([35.e3, 35.e3], 'ft'),\n", " 'velocity': ([455.49, 455.49], 'kn'),\n", " 'mass': ([165.e3, 140.e3], 'lbm'),\n", - " 'range': ([160.3, 3243.9], 'nmi'),\n", + " 'distance': ([160.3, 3243.9], 'nmi'),\n", " 'velocity_rate': ([0., 0.], 'm/s**2'),\n", " 'throttle': ([0.95, 0.9], 'unitless'),\n", " }\n", diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index 67f10696b..38a6bc929 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -325,9 +325,9 @@ "##########################################\n", "\n", "traj.link_phases([\"climb\", \"cruise\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "traj.link_phases([\"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "\n", "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", "\n", @@ -365,7 +365,7 @@ "\n", "prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", - "prob.model.connect('traj.climb.states:range',\n", + "prob.model.connect('traj.climb.states:distance',\n", " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", "prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", @@ -375,7 +375,7 @@ "prob.model.connect(Mission.Takeoff.FINAL_MASS,\n", " 'traj.climb.initial_states:mass')\n", "prob.model.connect(Mission.Takeoff.GROUND_DISTANCE,\n", - " 'traj.climb.initial_states:range')\n", + " 'traj.climb.initial_states:distance')\n", "prob.model.connect(Mission.Takeoff.FINAL_VELOCITY,\n", " 'traj.climb.initial_states:velocity')\n", "prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE,\n", @@ -443,8 +443,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s')\n", "prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - "prob.set_val('traj.climb.states:range', climb.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + "prob.set_val('traj.climb.states:distance', climb.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", "\n", "prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -462,8 +462,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s')\n", "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - "prob.set_val('traj.cruise.states:range', cruise.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", "\n", "prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -481,8 +481,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s')\n", "prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - "prob.set_val('traj.descent.states:range', descent.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", + "prob.set_val('traj.descent.states:distance', descent.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", "\n", "prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", @@ -502,7 +502,7 @@ "altitudes_climb = prob.get_val(\n", " 'traj.climb.timeseries.states:altitude', units='m')\n", "masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg')\n", - "ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m')\n", + "ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m')\n", "velocities_climb = prob.get_val(\n", " 'traj.climb.timeseries.states:velocity', units='m/s')\n", "thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')\n", @@ -510,7 +510,7 @@ "altitudes_cruise = prob.get_val(\n", " 'traj.cruise.timeseries.states:altitude', units='m')\n", "masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg')\n", - "ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m')\n", + "ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m')\n", "velocities_cruise = prob.get_val(\n", " 'traj.cruise.timeseries.states:velocity', units='m/s')\n", "thrusts_cruise = prob.get_val(\n", @@ -519,7 +519,7 @@ "altitudes_descent = prob.get_val(\n", " 'traj.descent.timeseries.states:altitude', units='m')\n", "masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg')\n", - "ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m')\n", + "ranges_descent = prob.get_val('traj.descent.timeseries.states:distance', units='m')\n", "velocities_descent = prob.get_val(\n", " 'traj.descent.timeseries.states:velocity', units='m/s')\n", "thrusts_descent = prob.get_val(\n", @@ -721,7 +721,7 @@ " prob.model.connect(Mission.Takeoff.FINAL_MASS,\n", " 'traj.climb.initial_states:mass')\n", " prob.model.connect(Mission.Takeoff.GROUND_DISTANCE,\n", - " 'traj.climb.initial_states:range')\n", + " 'traj.climb.initial_states:distance')\n", " prob.model.connect(Mission.Takeoff.FINAL_VELOCITY,\n", " 'traj.climb.initial_states:velocity')\n", " prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE,\n", @@ -768,8 +768,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s')\n", " prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - " prob.set_val('traj.climb.states:range', climb.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + " prob.set_val('traj.climb.states:distance', climb.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", "\n", " prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -787,8 +787,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s')\n", " prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - " prob.set_val('traj.cruise.states:range', cruise.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + " prob.set_val('traj.cruise.states:distance', cruise.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", "\n", " prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -806,8 +806,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s')\n", " prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - " prob.set_val('traj.descent.states:range', descent.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", + " prob.set_val('traj.descent.states:distance', descent.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", "\n", " prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", @@ -964,9 +964,9 @@ " strong_couple = False\n", "\n", " traj.link_phases([\"climb\", \"cruise\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", " traj.link_phases([\"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "\n", " traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", "\n", @@ -976,7 +976,7 @@ "\n", " prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", - " prob.model.connect('traj.climb.states:range',\n", + " prob.model.connect('traj.climb.states:distance',\n", " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", " prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", @@ -1082,7 +1082,7 @@ " altitudes_climb = prob.get_val(\n", " 'traj.climb.timeseries.states:altitude', units='m')\n", " masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg')\n", - " ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m')\n", + " ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m')\n", " velocities_climb = prob.get_val(\n", " 'traj.climb.timeseries.states:velocity', units='m/s')\n", " thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')\n", @@ -1090,7 +1090,7 @@ " altitudes_cruise = prob.get_val(\n", " 'traj.cruise.timeseries.states:altitude', units='m')\n", " masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg')\n", - " ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m')\n", + " ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m')\n", " velocities_cruise = prob.get_val(\n", " 'traj.cruise.timeseries.states:velocity', units='m/s')\n", " thrusts_cruise = prob.get_val(\n", @@ -1099,7 +1099,7 @@ " altitudes_descent = prob.get_val(\n", " 'traj.descent.timeseries.states:altitude', units='m')\n", " masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg')\n", - " ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m')\n", + " ranges_descent = prob.get_val('traj.descent.timeseries.states:distance', units='m')\n", " velocities_descent = prob.get_val(\n", " 'traj.descent.timeseries.states:velocity', units='m/s')\n", " thrusts_descent = prob.get_val(\n", diff --git a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb index c032c68dd..f89d2d31e 100644 --- a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb @@ -299,7 +299,7 @@ "liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff')\n", "\n", "liftoff.add_objective(\n", - " Dynamic.Mission.RANGE, loc='final', ref=max_range, units=units)\n", + " Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units)\n", "\n", "# Insert a constraint for a fake decision speed, until abort is added.\n", "takeoff.model.add_constraint(\n", @@ -551,7 +551,7 @@ "max_range, units = landing_fullstop_user_options.get_item('max_range')\n", "fullstop = landing_trajectory_builder.get_phase('landing_fullstop')\n", "\n", - "fullstop.add_objective(Dynamic.Mission.RANGE, loc='final', ref=max_range, units=units)\n", + "fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units)\n", "\n", "landing.model.add_subsystem(\n", " 'input_sink',\n", diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index f76118110..e2ea405ec 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -67,7 +67,7 @@ " 'core_aerodynamics': {'method': 'computed'}\n", " },\n", " 'user_options': {\n", - " 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.RANGE: False},\n", + " 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.DISTANCE: False},\n", " 'fix_initial_time': True,\n", " 'fix_duration': False,\n", " 'num_segments': 6,\n", @@ -434,9 +434,9 @@ " promotes_outputs=['mission:*'])\n", "\n", "traj.link_phases([\"climb\", \"cruise\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "traj.link_phases([\"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple)\n", + " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "\n", "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", "\n", @@ -474,7 +474,7 @@ "\n", "prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", - "prob.model.connect('traj.climb.states:range',\n", + "prob.model.connect('traj.climb.states:distance',\n", " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", "prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", @@ -484,7 +484,7 @@ "prob.model.connect(Mission.Takeoff.FINAL_MASS,\n", " 'traj.climb.initial_states:mass')\n", "prob.model.connect(Mission.Takeoff.GROUND_DISTANCE,\n", - " 'traj.climb.initial_states:range')\n", + " 'traj.climb.initial_states:distance')\n", "prob.model.connect(Mission.Takeoff.FINAL_VELOCITY,\n", " 'traj.climb.initial_states:velocity')\n", "prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE,\n", @@ -552,8 +552,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s')\n", "prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - "prob.set_val('traj.climb.states:range', climb.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + "prob.set_val('traj.climb.states:distance', climb.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", "\n", "prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -571,8 +571,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s')\n", "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - "prob.set_val('traj.cruise.states:range', cruise.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", "\n", "prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -590,8 +590,8 @@ " Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s')\n", "prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - "prob.set_val('traj.descent.states:range', descent.interp(\n", - " Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m')\n", + "prob.set_val('traj.descent.states:distance', descent.interp(\n", + " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", "\n", "prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", diff --git a/aviary/interface/default_phase_info/height_energy.py b/aviary/interface/default_phase_info/height_energy.py index 66d584192..1b233943c 100644 --- a/aviary/interface/default_phase_info/height_energy.py +++ b/aviary/interface/default_phase_info/height_energy.py @@ -27,7 +27,7 @@ 'core_aerodynamics': {'method': 'computed'} }, 'user_options': { - 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.RANGE: False}, + 'fix_initial': {Dynamic.Mission.MASS: False, Dynamic.Mission.DISTANCE: False}, 'fix_initial_time': True, 'fix_duration': False, 'num_segments': 6, @@ -50,7 +50,7 @@ 'altitude': ([0., 35.e3], 'ft'), 'velocity': ([220., 455.49], 'kn'), 'mass': ([170.e3, 165.e3], 'lbm'), - 'range': ([0., 160.3], 'nmi'), + 'distance': ([0., 160.3], 'nmi'), 'velocity_rate': ([0.25, 0.05], 'm/s**2'), 'throttle': ([0.5, 0.5], 'unitless'), } @@ -82,7 +82,7 @@ 'altitude': ([35.e3, 35.e3], 'ft'), 'velocity': ([455.49, 455.49], 'kn'), 'mass': ([165.e3, 140.e3], 'lbm'), - 'range': ([160.3, 3243.9], 'nmi'), + 'distance': ([160.3, 3243.9], 'nmi'), 'velocity_rate': ([0., 0.], 'm/s**2'), 'throttle': ([0.95, 0.9], 'unitless'), } @@ -112,7 +112,7 @@ 'altitude': ([35.e3, 35.], 'ft'), 'velocity': ([455.49, 198.44], 'kn'), 'mass': ([120.e3, 115.e3], 'lbm'), - 'range': ([3243.9, 3378.7], 'nmi'), + 'distance': ([3243.9, 3378.7], 'nmi'), 'velocity_rate': ([-0.25, 0.0], 'm/s**2'), 'throttle': ([0., 0.], 'unitless'), } @@ -154,13 +154,13 @@ def phase_info_parameterization(phase_info, aviary_inputs): if range_cruise != old_range_cruise: range_scale = range_cruise / old_range_cruise - vals = phase_info['descent']['initial_guesses']['range'][0] + vals = phase_info['descent']['initial_guesses']['distance'][0] new_vals = [vals[0] * range_scale, vals[1] * range_scale] - phase_info['descent']['initial_guesses']['range'] = (new_vals, 'NM') + phase_info['descent']['initial_guesses']['distance'] = (new_vals, 'NM') - vals = phase_info['cruise']['initial_guesses']['range'][0] + vals = phase_info['cruise']['initial_guesses']['distance'][0] new_val = vals[1] * range_scale - phase_info['cruise']['initial_guesses']['range'] = ([vals[0], new_val], 'NM') + phase_info['cruise']['initial_guesses']['distance'] = ([vals[0], new_val], 'NM') # Altitude diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 62fee7599..da6f45b2d 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -840,7 +840,7 @@ def _get_solved_phase(self, phase_name): phase.set_state_options("mass", rate_source="dmass_dv", fix_initial=True, fix_final=False, lower=1, upper=195_000, ref=takeoff_mass, defect_ref=takeoff_mass) - phase.set_state_options(Dynamic.Mission.RANGE, rate_source="over_a", + phase.set_state_options(Dynamic.Mission.DISTANCE, rate_source="over_a", fix_initial=True, fix_final=False, lower=0, upper=2000., ref=1.e2, defect_ref=1.e2) phase.add_parameter("t_init_gear", units="s", @@ -879,7 +879,7 @@ def _get_solved_phase(self, phase_name): static_target=False) phase.set_time_options(fix_initial=False, fix_duration=False, - units="range_units", name=Dynamic.Mission.RANGE, + units="range_units", name=Dynamic.Mission.DISTANCE, duration_bounds=wrapped_convert_units( phase_options['duration_bounds'], "range_units"), duration_ref=wrapped_convert_units( @@ -1132,7 +1132,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): pass elif phase_name == "descent": phase.add_boundary_constraint( - Dynamic.Mission.RANGE, + Dynamic.Mission.DISTANCE, loc="final", equals=target_range, units="NM", @@ -1263,7 +1263,7 @@ def add_post_mission_systems(self, include_landing=True): ("range_resid", Mission.Constraints.RANGE_RESIDUAL)], ) - self.model.connect(f"traj.{phases[-1]}.timeseries.states:range", + self.model.connect(f"traj.{phases[-1]}.timeseries.states:distance", "range_constraint.actual_range", src_indices=[-1]) self.model.add_constraint( Mission.Constraints.RANGE_RESIDUAL, equals=0.0, ref=1.e2) @@ -1378,12 +1378,12 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): self.traj.link_phases(phases, vars=['time'], ref=100.) self.traj.link_phases(phases, vars=['mass'], ref=10.e3) self.traj.link_phases( - phases, vars=[Dynamic.Mission.RANGE], units='m', ref=10.e3) + phases, vars=[Dynamic.Mission.DISTANCE], units='m', ref=10.e3) self.traj.link_phases(phases[:7], vars=['TAS'], units='kn', ref=200.) elif self.mission_method is SIMPLE: self.traj.link_phases( - phases, ["time", Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=True) + phases, ["time", Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=True) self._link_phases_helper_with_options( phases, 'optimize_altitude', Dynamic.Mission.ALTITUDE, ref=1.e4) @@ -1393,7 +1393,7 @@ def add_linkage_constraint(self, phase_a, phase_b, var_b): elif self.mission_method is HEIGHT_ENERGY: self.traj.link_phases( phases, ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=False, ref=1.e4) + Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=False, ref=1.e4) self.traj.link_phases( phases, [Dynamic.Mission.VELOCITY], connected=False, ref=250.) @@ -2064,11 +2064,11 @@ def _add_guesses(self, phase_name, phase, guesses): if self.mission_method is SIMPLE: control_keys = ["mach", "altitude"] - state_keys = ["mass", Dynamic.Mission.RANGE] + state_keys = ["mass", Dynamic.Mission.DISTANCE] else: control_keys = ["velocity_rate", "throttle"] state_keys = ["altitude", "velocity", "mass", - Dynamic.Mission.RANGE, "TAS", Dynamic.Mission.DISTANCE, "flight_path_angle", "alpha"] + Dynamic.Mission.DISTANCE, "TAS", Dynamic.Mission.DISTANCE, "flight_path_angle", "alpha"] if self.mission_method is TWO_DEGREES_OF_FREEDOM and phase_name == 'ascent': # Alpha is a control for ascent. control_keys.append('alpha') @@ -2412,7 +2412,7 @@ def _add_flops_landing_systems(self): self.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') self.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') + 'traj.climb.initial_states:distance') self.model.connect(Mission.Takeoff.FINAL_VELOCITY, 'traj.climb.initial_states:velocity') self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index 3d470a70b..56abb3a0b 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -154,7 +154,7 @@ def test_phase_info_parameterization_flops(self): prob.run_model() - assert_near_equal(prob.get_val("traj.descent.timeseries.input_values:states:range", units='km')[-1], + assert_near_equal(prob.get_val("traj.descent.timeseries.input_values:states:distance", units='km')[-1], 5000.0 * 3378.7 / 3500) assert_near_equal(prob.get_val("traj.cruise.timeseries.input_values:states:altitude", units='ft')[0], 31000.0) diff --git a/aviary/mission/flops_based/ode/landing_eom.py b/aviary/mission/flops_based/ode/landing_eom.py index af73cc2fc..1a2d7a61c 100644 --- a/aviary/mission/flops_based/ode/landing_eom.py +++ b/aviary/mission/flops_based/ode/landing_eom.py @@ -13,10 +13,7 @@ from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission class FlareEOM(om.Group): @@ -43,8 +40,8 @@ def setup(self): 'num_nodes': nn, 'climbing': True} - inputs = [Dynamic.FLIGHT_PATH_ANGLE, Dynamic.VELOCITY] - outputs = [Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE] + inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY] + outputs = [Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] self.add_subsystem( 'distance_rates', @@ -57,8 +54,8 @@ def setup(self): 'aviary_options': aviary_options} inputs = [ - Dynamic.MASS, Dynamic.LIFT, Dynamic.THRUST_TOTAL, Dynamic.DRAG, - 'angle_of_attack', Dynamic.FLIGHT_PATH_ANGLE] + Dynamic.Mission.MASS, Dynamic.Mission.LIFT, Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, + 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE] outputs = ['forces_horizontal', 'forces_vertical'] @@ -68,7 +65,7 @@ def setup(self): promotes_inputs=inputs, promotes_outputs=outputs) - inputs = ['forces_horizontal', 'forces_vertical', Dynamic.MASS] + inputs = ['forces_horizontal', 'forces_vertical', Dynamic.Mission.MASS] outputs = ['acceleration_horizontal', 'acceleration_vertical'] self.add_subsystem( @@ -79,9 +76,9 @@ def setup(self): inputs = [ 'acceleration_horizontal', 'acceleration_vertical', - Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE] + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] - outputs = [Dynamic.VELOCITY_RATE,] + outputs = [Dynamic.Mission.VELOCITY_RATE,] self.add_subsystem( 'velocity_rate', @@ -90,10 +87,10 @@ def setup(self): promotes_outputs=outputs) inputs = [ - Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE, + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, 'acceleration_horizontal', 'acceleration_vertical'] - outputs = [Dynamic.FLIGHT_PATH_ANGLE_RATE] + outputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] self.add_subsystem( 'flight_path_angle_rate', FlightPathAngleRate(num_nodes=nn), @@ -101,8 +98,8 @@ def setup(self): promotes_outputs=outputs) inputs = [ - Dynamic.MASS, Dynamic.LIFT, Dynamic.DRAG, - 'angle_of_attack', Dynamic.FLIGHT_PATH_ANGLE] + Dynamic.Mission.MASS, Dynamic.Mission.LIFT, Dynamic.Mission.DRAG, + 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE] outputs = ['forces_perpendicular', 'required_thrust'] @@ -147,13 +144,14 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') self.add_output( 'forces_perpendicular', val=np.zeros(nn), units='N', @@ -182,14 +180,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') total_num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal gamma = -gamma @@ -220,14 +218,14 @@ def compute_partials(self, inputs, J, discrete_inputs=None): t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') total_num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal gamma = -gamma @@ -246,20 +244,20 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h = -grav_metric * s_gamma / c_angle f_v = grav_metric * c_gamma / s_angle - J[forces_key, Dynamic.MASS] = f_h - f_v - J[thrust_key, Dynamic.MASS] = (f_h + f_v) / (2.) + J[forces_key, Dynamic.Mission.MASS] = f_h - f_v + J[thrust_key, Dynamic.Mission.MASS] = (f_h + f_v) / (2.) f_h = 0. f_v = -1. / s_angle - J[forces_key, Dynamic.LIFT] = -f_v - J[thrust_key, Dynamic.LIFT] = f_v / (2.) + J[forces_key, Dynamic.Mission.LIFT] = -f_v + J[thrust_key, Dynamic.Mission.LIFT] = f_v / (2.) f_h = 1. / c_angle f_v = 0. - J[forces_key, Dynamic.DRAG] = f_h - J[thrust_key, Dynamic.DRAG] = f_h / (2.) + J[forces_key, Dynamic.Mission.DRAG] = f_h + J[thrust_key, Dynamic.Mission.DRAG] = f_h / (2.) # ddx(1 / cos(x)) = sec(x) * tan(x) = tan(x) / cos(x) # ddx(1 / sin(x)) = -csc(x) * cot(x) = -1 / (sin(x) * tan(x)) @@ -274,8 +272,8 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h = -weight * c_gamma / c_angle f_v = -weight * s_gamma / s_angle - J[forces_key, Dynamic.FLIGHT_PATH_ANGLE] = - f_h + f_v - J[thrust_key, Dynamic.FLIGHT_PATH_ANGLE] = -(f_h + f_v) / (2.) + J[forces_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - f_h + f_v + J[thrust_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -(f_h + f_v) / (2.) class FlareSumForces(om.ExplicitComponent): @@ -298,14 +296,15 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') self.add_output( 'forces_horizontal', val=np.zeros(nn), units='N', @@ -322,15 +321,15 @@ def setup_partials(self): rows_cols = np.arange(nn) - self.declare_partials('forces_horizontal', Dynamic.MASS, dependent=False) + self.declare_partials('forces_horizontal', Dynamic.Mission.MASS, dependent=False) self.declare_partials( - 'forces_vertical', Dynamic.MASS, val=-grav_metric, rows=rows_cols, + 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, cols=rows_cols) wrt = [ - Dynamic.LIFT, Dynamic.THRUST_TOTAL, Dynamic.DRAG, 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE] + Dynamic.Mission.LIFT, Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, 'angle_of_attack', + Dynamic.Mission.FLIGHT_PATH_ANGLE] self.declare_partials('*', wrt, rows=rows_cols, cols=rows_cols) @@ -342,13 +341,13 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal gamma = -gamma @@ -380,13 +379,13 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal gamma = -gamma @@ -400,25 +399,25 @@ def compute_partials(self, inputs, J, discrete_inputs=None): s_gamma = np.sin(gamma) f_h_key = 'forces_horizontal' - J[f_h_key, Dynamic.LIFT] = -s_gamma + J[f_h_key, Dynamic.Mission.LIFT] = -s_gamma f_v_key = 'forces_vertical' - J[f_v_key, Dynamic.LIFT] = c_gamma + J[f_v_key, Dynamic.Mission.LIFT] = c_gamma - J[f_h_key, Dynamic.THRUST_TOTAL] = -c_angle - J[f_v_key, Dynamic.THRUST_TOTAL] = s_angle + J[f_h_key, Dynamic.Mission.THRUST_TOTAL] = -c_angle + J[f_v_key, Dynamic.Mission.THRUST_TOTAL] = s_angle - J[f_h_key, Dynamic.DRAG] = c_gamma - J[f_v_key, Dynamic.DRAG] = s_gamma + J[f_h_key, Dynamic.Mission.DRAG] = c_gamma + J[f_v_key, Dynamic.Mission.DRAG] = s_gamma J[f_h_key, 'angle_of_attack'] = thrust * s_angle J[f_v_key, 'angle_of_attack'] = thrust * c_angle f_h = -drag * s_gamma - lift * c_gamma - thrust * s_angle - J[f_h_key, Dynamic.FLIGHT_PATH_ANGLE] = -f_h + J[f_h_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -f_h f_v = -lift * s_gamma + drag * c_gamma - thrust * c_angle - J[f_v_key, Dynamic.FLIGHT_PATH_ANGLE] = -f_v + J[f_v_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -f_v class GroundSumForces(om.ExplicitComponent): @@ -442,10 +441,10 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') self.add_output( 'forces_horizontal', val=np.zeros(nn), units='N', @@ -463,25 +462,25 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - 'forces_vertical', Dynamic.MASS, val=-grav_metric, rows=rows_cols, + 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_vertical', Dynamic.LIFT, val=1., rows=rows_cols, cols=rows_cols) + 'forces_vertical', Dynamic.Mission.LIFT, val=1., rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_vertical', [Dynamic.THRUST_TOTAL, Dynamic.DRAG], dependent=False) + 'forces_vertical', [Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG], dependent=False) self.declare_partials( - 'forces_horizontal', [Dynamic.MASS, Dynamic.LIFT], rows=rows_cols, + 'forces_horizontal', [Dynamic.Mission.MASS, Dynamic.Mission.LIFT], rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_horizontal', Dynamic.THRUST_TOTAL, val=-1., rows=rows_cols, + 'forces_horizontal', Dynamic.Mission.THRUST_TOTAL, val=-1., rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_horizontal', Dynamic.DRAG, val=1., rows=rows_cols, cols=rows_cols) + 'forces_horizontal', Dynamic.Mission.DRAG, val=1., rows=rows_cols, cols=rows_cols) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): options = self.options @@ -489,10 +488,10 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): nn = options['num_nodes'] friction_coefficient = options['friction_coefficient'] - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric @@ -512,8 +511,8 @@ def compute_partials(self, inputs, J, discrete_inputs=None): nn = options['num_nodes'] friction_coefficient = options['friction_coefficient'] - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] weight = mass * grav_metric @@ -523,8 +522,8 @@ def compute_partials(self, inputs, J, discrete_inputs=None): friction = np.zeros(nn) friction[idx_sup] = friction_coefficient * grav_metric - J['forces_horizontal', Dynamic.MASS] = friction + J['forces_horizontal', Dynamic.Mission.MASS] = friction friction = np.zeros(nn) friction[idx_sup] = -friction_coefficient - J['forces_horizontal', Dynamic.LIFT] = friction + J['forces_horizontal', Dynamic.Mission.LIFT] = friction diff --git a/aviary/mission/flops_based/ode/landing_ode.py b/aviary/mission/flops_based/ode/landing_ode.py index c768083bb..76f5f9a36 100644 --- a/aviary/mission/flops_based/ode/landing_ode.py +++ b/aviary/mission/flops_based/ode/landing_ode.py @@ -14,13 +14,9 @@ from aviary.mission.gasp_based.flight_conditions import FlightConditions from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values, promote_aircraft_and_mission_vars -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn -Dynamic = _Dynamic.Mission - class ExternalSubsystemGroup(om.Group): def configure(self): @@ -79,16 +75,18 @@ def setup(self): self.add_subsystem( "USatm", USatm1976Comp(num_nodes=nn), - promotes_inputs=[("h", Dynamic.ALTITUDE)], + promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], promotes_outputs=[ - "rho", ("sos", Dynamic.SPEED_OF_SOUND), ("temp", Dynamic.TEMPERATURE), - ("pres", Dynamic.STATIC_PRESSURE), "viscosity"]) + "rho", ("sos", Dynamic.Mission.SPEED_OF_SOUND), ("temp", + Dynamic.Mission.TEMPERATURE), + ("pres", Dynamic.Mission.STATIC_PRESSURE), "viscosity"]) self.add_subsystem( "fc", FlightConditions(num_nodes=nn), - promotes_inputs=["rho", Dynamic.SPEED_OF_SOUND, ("TAS", Dynamic.VELOCITY)], - promotes_outputs=[Dynamic.DYNAMIC_PRESSURE, Dynamic.MACH, "EAS"]) + promotes_inputs=["rho", Dynamic.Mission.SPEED_OF_SOUND, + ("TAS", Dynamic.Mission.VELOCITY)], + promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MACH, "EAS"]) # NOTE: the following are potentially signficant differences in implementation # between FLOPS and Aviary: @@ -155,13 +153,13 @@ def setup(self): 'eoms', FlareEOM(**kwargs), promotes_inputs=[ - Dynamic.FLIGHT_PATH_ANGLE, Dynamic.VELOCITY, Dynamic.MASS, Dynamic.LIFT, - Dynamic.THRUST_TOTAL, Dynamic.DRAG, 'angle_of_attack', + Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, 'angle_of_attack', 'angle_of_attack_rate', Mission.Landing.FLARE_RATE ], promotes_outputs=[ - Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE, Dynamic.VELOCITY_RATE, - Dynamic.FLIGHT_PATH_ANGLE_RATE, 'forces_perpendicular', + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, 'forces_perpendicular', 'required_thrust', 'net_alpha_rate' ] ) @@ -174,10 +172,10 @@ def setup(self): v={'units': 'm/s', 'shape': nn}, # NOTE: FLOPS detailed takeoff stall speed is not dynamic - see above v_stall={'units': 'm/s', 'shape': nn}), - promotes_inputs=[('v', Dynamic.VELOCITY), 'v_stall'], + promotes_inputs=[('v', Dynamic.Mission.VELOCITY), 'v_stall'], promotes_outputs=['v_over_v_stall']) - self.set_input_defaults(Dynamic.ALTITUDE, np.zeros(nn), 'm') - self.set_input_defaults(Dynamic.VELOCITY, np.zeros(nn), 'm/s') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn), 'm') + self.set_input_defaults(Dynamic.Mission.VELOCITY, np.zeros(nn), 'm/s') set_aviary_initial_values(self, aviary_options) diff --git a/aviary/mission/flops_based/ode/mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py index 946a85468..74893c351 100644 --- a/aviary/mission/flops_based/ode/mission_EOM.py +++ b/aviary/mission/flops_based/ode/mission_EOM.py @@ -28,7 +28,7 @@ def setup(self): subsys=RangeRate(num_nodes=nn), promotes_inputs=[ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], - promotes_outputs=[Dynamic.Mission.RANGE_RATE]) + promotes_outputs=[Dynamic.Mission.DISTANCE_RATE]) self.add_subsystem(name='excess_specific_power', subsys=SpecificEnergyRate(num_nodes=nn), promotes_inputs=[(Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), diff --git a/aviary/mission/flops_based/ode/mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py index 0ce3b3541..3aed55277 100644 --- a/aviary/mission/flops_based/ode/mission_ODE.py +++ b/aviary/mission/flops_based/ode/mission_ODE.py @@ -122,7 +122,7 @@ def setup(self): Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.RANGE_RATE]) + Dynamic.Mission.DISTANCE_RATE]) self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones(nn), units='kg') self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s') diff --git a/aviary/mission/flops_based/ode/range_rate.py b/aviary/mission/flops_based/ode/range_rate.py index 9ef5d8fca..86614aeed 100644 --- a/aviary/mission/flops_based/ode/range_rate.py +++ b/aviary/mission/flops_based/ode/range_rate.py @@ -22,7 +22,7 @@ def setup(self): desc='current velocity', units='m/s') self.add_output( - Dynamic.Mission.RANGE_RATE, + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc='current horizontal velocity (assumed no wind)', units='m/s') @@ -35,19 +35,19 @@ def compute(self, inputs, outputs): if (climb_rate_2 >= velocity_2).any(): raise om.AnalysisError( "WARNING: climb rate exceeds velocity (range_rate.py)") - outputs[Dynamic.Mission.RANGE_RATE] = (velocity_2 - climb_rate_2)**0.5 + outputs[Dynamic.Mission.DISTANCE_RATE] = (velocity_2 - climb_rate_2)**0.5 def setup_partials(self): arange = np.arange(self.options['num_nodes']) self.declare_partials( - Dynamic.Mission.RANGE_RATE, [ + Dynamic.Mission.DISTANCE_RATE, [ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], rows=arange, cols=arange) def compute_partials(self, inputs, J): climb_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] velocity = inputs[Dynamic.Mission.VELOCITY] - J[Dynamic.Mission.RANGE_RATE, Dynamic.Mission.ALTITUDE_RATE] = -climb_rate / \ + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] = -climb_rate / \ (velocity**2 - climb_rate**2)**0.5 - J[Dynamic.Mission.RANGE_RATE, Dynamic.Mission.VELOCITY] = velocity / \ + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = velocity / \ (velocity**2 - climb_rate**2)**0.5 diff --git a/aviary/mission/flops_based/ode/simple_mission_EOM.py b/aviary/mission/flops_based/ode/simple_mission_EOM.py index 8e3e25e1f..b726d17b6 100644 --- a/aviary/mission/flops_based/ode/simple_mission_EOM.py +++ b/aviary/mission/flops_based/ode/simple_mission_EOM.py @@ -25,7 +25,7 @@ def setup(self): subsys=RangeRate(num_nodes=nn), promotes_inputs=[ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], - promotes_outputs=[Dynamic.Mission.RANGE_RATE]) + promotes_outputs=[Dynamic.Mission.DISTANCE_RATE]) self.add_subsystem(name='excess_specific_power', subsys=SpecificEnergyRate(num_nodes=nn), diff --git a/aviary/mission/flops_based/ode/simple_mission_ODE.py b/aviary/mission/flops_based/ode/simple_mission_ODE.py index 58554956b..0a34ad7ee 100644 --- a/aviary/mission/flops_based/ode/simple_mission_ODE.py +++ b/aviary/mission/flops_based/ode/simple_mission_ODE.py @@ -148,7 +148,7 @@ def setup(self): promotes_outputs=[ Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.RANGE_RATE, + Dynamic.Mission.DISTANCE_RATE, 'T_required', ]) diff --git a/aviary/mission/flops_based/ode/takeoff_eom.py b/aviary/mission/flops_based/ode/takeoff_eom.py index b50127327..058254c1f 100644 --- a/aviary/mission/flops_based/ode/takeoff_eom.py +++ b/aviary/mission/flops_based/ode/takeoff_eom.py @@ -8,10 +8,7 @@ from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission class StallSpeed(om.ExplicitComponent): @@ -131,8 +128,8 @@ def setup(self): 'climbing': climbing } - inputs = [Dynamic.FLIGHT_PATH_ANGLE, Dynamic.VELOCITY] - outputs = [Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE] + inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY] + outputs = [Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] self.add_subsystem( 'distance_rates', DistanceRates(**kwargs), @@ -197,11 +194,14 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.VELOCITY, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.RANGE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, + val=np.zeros(nn), units='m/s') + add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, + val=np.zeros(nn), units='m/s') def setup_partials(self): options = self.options @@ -215,18 +215,18 @@ def setup_partials(self): else: self.declare_partials( - Dynamic.RANGE_RATE, Dynamic.FLIGHT_PATH_ANGLE, dependent=False) + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE, dependent=False) self.declare_partials( - Dynamic.RANGE_RATE, Dynamic.VELOCITY, val=np.identity(nn)) + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY, val=np.identity(nn)) - self.declare_partials(Dynamic.ALTITUDE_RATE, '*', dependent=False) + self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, '*', dependent=False) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - velocity = inputs[Dynamic.VELOCITY] + velocity = inputs[Dynamic.Mission.VELOCITY] if self.options['climbing']: - flight_path_angle = inputs[Dynamic.FLIGHT_PATH_ANGLE] + flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] cgam = np.cos(flight_path_angle) range_rate = cgam * velocity @@ -234,26 +234,26 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): sgam = np.sin(flight_path_angle) altitude_rate = sgam * velocity - outputs[Dynamic.ALTITUDE_RATE] = altitude_rate + outputs[Dynamic.Mission.ALTITUDE_RATE] = altitude_rate else: range_rate = velocity - outputs[Dynamic.RANGE_RATE] = range_rate + outputs[Dynamic.Mission.DISTANCE_RATE] = range_rate def compute_partials(self, inputs, J, discrete_inputs=None): if self.options['climbing']: - flight_path_angle = inputs[Dynamic.FLIGHT_PATH_ANGLE] - velocity = inputs[Dynamic.VELOCITY] + flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] + velocity = inputs[Dynamic.Mission.VELOCITY] cgam = np.cos(flight_path_angle) sgam = np.sin(flight_path_angle) - J[Dynamic.RANGE_RATE, Dynamic.FLIGHT_PATH_ANGLE] = -sgam * velocity - J[Dynamic.RANGE_RATE, Dynamic.VELOCITY] = cgam + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -sgam * velocity + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = cgam - J[Dynamic.ALTITUDE_RATE, Dynamic.FLIGHT_PATH_ANGLE] = cgam * velocity - J[Dynamic.ALTITUDE_RATE, Dynamic.VELOCITY] = sgam + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = cgam * velocity + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = sgam class Accelerations(om.ExplicitComponent): @@ -269,7 +269,7 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') self.add_input( 'forces_horizontal', val=np.zeros(nn), units='N', @@ -293,10 +293,10 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - 'acceleration_horizontal', Dynamic.MASS, rows=rows_cols, cols=rows_cols) + 'acceleration_horizontal', Dynamic.Mission.MASS, rows=rows_cols, cols=rows_cols) self.declare_partials( - 'acceleration_vertical', Dynamic.MASS, rows=rows_cols, cols=rows_cols) + 'acceleration_vertical', Dynamic.Mission.MASS, rows=rows_cols, cols=rows_cols) self.declare_partials( 'acceleration_horizontal', 'forces_horizontal', rows=rows_cols, @@ -312,7 +312,7 @@ def setup_partials(self): 'acceleration_vertical', 'forces_vertical', rows=rows_cols, cols=rows_cols) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - mass = inputs[Dynamic.MASS] + mass = inputs[Dynamic.Mission.MASS] f_h = inputs['forces_horizontal'] f_v = inputs['forces_vertical'] @@ -323,14 +323,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): outputs['acceleration_vertical'] = a_v def compute_partials(self, inputs, J, discrete_inputs=None): - mass = inputs[Dynamic.MASS] + mass = inputs[Dynamic.Mission.MASS] f_h = inputs['forces_horizontal'] f_v = inputs['forces_vertical'] m2 = mass * mass - J['acceleration_horizontal', Dynamic.MASS] = -f_h / m2 - J['acceleration_vertical', Dynamic.MASS] = -f_v / m2 + J['acceleration_horizontal', Dynamic.Mission.MASS] = -f_h / m2 + J['acceleration_vertical', Dynamic.Mission.MASS] = -f_v / m2 J['acceleration_horizontal', 'forces_horizontal'] = 1. / mass @@ -358,10 +358,13 @@ def setup(self): 'acceleration_vertical', val=np.zeros(nn), desc='current vertical acceleration', units='m/s**2') - add_aviary_input(self, Dynamic.RANGE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, + val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, + val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.VELOCITY_RATE, val=np.ones(nn), units='m/s**2') + add_aviary_output(self, Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), units='m/s**2') rows_cols = np.arange(nn) @@ -370,30 +373,30 @@ def setup(self): def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): a_h = inputs['acceleration_horizontal'] a_v = inputs['acceleration_vertical'] - v_h = inputs[Dynamic.RANGE_RATE] - v_v = inputs[Dynamic.ALTITUDE_RATE] + v_h = inputs[Dynamic.Mission.DISTANCE_RATE] + v_v = inputs[Dynamic.Mission.ALTITUDE_RATE] v_mag = np.sqrt(v_h**2 + v_v**2) - outputs[Dynamic.VELOCITY_RATE] = (a_h * v_h + a_v * v_v) / v_mag + outputs[Dynamic.Mission.VELOCITY_RATE] = (a_h * v_h + a_v * v_v) / v_mag def compute_partials(self, inputs, J, discrete_inputs=None): a_h = inputs['acceleration_horizontal'] a_v = inputs['acceleration_vertical'] - v_h = inputs[Dynamic.RANGE_RATE] - v_v = inputs[Dynamic.ALTITUDE_RATE] + v_h = inputs[Dynamic.Mission.DISTANCE_RATE] + v_v = inputs[Dynamic.Mission.ALTITUDE_RATE] num = (a_h * v_h + a_v * v_v) fact = v_h**2 + v_v**2 den = np.sqrt(fact) - J[Dynamic.VELOCITY_RATE, 'acceleration_horizontal'] = v_h / den - J[Dynamic.VELOCITY_RATE, 'acceleration_vertical'] = v_v / den + J[Dynamic.Mission.VELOCITY_RATE, 'acceleration_horizontal'] = v_h / den + J[Dynamic.Mission.VELOCITY_RATE, 'acceleration_vertical'] = v_v / den - J[Dynamic.VELOCITY_RATE, - Dynamic.RANGE_RATE] = a_h / den - 0.5 * num / fact**(3/2) * 2.0 * v_h + J[Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.DISTANCE_RATE] = a_h / den - 0.5 * num / fact**(3/2) * 2.0 * v_h - J[Dynamic.VELOCITY_RATE, - Dynamic.ALTITUDE_RATE] = a_v / den - 0.5 * num / fact**(3/2) * 2.0 * v_v + J[Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.ALTITUDE_RATE] = a_v / den - 0.5 * num / fact**(3/2) * 2.0 * v_v class FlightPathAngleRate(om.ExplicitComponent): @@ -409,8 +412,10 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.RANGE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, + val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, + val=np.zeros(nn), units='m/s') self.add_input( 'acceleration_horizontal', val=np.zeros(nn), @@ -425,25 +430,25 @@ def setup(self): ) add_aviary_output( - self, Dynamic.FLIGHT_PATH_ANGLE_RATE, val=np.zeros(nn), units='rad/s') + self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.zeros(nn), units='rad/s') rows_cols = np.arange(nn) self.declare_partials('*', '*', rows=rows_cols, cols=rows_cols) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - v_h = inputs[Dynamic.RANGE_RATE] - v_v = inputs[Dynamic.ALTITUDE_RATE] + v_h = inputs[Dynamic.Mission.DISTANCE_RATE] + v_v = inputs[Dynamic.Mission.ALTITUDE_RATE] a_h = inputs['acceleration_horizontal'] a_v = inputs['acceleration_vertical'] x = (a_v * v_h - a_h * v_v) / (v_h**2 + v_v**2) - outputs[Dynamic.FLIGHT_PATH_ANGLE_RATE] = x + outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = x def compute_partials(self, inputs, J, discrete_inputs=None): - v_h = inputs[Dynamic.RANGE_RATE] - v_v = inputs[Dynamic.ALTITUDE_RATE] + v_h = inputs[Dynamic.Mission.DISTANCE_RATE] + v_v = inputs[Dynamic.Mission.ALTITUDE_RATE] a_h = inputs['acceleration_horizontal'] a_v = inputs['acceleration_vertical'] @@ -458,10 +463,10 @@ def compute_partials(self, inputs, J, discrete_inputs=None): df_dav = v_h / den - J[Dynamic.FLIGHT_PATH_ANGLE_RATE, Dynamic.RANGE_RATE] = df_dvh - J[Dynamic.FLIGHT_PATH_ANGLE_RATE, Dynamic.ALTITUDE_RATE] = df_dvv - J[Dynamic.FLIGHT_PATH_ANGLE_RATE, 'acceleration_horizontal'] = df_dah - J[Dynamic.FLIGHT_PATH_ANGLE_RATE, 'acceleration_vertical'] = df_dav + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.DISTANCE_RATE] = df_dvh + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.ALTITUDE_RATE] = df_dvv + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, 'acceleration_horizontal'] = df_dah + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, 'acceleration_vertical'] = df_dav class SumForces(om.ExplicitComponent): @@ -494,14 +499,15 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') self.add_output( 'forces_horizontal', val=np.zeros(nn), units='N', @@ -520,15 +526,16 @@ def setup_partials(self): rows_cols = np.arange(nn) if climbing: - self.declare_partials('forces_horizontal', Dynamic.MASS, dependent=False) + self.declare_partials('forces_horizontal', + Dynamic.Mission.MASS, dependent=False) self.declare_partials( - 'forces_vertical', Dynamic.MASS, val=-grav_metric, rows=rows_cols, + 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, cols=rows_cols) wrt = [ - Dynamic.THRUST_TOTAL, Dynamic.LIFT, Dynamic.DRAG, 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE] + Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.LIFT, Dynamic.Mission.DRAG, 'angle_of_attack', + Dynamic.Mission.FLIGHT_PATH_ANGLE] self.declare_partials('*', wrt, rows=rows_cols, cols=rows_cols) @@ -539,26 +546,27 @@ def setup_partials(self): val = -grav_metric * mu self.declare_partials( - 'forces_horizontal', Dynamic.MASS, val=val, rows=rows_cols, + 'forces_horizontal', Dynamic.Mission.MASS, val=val, rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_horizontal', Dynamic.LIFT, val=mu, rows=rows_cols, + 'forces_horizontal', Dynamic.Mission.LIFT, val=mu, rows=rows_cols, cols=rows_cols) t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') val = np.cos(t_inc) + np.sin(t_inc) * mu self.declare_partials( - 'forces_horizontal', Dynamic.THRUST_TOTAL, val=val, rows=rows_cols, + 'forces_horizontal', Dynamic.Mission.THRUST_TOTAL, val=val, rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_horizontal', Dynamic.DRAG, val=-1., rows=rows_cols, + 'forces_horizontal', Dynamic.Mission.DRAG, val=-1., rows=rows_cols, cols=rows_cols) self.declare_partials( - 'forces_horizontal', ['angle_of_attack', Dynamic.FLIGHT_PATH_ANGLE], + 'forces_horizontal', ['angle_of_attack', + Dynamic.Mission.FLIGHT_PATH_ANGLE], dependent=False) self.declare_partials('forces_vertical', ['*'], dependent=False) @@ -571,10 +579,10 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric @@ -587,7 +595,7 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc + gamma @@ -631,12 +639,12 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc + gamma @@ -646,22 +654,22 @@ def compute_partials(self, inputs, J, discrete_inputs=None): c_gamma = np.cos(gamma) s_gamma = np.sin(gamma) - J['forces_horizontal', Dynamic.THRUST_TOTAL] = c_angle - J['forces_vertical', Dynamic.THRUST_TOTAL] = s_angle + J['forces_horizontal', Dynamic.Mission.THRUST_TOTAL] = c_angle + J['forces_vertical', Dynamic.Mission.THRUST_TOTAL] = s_angle - J['forces_horizontal', Dynamic.LIFT] = -s_gamma - J['forces_vertical', Dynamic.LIFT] = c_gamma + J['forces_horizontal', Dynamic.Mission.LIFT] = -s_gamma + J['forces_vertical', Dynamic.Mission.LIFT] = c_gamma - J['forces_horizontal', Dynamic.DRAG] = -c_gamma - J['forces_vertical', Dynamic.DRAG] = -s_gamma + J['forces_horizontal', Dynamic.Mission.DRAG] = -c_gamma + J['forces_vertical', Dynamic.Mission.DRAG] = -s_gamma J['forces_horizontal', 'angle_of_attack'] = -thrust * s_angle J['forces_vertical', 'angle_of_attack'] = thrust * c_angle - J['forces_horizontal', Dynamic.FLIGHT_PATH_ANGLE] = \ + J['forces_horizontal', Dynamic.Mission.FLIGHT_PATH_ANGLE] = \ -thrust * s_angle + drag * s_gamma - lift * c_gamma - J['forces_vertical', Dynamic.FLIGHT_PATH_ANGLE] = \ + J['forces_vertical', Dynamic.Mission.FLIGHT_PATH_ANGLE] = \ thrust * c_angle - drag * c_gamma - lift * s_gamma @@ -685,14 +693,15 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') self.add_output( 'climb_gradient_forces_horizontal', val=np.zeros(nn), units='N', @@ -714,22 +723,22 @@ def setup_partials(self): self.declare_partials( '*', [ - Dynamic.MASS, Dynamic.THRUST_TOTAL, 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE], + Dynamic.Mission.MASS, Dynamic.Mission.THRUST_TOTAL, 'angle_of_attack', + Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=rows_cols, cols=rows_cols) self.declare_partials( - 'climb_gradient_forces_horizontal', Dynamic.DRAG, val=-1., + 'climb_gradient_forces_horizontal', Dynamic.Mission.DRAG, val=-1., rows=rows_cols, cols=rows_cols) self.declare_partials( - 'climb_gradient_forces_vertical', Dynamic.DRAG, dependent=False) + 'climb_gradient_forces_vertical', Dynamic.Mission.DRAG, dependent=False) self.declare_partials( - 'climb_gradient_forces_horizontal', Dynamic.LIFT, dependent=False) + 'climb_gradient_forces_horizontal', Dynamic.Mission.LIFT, dependent=False) self.declare_partials( - 'climb_gradient_forces_vertical', Dynamic.LIFT, val=1., + 'climb_gradient_forces_vertical', Dynamic.Mission.LIFT, val=1., rows=rows_cols, cols=rows_cols) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): @@ -740,15 +749,15 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc @@ -774,15 +783,15 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.MASS] - lift = inputs[Dynamic.LIFT] - thrust = inputs[Dynamic.THRUST_TOTAL] - drag = inputs[Dynamic.DRAG] + mass = inputs[Dynamic.Mission.MASS] + lift = inputs[Dynamic.Mission.LIFT] + thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + drag = inputs[Dynamic.Mission.DRAG] weight = mass * grav_metric alpha = inputs['angle_of_attack'] - gamma = inputs[Dynamic.FLIGHT_PATH_ANGLE] + gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc @@ -795,14 +804,14 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h_key = 'climb_gradient_forces_horizontal' f_v_key = 'climb_gradient_forces_vertical' - J[f_h_key, Dynamic.MASS] = -grav_metric * s_gamma - J[f_v_key, Dynamic.MASS] = -grav_metric * c_gamma + J[f_h_key, Dynamic.Mission.MASS] = -grav_metric * s_gamma + J[f_v_key, Dynamic.Mission.MASS] = -grav_metric * c_gamma - J[f_h_key, Dynamic.THRUST_TOTAL] = c_angle - J[f_v_key, Dynamic.THRUST_TOTAL] = s_angle + J[f_h_key, Dynamic.Mission.THRUST_TOTAL] = c_angle + J[f_v_key, Dynamic.Mission.THRUST_TOTAL] = s_angle J[f_h_key, 'angle_of_attack'] = -thrust * s_angle J[f_v_key, 'angle_of_attack'] = thrust * c_angle - J[f_h_key, Dynamic.FLIGHT_PATH_ANGLE] = -weight * c_gamma - J[f_v_key, Dynamic.FLIGHT_PATH_ANGLE] = weight * s_gamma + J[f_h_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -weight * c_gamma + J[f_v_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = weight * s_gamma diff --git a/aviary/mission/flops_based/ode/takeoff_ode.py b/aviary/mission/flops_based/ode/takeoff_ode.py index 73accaa91..e8304e181 100644 --- a/aviary/mission/flops_based/ode/takeoff_ode.py +++ b/aviary/mission/flops_based/ode/takeoff_ode.py @@ -9,13 +9,9 @@ from aviary.mission.gasp_based.flight_conditions import FlightConditions from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values, promote_aircraft_and_mission_vars -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.variables_in import VariablesIn -Dynamic = _Dynamic.Mission - class ExternalSubsystemGroup(om.Group): def configure(self): @@ -77,16 +73,18 @@ def setup(self): self.add_subsystem( "USatm", USatm1976Comp(num_nodes=nn), - promotes_inputs=[("h", Dynamic.ALTITUDE)], + promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], promotes_outputs=[ - "rho", ("sos", Dynamic.SPEED_OF_SOUND), ("temp", Dynamic.TEMPERATURE), - ("pres", Dynamic.STATIC_PRESSURE), "viscosity"]) + "rho", ("sos", Dynamic.Mission.SPEED_OF_SOUND), ("temp", + Dynamic.Mission.TEMPERATURE), + ("pres", Dynamic.Mission.STATIC_PRESSURE), "viscosity"]) self.add_subsystem( "fc", FlightConditions(num_nodes=nn), - promotes_inputs=["rho", Dynamic.SPEED_OF_SOUND, ("TAS", Dynamic.VELOCITY)], - promotes_outputs=[Dynamic.DYNAMIC_PRESSURE, Dynamic.MACH, "EAS"]) + promotes_inputs=["rho", Dynamic.Mission.SPEED_OF_SOUND, + ("TAS", Dynamic.Mission.VELOCITY)], + promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MACH, "EAS"]) # NOTE: the following are potentially signficant differences in implementation # between FLOPS and Aviary: @@ -154,11 +152,11 @@ def setup(self): self.add_subsystem( 'eoms', TakeoffEOM(**kwargs), promotes_inputs=[ - Dynamic.FLIGHT_PATH_ANGLE, Dynamic.VELOCITY, Dynamic.MASS, Dynamic.LIFT, - Dynamic.THRUST_TOTAL, Dynamic.DRAG, 'angle_of_attack'], + Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, 'angle_of_attack'], promotes_outputs=[ - Dynamic.RANGE_RATE, Dynamic.ALTITUDE_RATE, Dynamic.VELOCITY_RATE, - Dynamic.FLIGHT_PATH_ANGLE_RATE]) + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE]) self.add_subsystem( 'comp_v_ratio', @@ -168,11 +166,11 @@ def setup(self): v={'units': 'm/s', 'shape': nn}, # NOTE: FLOPS detailed takeoff stall speed is not dynamic - see above v_stall={'units': 'm/s', 'shape': nn}), - promotes_inputs=[('v', Dynamic.VELOCITY), 'v_stall'], + promotes_inputs=[('v', Dynamic.Mission.VELOCITY), 'v_stall'], promotes_outputs=['v_over_v_stall']) - self.set_input_defaults(Dynamic.ALTITUDE, np.zeros(nn), 'm') - self.set_input_defaults(Dynamic.VELOCITY, np.zeros(nn), 'm/s') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn), 'm') + self.set_input_defaults(Dynamic.Mission.VELOCITY, np.zeros(nn), 'm/s') self.set_input_defaults(Mission.Design.GROSS_MASS, val=1.0, units='kg') set_aviary_initial_values(self, aviary_options) diff --git a/aviary/mission/flops_based/ode/test/test_landing_eom.py b/aviary/mission/flops_based/ode/test/test_landing_eom.py index 0afa883eb..ef4903f4e 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_eom.py +++ b/aviary/mission/flops_based/ode/test/test_landing_eom.py @@ -6,9 +6,7 @@ from aviary.models.N3CC.N3CC_data import ( detailed_landing_flare, inputs) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic as _Dynamic - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic class FlareEOMTest(unittest.TestCase): @@ -34,15 +32,15 @@ def test_case(self): output_validation_data=detailed_landing_flare, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE], tol=1e-2, atol=1e-8, rtol=5e-10) diff --git a/aviary/mission/flops_based/ode/test/test_landing_ode.py b/aviary/mission/flops_based/ode/test/test_landing_ode.py index 16e34c0f2..526fbc9cf 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_ode.py +++ b/aviary/mission/flops_based/ode/test/test_landing_ode.py @@ -7,9 +7,7 @@ from aviary.models.N3CC.N3CC_data import ( detailed_landing_flare, inputs, landing_subsystem_options) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic as _Dynamic - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic class FlareODETest(unittest.TestCase): @@ -39,15 +37,15 @@ def test_case(self): output_validation_data=detailed_landing_flare, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE], tol=1e-2, atol=5e-9, rtol=5e-9, check_values=False, check_partials=True) diff --git a/aviary/mission/flops_based/ode/test/test_mission_EOM.py b/aviary/mission/flops_based/ode/test/test_mission_EOM.py index c2210d1f1..ea8e6be39 100644 --- a/aviary/mission/flops_based/ode/test/test_mission_EOM.py +++ b/aviary/mission/flops_based/ode/test/test_mission_EOM.py @@ -42,7 +42,7 @@ def test_case1(self): # - actual: 760.55416759 # - desired: 3.86361517135375 # Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.RANGE_RATE, + Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS], tol=1e-12) diff --git a/aviary/mission/flops_based/ode/test/test_range_rate.py b/aviary/mission/flops_based/ode/test/test_range_rate.py index 7809e849e..e371e2212 100644 --- a/aviary/mission/flops_based/ode/test/test_range_rate.py +++ b/aviary/mission/flops_based/ode/test/test_range_rate.py @@ -17,7 +17,7 @@ def setUp(self): time, _ = data.get_item('time') prob.model.add_subsystem( - Dynamic.Mission.RANGE_RATE, + Dynamic.Mission.DISTANCE_RATE, RangeRate(num_nodes=len(time)), promotes_inputs=['*'], promotes_outputs=['*'], @@ -33,7 +33,7 @@ def test_case1(self): output_validation_data=data, input_keys=[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], - output_keys=Dynamic.Mission.RANGE_RATE, + output_keys=Dynamic.Mission.DISTANCE_RATE, tol=1e-12) def test_IO(self): diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_eom.py b/aviary/mission/flops_based/ode/test/test_takeoff_eom.py index 6494143ba..f92e04771 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_eom.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_eom.py @@ -6,10 +6,7 @@ from aviary.models.N3CC.N3CC_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, inputs) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission class TakeoffEOMTest(unittest.TestCase): @@ -23,16 +20,16 @@ def test_case_ground(self): output_validation_data=detailed_takeoff_ground, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE, - Dynamic.VELOCITY_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY_RATE], tol=1e-2) def test_case_climbing(self): @@ -45,16 +42,16 @@ def test_case_climbing(self): output_validation_data=detailed_takeoff_climbing, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE, - Dynamic.VELOCITY_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY_RATE], tol=1e-2, atol=1e-9, rtol=1e-11) @staticmethod diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py index fd39339e5..6ffbf6e20 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py @@ -8,10 +8,7 @@ from aviary.models.N3CC.N3CC_data import ( detailed_takeoff_climbing, detailed_takeoff_ground, takeoff_subsystem_options, inputs) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission takeoff_subsystem_options = deepcopy(takeoff_subsystem_options) @@ -27,17 +24,17 @@ def test_case_ground(self): output_validation_data=detailed_takeoff_ground, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.ALTITUDE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.ALTITUDE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE, - Dynamic.VELOCITY_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY_RATE], tol=1e-2, atol=1e-9, rtol=1e-11, check_values=False, check_partials=True) @@ -51,17 +48,17 @@ def test_case_climbing(self): output_validation_data=detailed_takeoff_climbing, input_keys=[ 'angle_of_attack', - Dynamic.FLIGHT_PATH_ANGLE, - Dynamic.ALTITUDE, - Dynamic.VELOCITY, - Dynamic.MASS, - Dynamic.LIFT, - Dynamic.THRUST_TOTAL, - Dynamic.DRAG], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.ALTITUDE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.MASS, + Dynamic.Mission.LIFT, + Dynamic.Mission.THRUST_TOTAL, + Dynamic.Mission.DRAG], output_keys=[ - Dynamic.RANGE_RATE, - Dynamic.ALTITUDE_RATE, - Dynamic.VELOCITY_RATE], + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY_RATE], tol=1e-2, atol=1e-9, rtol=1e-11, check_values=False, check_partials=True) diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py index 002760085..7c7c97277 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py @@ -149,8 +149,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') + prob.set_val('traj.climb.states:distance', climb.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -179,7 +179,7 @@ def bench_test_climb_large_single_aisle_1(self): times = prob.get_val('traj.climb.timeseries.time', units='s') altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py index f03466f7f..761b30e97 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py @@ -152,8 +152,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + prob.set_val('traj.climb.states:distance', climb.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -182,7 +182,7 @@ def bench_test_climb_large_single_aisle_2(self): times = prob.get_val('traj.climb.timeseries.time', units='s') altitudes = prob.get_val('traj.climb.timeseries.states:altitude', units='m') masses = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities = prob.get_val('traj.climb.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py index c88f5dd8e..7e6249379 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py @@ -172,8 +172,8 @@ def run_trajectory(): velocity_i_cruise, velocity_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -201,7 +201,7 @@ def bench_test_cruise_climb_large_single_aisle_1(self): times = prob.get_val('traj.cruise.timeseries.time', units='s') altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py index b9925cf5b..353a9acc0 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py @@ -171,8 +171,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -203,7 +203,7 @@ def bench_test_cruise_large_single_aisle_1(self): times = prob.get_val('traj.cruise.timeseries.time', units='s') altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py index 8e1cfae23..26f8a4a1b 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py @@ -162,8 +162,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -194,7 +194,7 @@ def bench_test_cruise_large_single_asile_2(self): times = prob.get_val('traj.cruise.timeseries.time', units='s') altitudes = prob.get_val('traj.cruise.timeseries.states:altitude', units='m') masses = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities = prob.get_val('traj.cruise.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.cruise.timeseries.thrust_net', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py index c1dba6168..811648701 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py @@ -126,7 +126,7 @@ def run_trajectory(): descent = descent_options.build_phase(MissionODE, transcription) # descent.add_objective(Dynamic.Mission.MASS, ref=-1e4, loc='final') - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') + descent.add_objective(Dynamic.Mission.DISTANCE, ref=-1e5, loc='final') traj.add_phase('descent', descent) @@ -147,8 +147,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -177,7 +177,7 @@ def bench_test_descent_large_single_aisle_1(self): times = prob.get_val('traj.descent.timeseries.time', units='s') altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges = prob.get_val('traj.descent.timeseries.states:distance', units='m') velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py index e6378c4a2..251b86944 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py @@ -127,7 +127,7 @@ def run_trajectory(): descent = descent_options.build_phase(MissionODE, transcription) - descent.add_objective(Dynamic.Mission.RANGE, ref=-1e5, loc='final') + descent.add_objective(Dynamic.Mission.DISTANCE, ref=-1e5, loc='final') traj.add_phase('descent', descent) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -147,8 +147,8 @@ def run_trajectory(): Dynamic.Mission.VELOCITY, ys=[v_i, v_f]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i, mass_f]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i, range_f]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + Dynamic.Mission.DISTANCE, ys=[range_i, range_f]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -177,7 +177,7 @@ def bench_test_descent_large_single_aisle_2(self): times = prob.get_val('traj.descent.timeseries.time', units='s') altitudes = prob.get_val('traj.descent.timeseries.states:altitude', units='m') masses = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges = prob.get_val('traj.descent.timeseries.states:distance', units='m') velocities = prob.get_val('traj.descent.timeseries.states:velocity', units='m/s') thrusts = prob.get_val('traj.descent.timeseries.thrust_net', units='N') diff --git a/aviary/mission/flops_based/phases/cruise_phase.py b/aviary/mission/flops_based/phases/cruise_phase.py index 2f861c585..4bc0f4796 100644 --- a/aviary/mission/flops_based/phases/cruise_phase.py +++ b/aviary/mission/flops_based/phases/cruise_phase.py @@ -212,13 +212,13 @@ def build_phase(self, aviary_options: AviaryValues = None): input_initial=input_initial_mass ) - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) + input_initial_distance = get_initial(input_initial, Dynamic.Mission.DISTANCE) + fix_initial_distance = get_initial(fix_initial, Dynamic.Mission.DISTANCE, True) phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=fix_final, + Dynamic.Mission.DISTANCE, fix_initial=fix_initial_distance, fix_final=fix_final, lower=0.0, ref=range_f_cruise, defect_ref=range_f_cruise, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range + rate_source=Dynamic.Mission.DISTANCE_RATE, + input_initial=input_initial_distance ) phase = add_subsystem_variables_to_phase( @@ -413,7 +413,7 @@ def _extra_ode_init_kwargs(self): desc='initial guess for initial time and duration specified as a tuple') Cruise._add_initial_guess_meta_data( - InitialGuessState('range'), + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled') Cruise._add_initial_guess_meta_data( diff --git a/aviary/mission/flops_based/phases/detailed_landing_phases.py b/aviary/mission/flops_based/phases/detailed_landing_phases.py index e71d350c5..ee46b4a1e 100644 --- a/aviary/mission/flops_based/phases/detailed_landing_phases.py +++ b/aviary/mission/flops_based/phases/detailed_landing_phases.py @@ -37,10 +37,7 @@ InitialGuessState, PhaseBuilderBase) from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission @_init_initial_guess_meta_data @@ -151,39 +148,39 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, fix_final=False, + Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, upper=0, ref=max_range, defect_ref=max_range, units=units, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, fix_final=False, + Dynamic.Mission.ALTITUDE, fix_initial=False, fix_final=False, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, fix_final=False, + Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) - phase.add_control(Dynamic.FLIGHT_PATH_ANGLE, opt=False, fix_initial=True) + phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, opt=False, fix_initial=True) phase.add_state( - Dynamic.MASS, fix_initial=True, fix_final=False, + Dynamic.Mission.MASS, fix_initial=True, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -199,12 +196,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) initial_height, units = user_options.get_item('initial_height') @@ -215,7 +212,7 @@ def build_phase(self, aviary_options: AviaryValues = None): h = initial_height + airport_altitude phase.add_boundary_constraint( - Dynamic.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) return phase @@ -262,7 +259,7 @@ def _extra_ode_init_kwargs(self): LandingApproachToMicP3._add_initial_guess_meta_data(InitialGuessState('altitude')) LandingApproachToMicP3._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) # @_init_initial_guess_meta_data # <--- inherited from base class @@ -360,9 +357,9 @@ def build_phase(self, aviary_options: AviaryValues = None): # at the moment, these state options are the only differences between phases of # this class and phases of its base class - phase.set_state_options(Dynamic.RANGE, fix_final=True) - phase.set_state_options(Dynamic.VELOCITY, fix_final=True) - phase.set_state_options(Dynamic.MASS, fix_initial=False) + phase.set_state_options(Dynamic.Mission.DISTANCE, fix_final=True) + phase.set_state_options(Dynamic.Mission.VELOCITY, fix_final=True) + phase.set_state_options(Dynamic.Mission.MASS, fix_initial=False) return phase @@ -467,48 +464,49 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=True, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=max_range, defect_ref=max_range, units=units, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) - phase.add_control(Dynamic.FLIGHT_PATH_ANGLE, opt=False, fix_initial=False) + phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, + opt=False, fix_initial=False) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) phase.add_control('angle_of_attack', opt=False, units='deg') phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) obstacle_height, units = aviary_options.get_item( @@ -524,7 +522,7 @@ def build_phase(self, aviary_options: AviaryValues = None): h = obstacle_height + airport_altitude phase.add_boundary_constraint( - Dynamic.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) return phase @@ -559,7 +557,7 @@ def _extra_ode_init_kwargs(self): LandingObstacleToFlare._add_initial_guess_meta_data(InitialGuessState('altitude')) LandingObstacleToFlare._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -669,39 +667,40 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, fix_final=True, + Dynamic.Mission.ALTITUDE, fix_initial=False, fix_final=True, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) - phase.add_control(Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, opt=False) + phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, opt=False) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) # TODO: Upper limit is a bit of a hack. It hopefully won't be needed if we # can get some other constraints working. phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', lower=0.0, upper=0.2, opt=True ) @@ -719,12 +718,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_timeseries_output( @@ -783,7 +782,7 @@ def _extra_ode_init_kwargs(self): LandingFlareToTouchdown._add_initial_guess_meta_data(InitialGuessState('altitude')) LandingFlareToTouchdown._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -887,27 +886,27 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -920,12 +919,12 @@ def build_phase(self, aviary_options=None): fix_initial=False, ref=max_angle_of_attack) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) return phase @@ -1062,42 +1061,42 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, fix_final=False, + Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, lower=0, ref=max_range, defect_ref=max_range, units=units, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, fix_final=True, + Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=True, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) return phase @@ -1314,7 +1313,7 @@ def _add_phases(self, aviary_options: AviaryValues): def _link_phases(self): traj: dm.Trajectory = self._traj - basic_vars = ['time', 'range', 'velocity', 'mass'] + basic_vars = ['time', 'distance', 'velocity', 'mass'] ext_vars = basic_vars + ['angle_of_attack'] full_vars = ext_vars + ['altitude'] @@ -1329,7 +1328,7 @@ def _link_phases(self): obstacle_vars = ['mass', 'time', 'altitude', 'angle_of_attack'] traj.link_phases([p3_obstacle_name, obstacle_name], vars=obstacle_vars) - pre_obs_vars = obstacle_vars + ['range', 'velocity'] + pre_obs_vars = obstacle_vars + ['distance', 'velocity'] traj.link_phases([approach_p3_name, p3_obstacle_name], vars=pre_obs_vars) flare_name = self._flare_to_touchdown.name diff --git a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py index 742c774f8..e637c2a46 100644 --- a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py +++ b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py @@ -51,10 +51,7 @@ InitialGuessState, InitialGuessTime, PhaseBuilderBase) from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Dynamic, Mission def _init_initial_guess_meta_data(cls: PhaseBuilderBase): @@ -68,7 +65,7 @@ def _init_initial_guess_meta_data(cls: PhaseBuilderBase): desc='initial guess for initial time and duration specified as a tuple') cls._add_initial_guess_meta_data( - InitialGuessState('range'), + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled') cls._add_initial_guess_meta_data( @@ -185,40 +182,40 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=True, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) phase.add_state( - Dynamic.MASS, fix_initial=True, fix_final=False, + Dynamic.Mission.MASS, fix_initial=True, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) return phase @@ -355,28 +352,28 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -385,12 +382,12 @@ def build_phase(self, aviary_options=None): phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( @@ -636,29 +633,29 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) max_angle_of_attack, units = user_options.get_item('max_angle_of_attack') phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -668,12 +665,12 @@ def build_phase(self, aviary_options=None): ref=max_angle_of_attack) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_timeseries_output( @@ -824,42 +821,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=True, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=True, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, upper=altitude_ref, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=True, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=True, lower=0, ref=flight_path_angle_ref, upper=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -873,12 +870,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) obstacle_height, units = aviary_options.get_item( @@ -894,7 +891,7 @@ def build_phase(self, aviary_options: AviaryValues = None): h = obstacle_height + airport_altitude phase.add_boundary_constraint( - Dynamic.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) phase.add_path_constraint( 'v_over_v_stall', lower=1.25, ref=2.0) @@ -947,7 +944,7 @@ def _extra_ode_init_kwargs(self): TakeoffLiftoffToObstacle._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffLiftoffToObstacle._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -1060,42 +1057,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, ref=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -1109,12 +1106,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) final_alt, units = user_options.get_item('mic_altitude') @@ -1125,7 +1122,7 @@ def build_phase(self, aviary_options: AviaryValues = None): h = final_alt + airport_altitude phase.add_boundary_constraint( - Dynamic.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) phase.add_boundary_constraint( 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) @@ -1179,7 +1176,7 @@ def _extra_ode_init_kwargs(self): TakeoffObstacleToMicP2._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffObstacleToMicP2._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -1292,42 +1289,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, ref=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -1341,12 +1338,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) # start engine cutback phase at this range, where this phase ends @@ -1356,7 +1353,7 @@ def build_phase(self, aviary_options: AviaryValues = None): final_range, units = user_options.get_item('final_range') phase.add_boundary_constraint( - Dynamic.RANGE, loc='final', equals=final_range, ref=final_range, + Dynamic.Mission.DISTANCE, loc='final', equals=final_range, ref=final_range, units=units, linear=True) phase.add_boundary_constraint( @@ -1412,7 +1409,7 @@ def _extra_ode_init_kwargs(self): TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -1520,42 +1517,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, ref=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -1569,12 +1566,12 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) phase.add_boundary_constraint( @@ -1623,7 +1620,7 @@ def _extra_ode_init_kwargs(self): TakeoffEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffEngineCutback._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -1736,42 +1733,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, ref=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -1785,18 +1782,18 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) mic_range, units = user_options.get_item('mic_range') phase.add_boundary_constraint( - Dynamic.RANGE, loc='final', equals=mic_range, ref=mic_range, + Dynamic.Mission.DISTANCE, loc='final', equals=mic_range, ref=mic_range, units=units, linear=True) phase.add_boundary_constraint( @@ -1852,7 +1849,7 @@ def _extra_ode_init_kwargs(self): TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -1965,42 +1962,42 @@ def build_phase(self, aviary_options: AviaryValues = None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') phase.add_state( - Dynamic.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, + Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, defect_ref=altitude_ref, units=units, - rate_source=Dynamic.ALTITUDE_RATE) + rate_source=Dynamic.Mission.ALTITUDE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, + Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') phase.add_state( - Dynamic.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, ref=flight_path_angle_ref, defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.FLIGHT_PATH_ANGLE_RATE) + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -2014,18 +2011,18 @@ def build_phase(self, aviary_options: AviaryValues = None): ref=angle_of_attack_ref) phase.add_timeseries_output( - Dynamic.DRAG, output_name=Dynamic.DRAG, units='lbf' + Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.THRUST_TOTAL, - output_name=Dynamic.THRUST_TOTAL, units='lbf' + Dynamic.Mission.THRUST_TOTAL, + output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' ) mic_range, units = user_options.get_item('mic_range') phase.add_boundary_constraint( - Dynamic.RANGE, loc='final', equals=mic_range, ref=mic_range, + Dynamic.Mission.DISTANCE, loc='final', equals=mic_range, ref=mic_range, units=units, linear=True) phase.add_boundary_constraint( @@ -2080,7 +2077,7 @@ def _extra_ode_init_kwargs(self): TakeoffMicP1ToClimb._add_initial_guess_meta_data(InitialGuessState('altitude')) TakeoffMicP1ToClimb._add_initial_guess_meta_data( - InitialGuessState(Dynamic.FLIGHT_PATH_ANGLE)) + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) @_init_initial_guess_meta_data @@ -2185,28 +2182,28 @@ def build_phase(self, aviary_options=None): max_range, units = user_options.get_item('max_range') phase.add_state( - Dynamic.RANGE, fix_initial=False, lower=0, ref=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, defect_ref=max_range, units=units, upper=max_range, - rate_source=Dynamic.RANGE_RATE) + rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') phase.add_state( - Dynamic.VELOCITY, fix_initial=False, fix_final=True, + Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=True, lower=0, ref=max_velocity, upper=max_velocity, defect_ref=max_velocity, units=units, - rate_source=Dynamic.VELOCITY_RATE) + rate_source=Dynamic.Mission.VELOCITY_RATE) phase.add_state( - Dynamic.MASS, fix_initial=False, fix_final=False, + Dynamic.Mission.MASS, fix_initial=False, fix_final=False, lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.MASS, + rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Mission.MASS, ) phase.add_control( - Dynamic.THROTTLE, - targets=Dynamic.THROTTLE, units='unitless', + Dynamic.Mission.THROTTLE, + targets=Dynamic.Mission.THROTTLE, units='unitless', opt=False ) @@ -2519,7 +2516,7 @@ def _link_phases(self): brake_release_name = self._brake_release_to_decision_speed.name decision_speed_name = self._decision_speed_to_rotate.name - basic_vars = ['time', 'range', 'velocity', 'mass'] + basic_vars = ['time', 'distance', 'velocity', 'mass'] traj.link_phases([brake_release_name, decision_speed_name], vars=basic_vars) @@ -2542,7 +2539,7 @@ def _link_phases(self): engine_cutback_to_mic_p1_name = self._engine_cutback_to_mic_p1.name mic_p1_to_climb_name = self._mic_p1_to_climb.name - acoustics_vars = ext_vars + [Dynamic.FLIGHT_PATH_ANGLE, 'altitude'] + acoustics_vars = ext_vars + [Dynamic.Mission.FLIGHT_PATH_ANGLE, 'altitude'] traj.link_phases( [liftoff_name, obstacle_to_mic_p2_name], @@ -2574,8 +2571,8 @@ def _link_phases(self): traj.link_phases([brake_name, abort_name], vars=basic_vars) traj.add_linkage_constraint( - phase_a=abort_name, var_a='range', loc_a='final', - phase_b=liftoff_name, var_b='range', loc_b='final', + phase_a=abort_name, var_a='distance', loc_a='final', + phase_b=liftoff_name, var_b='distance', loc_b='final', ref=self._balanced_field_ref) def _add_phase(self, phase_builder: PhaseBuilderBase, aviary_options: AviaryValues): diff --git a/aviary/mission/flops_based/phases/energy_phase.py b/aviary/mission/flops_based/phases/energy_phase.py index 94ac79e4a..65f6c2f2e 100644 --- a/aviary/mission/flops_based/phases/energy_phase.py +++ b/aviary/mission/flops_based/phases/energy_phase.py @@ -242,13 +242,13 @@ def build_phase(self, aviary_options: AviaryValues = None): input_initial=input_initial_mass ) - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) + input_initial_distance = get_initial(input_initial, Dynamic.Mission.DISTANCE) + fix_initial_distance = get_initial(fix_initial, Dynamic.Mission.DISTANCE, True) phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=fix_range, + Dynamic.Mission.DISTANCE, fix_initial=fix_initial_distance, fix_final=fix_range, lower=0.0, ref=1e6, defect_ref=1e6, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range + rate_source=Dynamic.Mission.DISTANCE_RATE, + input_initial=input_initial_distance ) phase = add_subsystem_variables_to_phase( @@ -517,7 +517,7 @@ def _extra_ode_init_kwargs(self): desc='initial guess for initial time and duration specified as a tuple') EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('range'), + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled') EnergyPhase._add_initial_guess_meta_data( diff --git a/aviary/mission/flops_based/phases/simple_energy_phase.py b/aviary/mission/flops_based/phases/simple_energy_phase.py index e5ffd1928..0927925dc 100644 --- a/aviary/mission/flops_based/phases/simple_energy_phase.py +++ b/aviary/mission/flops_based/phases/simple_energy_phase.py @@ -189,13 +189,13 @@ def build_phase(self, aviary_options: AviaryValues = None): # solve_segments='forward', ) - input_initial_range = get_initial(input_initial, Dynamic.Mission.RANGE) - fix_initial_range = get_initial(fix_initial, Dynamic.Mission.RANGE, True) + input_initial_distance = get_initial(input_initial, Dynamic.Mission.DISTANCE) + fix_initial_distance = get_initial(fix_initial, Dynamic.Mission.DISTANCE, True) phase.add_state( - Dynamic.Mission.RANGE, fix_initial=fix_initial_range, fix_final=False, + Dynamic.Mission.DISTANCE, fix_initial=fix_initial_distance, fix_final=False, lower=0.0, ref=1e6, defect_ref=1e8, units='m', - rate_source=Dynamic.Mission.RANGE_RATE, - input_initial=input_initial_range, + rate_source=Dynamic.Mission.DISTANCE_RATE, + input_initial=input_initial_distance, solve_segments='forward' if solve_for_range else None, ) @@ -385,7 +385,7 @@ def _extra_ode_init_kwargs(self): desc='initial guess for initial time and duration specified as a tuple') EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('range'), + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled') EnergyPhase._add_initial_guess_meta_data( diff --git a/aviary/mission/gasp_based/phases/run_phases/run_climb.py b/aviary/mission/gasp_based/phases/run_phases/run_climb.py index fadcd2155..003222ec4 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_climb.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_climb.py @@ -28,7 +28,7 @@ "time": ("TIME", "time", "s"), Dynamic.Mission.ALTITUDE: ("ALT", "states:altitude", "ft"), "mass": ("MASS", "states:mass", "lbm"), - Dynamic.Mission.DISTANCE: (Dynamic.Mission.RANGE, "states:distance", "NM"), + Dynamic.Mission.DISTANCE: (Dynamic.Mission.DISTANCE, "states:distance", "NM"), Dynamic.Mission.MACH: ("MACH", Dynamic.Mission.MACH, None), "EAS": ("EAS", "EAS", "kn"), "alpha": ("ALPHA", "alpha", "deg"), diff --git a/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py b/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py index fc3283d4c..13d7c45fc 100644 --- a/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py +++ b/aviary/mission/gasp_based/phases/run_phases/run_climb_test_FLOPS_prop.py @@ -30,7 +30,7 @@ "time": ("TIME", "time", "s"), Dynamic.Mission.ALTITUDE: ("ALT", "states:altitude", "ft"), "mass": ("MASS", "states:mass", "lbm"), - Dynamic.Mission.DISTANCE: (Dynamic.Mission.RANGE, "states:distance", "NM"), + Dynamic.Mission.DISTANCE: (Dynamic.Mission.DISTANCE, "states:distance", "NM"), Dynamic.Mission.MACH: ("MACH", Dynamic.Mission.MACH, None), "EAS": ("EAS", "EAS", "kn"), "alpha": ("ALPHA", "alpha", "deg"), diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index a163553ea..c8cce58c9 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -21,14 +21,10 @@ from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission -from aviary.variable_info.variables import Settings +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings from aviary.variable_info.enums import EquationsOfMotion, LegacyCode from aviary.interface.default_phase_info.height_energy import default_mission_subsystems -Dynamic = _Dynamic.Mission N3CC = {} inputs = N3CC['inputs'] = AviaryValues() @@ -490,7 +486,7 @@ takeoff_brake_release_initial_guesses = AviaryValues() takeoff_brake_release_initial_guesses.set_val('times', [0., 30.], 's') -takeoff_brake_release_initial_guesses.set_val('range', [0., 4100.], 'ft') +takeoff_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft') takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn') gross_mass_units = 'lbm' @@ -523,7 +519,7 @@ takeoff_decision_speed_initial_guesses = AviaryValues() takeoff_decision_speed_initial_guesses.set_val('times', [30., 2.], 's') -takeoff_decision_speed_initial_guesses.set_val('range', [4100., 4500.], 'ft') +takeoff_decision_speed_initial_guesses.set_val('distance', [4100., 4500.], 'ft') takeoff_decision_speed_initial_guesses.set_val('velocity', [150., 160.], 'kn') takeoff_decision_speed_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_decision_speed_initial_guesses.set_val('throttle', 1.) @@ -552,7 +548,7 @@ takeoff_rotate_initial_guesses = AviaryValues() takeoff_rotate_initial_guesses.set_val('times', [32., 1.], 's') -takeoff_rotate_initial_guesses.set_val('range', [4500, 4800.0], 'ft') +takeoff_rotate_initial_guesses.set_val('distance', [4500, 4800.0], 'ft') takeoff_rotate_initial_guesses.set_val('velocity', [160., 160.0], 'kn') takeoff_rotate_initial_guesses.set_val('throttle', 1.) takeoff_rotate_initial_guesses.set_val('angle_of_attack', [0., 8.], 'deg') @@ -585,11 +581,12 @@ takeoff_liftoff_initial_guesses = AviaryValues() takeoff_liftoff_initial_guesses.set_val('times', [33., 4.], 's') -takeoff_liftoff_initial_guesses.set_val('range', [4800, 5700.0], 'ft') +takeoff_liftoff_initial_guesses.set_val('distance', [4800, 5700.0], 'ft') takeoff_liftoff_initial_guesses.set_val('velocity', [160, 167.0], 'kn') takeoff_liftoff_initial_guesses.set_val('throttle', 1.) takeoff_liftoff_initial_guesses.set_val('altitude', [0, 35.0], 'ft') -takeoff_liftoff_initial_guesses.set_val(Dynamic.FLIGHT_PATH_ANGLE, [0, 6.0], 'deg') +takeoff_liftoff_initial_guesses.set_val( + Dynamic.Mission.FLIGHT_PATH_ANGLE, [0, 6.0], 'deg') takeoff_liftoff_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') takeoff_liftoff_initial_guesses.set_val('mass', gross_mass, gross_mass_units) @@ -627,11 +624,12 @@ takeoff_mic_p2_initial_guesses = AviaryValues() takeoff_mic_p2_initial_guesses.set_val('times', [36., 18], 's') -takeoff_mic_p2_initial_guesses.set_val('range', [5700, 10000.0], 'ft') +takeoff_mic_p2_initial_guesses.set_val('distance', [5700, 10000.0], 'ft') takeoff_mic_p2_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_mic_p2_initial_guesses.set_val('throttle', 1.) takeoff_mic_p2_initial_guesses.set_val('altitude', [35, 985.0], 'ft') -takeoff_mic_p2_initial_guesses.set_val(Dynamic.FLIGHT_PATH_ANGLE, [7.0, 10.0], 'deg') +takeoff_mic_p2_initial_guesses.set_val( + Dynamic.Mission.FLIGHT_PATH_ANGLE, [7.0, 10.0], 'deg') takeoff_mic_p2_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') takeoff_mic_p2_initial_guesses.set_val('mass', gross_mass, gross_mass_units) @@ -679,13 +677,14 @@ takeoff_mic_p2_to_engine_cutback_initial_guesses = AviaryValues() takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('times', [53., 27], 's') -takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('range', [10000, 19000.0], 'ft') +takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val( + 'distance', [10000, 19000.0], 'ft') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('throttle', 1.0) takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('altitude', [985, 2500.0], 'ft') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, [11.0, 10.0], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [11.0, 10.0], 'deg') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') @@ -734,13 +733,13 @@ takeoff_engine_cutback_initial_guesses = AviaryValues() takeoff_engine_cutback_initial_guesses.set_val('times', [84., cutback_duration], 's') -takeoff_engine_cutback_initial_guesses.set_val('range', [19000, 20000.0], 'ft') +takeoff_engine_cutback_initial_guesses.set_val('distance', [19000, 20000.0], 'ft') takeoff_engine_cutback_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_engine_cutback_initial_guesses.set_val('throttle', [1.0, cutback_throttle]) takeoff_engine_cutback_initial_guesses.set_val('altitude', [2500.0, 2600.0], 'ft') takeoff_engine_cutback_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, [10.0, 10.0], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [10.0, 10.0], 'deg') takeoff_engine_cutback_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') takeoff_engine_cutback_initial_guesses.set_val('mass', gross_mass, gross_mass_units) @@ -792,7 +791,8 @@ takeoff_engine_cutback_to_mic_p1_initial_guesses = AviaryValues() takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('times', [87., 10], 's') -takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('range', [20000, 21325.0], 'ft') +takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( + 'distance', [20000, 21325.0], 'ft') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('throttle', cutback_throttle) @@ -800,7 +800,7 @@ 'altitude', [2600, 2700.0], 'ft') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, 2.29, 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( @@ -842,11 +842,12 @@ takeoff_mic_p1_to_climb_initial_guesses = AviaryValues() takeoff_mic_p1_to_climb_initial_guesses.set_val('times', [95., 32], 's') -takeoff_mic_p1_to_climb_initial_guesses.set_val('range', [21325, 30000.0], 'ft') +takeoff_mic_p1_to_climb_initial_guesses.set_val('distance', [21325, 30000.0], 'ft') takeoff_mic_p1_to_climb_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_mic_p1_to_climb_initial_guesses.set_val('throttle', cutback_throttle) takeoff_mic_p1_to_climb_initial_guesses.set_val('altitude', [2700, 3200.0], 'ft') -takeoff_mic_p1_to_climb_initial_guesses.set_val(Dynamic.FLIGHT_PATH_ANGLE, 2.29, 'deg') +takeoff_mic_p1_to_climb_initial_guesses.set_val( + Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg') takeoff_mic_p1_to_climb_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') takeoff_mic_p1_to_climb_initial_guesses.set_val('mass', gross_mass, gross_mass_units) @@ -867,51 +868,54 @@ detailed_takeoff = AviaryValues() detailed_takeoff.set_val('time', [0.77, 32.01, 33.00, 35.40], 's') -detailed_takeoff.set_val(Dynamic.RANGE, [3.08, 4626.88, 4893.40, 5557.61], 'ft') -detailed_takeoff.set_val(Dynamic.ALTITUDE, [0.00, 0.00, 0.64, 27.98], 'ft') +detailed_takeoff.set_val(Dynamic.Mission.DISTANCE, [ + 3.08, 4626.88, 4893.40, 5557.61], 'ft') +detailed_takeoff.set_val(Dynamic.Mission.ALTITUDE, [0.00, 0.00, 0.64, 27.98], 'ft') velocity = np.array([4.74, 157.58, 160.99, 166.68]) -detailed_takeoff.set_val(Dynamic.VELOCITY, velocity, 'kn') -detailed_takeoff.set_val(Dynamic.MACH, [0.007, 0.2342, 0.2393, 0.2477]) +detailed_takeoff.set_val(Dynamic.Mission.VELOCITY, velocity, 'kn') +detailed_takeoff.set_val(Dynamic.Mission.MACH, [0.007, 0.2342, 0.2393, 0.2477]) detailed_takeoff.set_val( - Dynamic.THRUST_TOTAL, [44038.8, 34103.4, 33929.0, 33638.2], 'lbf') + Dynamic.Mission.THRUST_TOTAL, [44038.8, 34103.4, 33929.0, 33638.2], 'lbf') detailed_takeoff.set_val('angle_of_attack', [0.000, 3.600, 8.117, 8.117], 'deg') -detailed_takeoff.set_val(Dynamic.FLIGHT_PATH_ANGLE, [0.000, 0.000, 0.612, 4.096], 'deg') +detailed_takeoff.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [ + 0.000, 0.000, 0.612, 4.096], 'deg') # missing from the default FLOPS output generated by hand # RANGE_RATE = VELOCITY * cos(flight_path_angle) range_rate = np.array([4.74, 157.58, 160.98, 166.25]) -detailed_takeoff.set_val(Dynamic.RANGE_RATE, range_rate, 'kn') +detailed_takeoff.set_val(Dynamic.Mission.DISTANCE_RATE, range_rate, 'kn') # ALTITUDE_RATE = VELOCITY * sin(flight_path_angle) altitude_rate = np.array([0.00, 0.00, 1.72, 11.91]) -detailed_takeoff.set_val(Dynamic.ALTITUDE_RATE, altitude_rate, 'kn') +detailed_takeoff.set_val(Dynamic.Mission.ALTITUDE_RATE, altitude_rate, 'kn') # NOTE FLOPS output is horizontal acceleration only # - divide the FLOPS values by the cos(flight_path_angle) -# detailed_takeoff.set_val(Dynamic.VELOCITY_RATE, [10.36, 6.20, 5.23, 2.69], 'ft/s**2') +# detailed_takeoff.set_val(Dynamic.Mission.VELOCITY_RATE, [10.36, 6.20, 5.23, 2.69], 'ft/s**2') velocity_rate = [10.36, 6.20, 5.23, 2.70] -detailed_takeoff.set_val(Dynamic.VELOCITY_RATE, velocity_rate, 'ft/s**2') +detailed_takeoff.set_val(Dynamic.Mission.VELOCITY_RATE, velocity_rate, 'ft/s**2') # NOTE FLOPS output is based on "constant" takeoff mass - assume gross weight # - currently neglecting taxi -detailed_takeoff.set_val(Dynamic.MASS, [129734., 129734., 129734., 129734.], 'lbm') +detailed_takeoff.set_val(Dynamic.Mission.MASS, [ + 129734., 129734., 129734., 129734.], 'lbm') lift_coeff = np.array([0.5580, 0.9803, 1.4831, 1.3952]) drag_coeff = np.array([0.0801, 0.0859, 0.1074, 0.1190]) S = inputs.get_val(Aircraft.Wing.AREA, 'm**2') -v = detailed_takeoff.get_val(Dynamic.VELOCITY, 'm/s') +v = detailed_takeoff.get_val(Dynamic.Mission.VELOCITY, 'm/s') # NOTE sea level; includes effect of FLOPS &TOLIN DTCT 10 DEG C rho = 1.18391 # kg/m**3 RHV2 = 0.5 * rho * v * v * S lift = RHV2 * lift_coeff # N -detailed_takeoff.set_val(Dynamic.LIFT, lift, 'N') +detailed_takeoff.set_val(Dynamic.Mission.LIFT, lift, 'N') drag = RHV2 * drag_coeff # N -detailed_takeoff.set_val(Dynamic.DRAG, drag, 'N') +detailed_takeoff.set_val(Dynamic.Mission.DRAG, drag, 'N') def _split_aviary_values(aviary_values, slicing): @@ -941,7 +945,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_brake_release_initial_guesses = AviaryValues() balanced_brake_release_initial_guesses.set_val('times', [0., 30.], 's') -balanced_brake_release_initial_guesses.set_val('range', [0., 4100.], 'ft') +balanced_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft') balanced_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn') balanced_brake_release_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_brake_release_initial_guesses.set_val('throttle', 1.) @@ -971,7 +975,7 @@ def _split_aviary_values(aviary_values, slicing): engine_out_throttle = (num_engines - 1) / num_engines balanced_decision_speed_initial_guesses.set_val('times', [30., 2.], 's') -balanced_decision_speed_initial_guesses.set_val('range', [4100., 4500.], 'ft') +balanced_decision_speed_initial_guesses.set_val('distance', [4100., 4500.], 'ft') balanced_decision_speed_initial_guesses.set_val('velocity', [150., 160.], 'kn') balanced_decision_speed_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_decision_speed_initial_guesses.set_val('throttle', engine_out_throttle) @@ -999,7 +1003,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_rotate_initial_guesses = AviaryValues() balanced_rotate_initial_guesses.set_val('times', [32., 1.], 's') -balanced_rotate_initial_guesses.set_val('range', [4500., 4800.], 'ft') +balanced_rotate_initial_guesses.set_val('distance', [4500., 4800.], 'ft') balanced_rotate_initial_guesses.set_val('velocity', [160., 160.], 'kn') balanced_rotate_initial_guesses.set_val('throttle', engine_out_throttle) balanced_rotate_initial_guesses.set_val('angle_of_attack', [0., 8.], 'deg') @@ -1031,11 +1035,12 @@ def _split_aviary_values(aviary_values, slicing): balanced_liftoff_initial_guesses = AviaryValues() balanced_liftoff_initial_guesses.set_val('times', [33., 4.], 's') -balanced_liftoff_initial_guesses.set_val('range', [4800., 7000.], 'ft') +balanced_liftoff_initial_guesses.set_val('distance', [4800., 7000.], 'ft') balanced_liftoff_initial_guesses.set_val('velocity', [160., 167.], 'kn') balanced_liftoff_initial_guesses.set_val('throttle', engine_out_throttle) balanced_liftoff_initial_guesses.set_val('altitude', [0., 35.], 'ft') -balanced_liftoff_initial_guesses.set_val(Dynamic.FLIGHT_PATH_ANGLE, [0., 5.], 'deg') +balanced_liftoff_initial_guesses.set_val( + Dynamic.Mission.FLIGHT_PATH_ANGLE, [0., 5.], 'deg') balanced_liftoff_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') balanced_liftoff_initial_guesses.set_val('mass', gross_mass, gross_mass_units) @@ -1059,7 +1064,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_delayed_brake_initial_guesses = AviaryValues() balanced_delayed_brake_initial_guesses.set_val('times', [30., 3.], 's') -balanced_delayed_brake_initial_guesses.set_val('range', [4100., 4600.], 'ft') +balanced_delayed_brake_initial_guesses.set_val('distance', [4100., 4600.], 'ft') balanced_delayed_brake_initial_guesses.set_val('velocity', [150., 150.], 'kn') balanced_delayed_brake_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_delayed_brake_initial_guesses.set_val('throttle', engine_out_throttle) @@ -1086,7 +1091,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_abort_initial_guesses = AviaryValues() balanced_abort_initial_guesses.set_val('times', [32., 22.], 's') -balanced_abort_initial_guesses.set_val('range', [4600., 7000.], 'ft') +balanced_abort_initial_guesses.set_val('distance', [4600., 7000.], 'ft') balanced_abort_initial_guesses.set_val('velocity', [150., 0.01], 'kn') balanced_abort_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_abort_initial_guesses.set_val('throttle', 0.) @@ -1179,10 +1184,10 @@ def _split_aviary_values(aviary_values, slicing): base = values[0] values = values - base -detailed_landing.set_val(Dynamic.RANGE, values, 'ft') +detailed_landing.set_val(Dynamic.Mission.DISTANCE, values, 'ft') detailed_landing.set_val( - Dynamic.ALTITUDE, + Dynamic.Mission.ALTITUDE, [ 100, 100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 74, 72, 70, 68, 66, 64, @@ -1194,7 +1199,7 @@ def _split_aviary_values(aviary_values, slicing): 'ft') detailed_landing.set_val( - Dynamic.VELOCITY, + Dynamic.Mission.VELOCITY, np.array([ 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, @@ -1206,7 +1211,7 @@ def _split_aviary_values(aviary_values, slicing): 'kn') detailed_landing.set_val( - Dynamic.MACH, + Dynamic.Mission.MACH, [ 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, @@ -1217,7 +1222,7 @@ def _split_aviary_values(aviary_values, slicing): 0.086, 0.0756, 0.0653, 0.0551, 0.045, 0.035, 0.025, 0.015, 0.0051, 0]) detailed_landing.set_val( - Dynamic.THRUST_TOTAL, + Dynamic.Mission.THRUST_TOTAL, [ 7614, 7614, 7607.7, 7601, 7593.9, 7586.4, 7578.5, 7570.2, 7561.3, 7551.8, 7541.8, 7531.1, 7519.7, 7507.6, 7494.6, 7480.6, 7465.7, 7449.7, 7432.5, 7414, @@ -1242,7 +1247,7 @@ def _split_aviary_values(aviary_values, slicing): # glide slope == flight path angle? detailed_landing.set_val( - Dynamic.FLIGHT_PATH_ANGLE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, @@ -1255,13 +1260,13 @@ def _split_aviary_values(aviary_values, slicing): # missing from the default FLOPS output generated by script # RANGE_RATE = VELOCITY * cos(flight_path_angle) -velocity: np.ndarray = detailed_landing.get_val(Dynamic.VELOCITY, 'kn') -flight_path_angle = detailed_landing.get_val(Dynamic.FLIGHT_PATH_ANGLE, 'rad') +velocity: np.ndarray = detailed_landing.get_val(Dynamic.Mission.VELOCITY, 'kn') +flight_path_angle = detailed_landing.get_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 'rad') range_rate = velocity * np.cos(-flight_path_angle) -detailed_landing.set_val(Dynamic.RANGE_RATE, range_rate, 'kn') +detailed_landing.set_val(Dynamic.Mission.DISTANCE_RATE, range_rate, 'kn') # ALTITUDE_RATE = VELOCITY * sin(flight_path_angle) altitude_rate = velocity * np.sin(flight_path_angle) -detailed_landing.set_val(Dynamic.ALTITUDE_RATE, altitude_rate, 'kn') +detailed_landing.set_val(Dynamic.Mission.ALTITUDE_RATE, altitude_rate, 'kn') # NOTE FLOPS output is horizontal acceleration only, and virtually no acceleration while # airborne @@ -1272,7 +1277,7 @@ def _split_aviary_values(aviary_values, slicing): detailed_landing_mass = 106292. # units='lbm' detailed_landing.set_val( - Dynamic.MASS, np.full(velocity.shape, detailed_landing_mass), 'lbm') + Dynamic.Mission.MASS, np.full(velocity.shape, detailed_landing_mass), 'lbm') # lift/drag is calculated very close to landing altitude (sea level, in this case)... lift_coeff = np.array([ @@ -1294,17 +1299,17 @@ def _split_aviary_values(aviary_values, slicing): 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785]) S = inputs.get_val(Aircraft.Wing.AREA, 'm**2') -v = detailed_landing.get_val(Dynamic.VELOCITY, 'm/s') +v = detailed_landing.get_val(Dynamic.Mission.VELOCITY, 'm/s') # NOTE sea level; includes effect of FLOPS &TOLIN DTCT 10 DEG C rho = 1.18391 # kg/m**3 RHV2 = 0.5 * rho * v * v * S lift = RHV2 * lift_coeff # N -detailed_landing.set_val(Dynamic.LIFT, lift, 'N') +detailed_landing.set_val(Dynamic.Mission.LIFT, lift, 'N') drag = RHV2 * drag_coeff # N -detailed_landing.set_val(Dynamic.DRAG, drag, 'N') +detailed_landing.set_val(Dynamic.Mission.DRAG, drag, 'N') # Flops variable APRANG apr_angle = -3.0 # deg @@ -1338,14 +1343,14 @@ def _split_aviary_values(aviary_values, slicing): landing_approach_to_mic_p3_initial_guesses = AviaryValues() landing_approach_to_mic_p3_initial_guesses.set_val('times', [-42., 15.], 's') -landing_approach_to_mic_p3_initial_guesses.set_val('range', [-4000., -2000.], 'ft') +landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000., -2000.], 'ft') landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140., 'kn') landing_approach_to_mic_p3_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_approach_to_mic_p3_initial_guesses.set_val('throttle', throttle) landing_approach_to_mic_p3_initial_guesses.set_val('altitude', [600., 394.], 'ft') landing_approach_to_mic_p3_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') landing_approach_to_mic_p3_initial_guesses.set_val('angle_of_attack', 5.25, 'deg') @@ -1389,14 +1394,14 @@ def _split_aviary_values(aviary_values, slicing): landing_mic_p3_to_obstacle_initial_guesses = AviaryValues() landing_mic_p3_to_obstacle_initial_guesses.set_val('times', [-27., 27.], 's') -landing_mic_p3_to_obstacle_initial_guesses.set_val('range', [-2000., 0.], 'ft') +landing_mic_p3_to_obstacle_initial_guesses.set_val('distance', [-2000., 0.], 'ft') landing_mic_p3_to_obstacle_initial_guesses.set_val('velocity', 140., 'kn') landing_mic_p3_to_obstacle_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_mic_p3_to_obstacle_initial_guesses.set_val('throttle', throttle) landing_mic_p3_to_obstacle_initial_guesses.set_val('altitude', [394., 50.], 'ft') landing_mic_p3_to_obstacle_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') landing_mic_p3_to_obstacle_initial_guesses.set_val('angle_of_attack', 5.25, 'deg') @@ -1427,14 +1432,14 @@ def _split_aviary_values(aviary_values, slicing): landing_obstacle_initial_guesses = AviaryValues() landing_obstacle_initial_guesses.set_val('times', [0., 4.], 's') -landing_obstacle_initial_guesses.set_val('range', [0., 800.], 'ft') +landing_obstacle_initial_guesses.set_val('distance', [0., 800.], 'ft') landing_obstacle_initial_guesses.set_val('velocity', 140., 'kn') landing_obstacle_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_obstacle_initial_guesses.set_val('throttle', throttle) landing_obstacle_initial_guesses.set_val('altitude', [50., 15.], 'ft') landing_obstacle_initial_guesses.set_val( - Dynamic.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') landing_obstacle_initial_guesses.set_val('angle_of_attack', 5.2, 'deg') @@ -1469,12 +1474,13 @@ def _split_aviary_values(aviary_values, slicing): landing_flare_initial_guesses = AviaryValues() landing_flare_initial_guesses.set_val('times', [4., 6.], 's') -landing_flare_initial_guesses.set_val('range', [800., 1000.], 'ft') +landing_flare_initial_guesses.set_val('distance', [800., 1000.], 'ft') landing_flare_initial_guesses.set_val('velocity', 140., 'kn') landing_flare_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_flare_initial_guesses.set_val('throttle', [throttle, throttle*4/7]) landing_flare_initial_guesses.set_val('altitude', [15., 0.], 'ft') -landing_flare_initial_guesses.set_val(Dynamic.FLIGHT_PATH_ANGLE, [apr_angle, 0.], 'deg') +landing_flare_initial_guesses.set_val( + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, 0.], 'deg') landing_flare_initial_guesses.set_val('angle_of_attack', [5.2, 7.5], 'deg') landing_flare_builder = LandingFlareToTouchdown( @@ -1504,7 +1510,7 @@ def _split_aviary_values(aviary_values, slicing): landing_touchdown_initial_guesses = AviaryValues() landing_touchdown_initial_guesses.set_val('times', [6., 9.], 's') -landing_touchdown_initial_guesses.set_val('range', [1000., 1400.], 'ft') +landing_touchdown_initial_guesses.set_val('distance', [1000., 1400.], 'ft') landing_touchdown_initial_guesses.set_val('velocity', [140., 135.], 'kn') landing_touchdown_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_touchdown_initial_guesses.set_val('throttle', 0.) @@ -1536,7 +1542,7 @@ def _split_aviary_values(aviary_values, slicing): landing_fullstop_initial_guesses = AviaryValues() landing_fullstop_initial_guesses.set_val('times', [9., 29.], 's') -landing_fullstop_initial_guesses.set_val('range', [1400., 3500.], 'ft') +landing_fullstop_initial_guesses.set_val('distance', [1400., 3500.], 'ft') landing_fullstop_initial_guesses.set_val('velocity', [135., 0.01], 'kn') landing_fullstop_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_fullstop_initial_guesses.set_val('throttle', 0.) diff --git a/aviary/subsystems/aerodynamics/flops_based/ground_effect.py b/aviary/subsystems/aerodynamics/flops_based/ground_effect.py index 27aee4eee..8a6efb8dc 100644 --- a/aviary/subsystems/aerodynamics/flops_based/ground_effect.py +++ b/aviary/subsystems/aerodynamics/flops_based/ground_effect.py @@ -11,10 +11,7 @@ import openmdao.api as om from aviary.variable_info.functions import add_aviary_input -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Aircraft, Dynamic class GroundEffect(om.ExplicitComponent): @@ -41,9 +38,10 @@ def setup(self): self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.ALTITUDE, np.zeros(nn), units='m') + add_aviary_input(self, Dynamic.Mission.ALTITUDE, np.zeros(nn), units='m') - add_aviary_input(self, Dynamic.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), units='rad') self.add_input( 'minimum_drag_coefficient', 0.0, @@ -83,14 +81,14 @@ def setup_partials(self): ) self.declare_partials( - 'lift_coefficient', [Dynamic.ALTITUDE, 'base_lift_coefficient'], + 'lift_coefficient', [Dynamic.Mission.ALTITUDE, 'base_lift_coefficient'], rows=rows_cols, cols=rows_cols ) self.declare_partials( 'lift_coefficient', [ - 'angle_of_attack', Dynamic.FLIGHT_PATH_ANGLE, 'minimum_drag_coefficient', + 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE, 'minimum_drag_coefficient', 'base_drag_coefficient', ], dependent=False @@ -104,7 +102,7 @@ def setup_partials(self): self.declare_partials( 'drag_coefficient', [ - 'angle_of_attack', Dynamic.ALTITUDE, Dynamic.FLIGHT_PATH_ANGLE, + 'angle_of_attack', Dynamic.Mission.ALTITUDE, Dynamic.Mission.FLIGHT_PATH_ANGLE, 'base_drag_coefficient', 'base_lift_coefficient' ], rows=rows_cols, cols=rows_cols @@ -121,8 +119,8 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): ground_altitude = options['ground_altitude'] angle_of_attack = inputs['angle_of_attack'] - altitude = inputs[Dynamic.ALTITUDE] - flight_path_angle = inputs[Dynamic.FLIGHT_PATH_ANGLE] + altitude = inputs[Dynamic.Mission.ALTITUDE] + flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] minimum_drag_coefficient = inputs['minimum_drag_coefficient'] base_lift_coefficient = inputs['base_lift_coefficient'] base_drag_coefficient = inputs['base_drag_coefficient'] @@ -177,8 +175,8 @@ def compute_partials(self, inputs, J, discrete_inputs=None): ground_altitude = options['ground_altitude'] angle_of_attack = inputs['angle_of_attack'] - altitude = inputs[Dynamic.ALTITUDE] - flight_path_angle = inputs[Dynamic.FLIGHT_PATH_ANGLE] + altitude = inputs[Dynamic.Mission.ALTITUDE] + flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] minimum_drag_coefficient = inputs['minimum_drag_coefficient'] base_lift_coefficient = inputs['base_lift_coefficient'] base_drag_coefficient = inputs['base_drag_coefficient'] @@ -224,7 +222,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): (d_hf_alt * lift_coeff_factor_denom) - (height_factor * d_lcfd_alt) ) / lift_coeff_factor_denom**2 - J['lift_coefficient', Dynamic.ALTITUDE] = base_lift_coefficient * d_lcf_alt + J['lift_coefficient', Dynamic.Mission.ALTITUDE] = base_lift_coefficient * d_lcf_alt J['lift_coefficient', 'base_lift_coefficient'] = lift_coeff_factor # endregion lift_coefficient wrt [altitude, base_lift_coefficient] @@ -306,7 +304,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): d_dc_fpa = base_lift_coefficient * (lift_coeff_factor - 1.) * d_ca_fpa - J['drag_coefficient', Dynamic.FLIGHT_PATH_ANGLE] = d_dc_fpa + J['drag_coefficient', Dynamic.Mission.FLIGHT_PATH_ANGLE] = d_dc_fpa # endregion drag_coefficient wrt flight_path_angle # region drag_coefficient wrt altitude @@ -336,7 +334,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): + combined_angle * base_lift_coefficient * d_lcf_alt ) - J['drag_coefficient', Dynamic.ALTITUDE] = d_dc_alt + J['drag_coefficient', Dynamic.Mission.ALTITUDE] = d_dc_alt # endregion drag_coefficient wrt altitude # region drag_coefficient wrt minimum_drag_coefficient @@ -401,7 +399,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # Check for out of ground effect. idx = np.where(ground_effect_state > 1.1) if idx: - J['drag_coefficient', Dynamic.ALTITUDE][idx] = 0.0 + J['drag_coefficient', Dynamic.Mission.ALTITUDE][idx] = 0.0 J['drag_coefficient', 'minimum_drag_coefficient'][idx] = 0.0 J['drag_coefficient', 'base_lift_coefficient'][idx] = 0.0 J['drag_coefficient', 'base_drag_coefficient'][idx] = 1.0 @@ -409,9 +407,9 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J['drag_coefficient', Aircraft.Wing.HEIGHT][idx] = 0.0 J['drag_coefficient', Aircraft.Wing.SPAN][idx] = 0.0 J['drag_coefficient', 'angle_of_attack'][idx] = 0.0 - J['drag_coefficient', Dynamic.FLIGHT_PATH_ANGLE][idx] = 0.0 + J['drag_coefficient', Dynamic.Mission.FLIGHT_PATH_ANGLE][idx] = 0.0 - J['lift_coefficient', Dynamic.ALTITUDE][idx] = 0.0 + J['lift_coefficient', Dynamic.Mission.ALTITUDE][idx] = 0.0 J['lift_coefficient', 'base_lift_coefficient'][idx] = 1.0 J['lift_coefficient', Aircraft.Wing.ASPECT_RATIO][idx] = 0.0 J['lift_coefficient', Aircraft.Wing.HEIGHT][idx] = 0.0 diff --git a/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py index d6245f60e..6185b25ca 100644 --- a/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py @@ -11,11 +11,7 @@ GroundEffect from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class TakeoffAeroGroup(om.Group): @@ -119,7 +115,7 @@ def setup(self): } inputs = [ - 'angle_of_attack', Dynamic.ALTITUDE, Dynamic.FLIGHT_PATH_ANGLE, + 'angle_of_attack', Dynamic.Mission.ALTITUDE, Dynamic.Mission.FLIGHT_PATH_ANGLE, ('minimum_drag_coefficient', Mission.Takeoff.DRAG_COEFFICIENT_MIN), Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, Aircraft.Wing.SPAN @@ -173,8 +169,8 @@ def setup(self): self.connect('ground_effect.drag_coefficient', 'ground_effect_drag') self.connect('climb_drag_coefficient', 'aero_forces.CD') - inputs = [Dynamic.DYNAMIC_PRESSURE, Aircraft.Wing.AREA] - outputs = [Dynamic.LIFT, Dynamic.DRAG] + inputs = [Dynamic.Mission.DYNAMIC_PRESSURE, Aircraft.Wing.AREA] + outputs = [Dynamic.Mission.LIFT, Dynamic.Mission.DRAG] self.add_subsystem( 'aero_forces', AeroForces(num_nodes=nn), diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py b/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py index 940981305..bfcf6c008 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py @@ -6,10 +6,7 @@ from aviary.subsystems.aerodynamics.flops_based.ground_effect import GroundEffect from aviary.utils.aviary_values import AviaryValues, get_items -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic - -Dynamic = _Dynamic.Mission +from aviary.variable_info.variables import Aircraft, Dynamic class TestGroundEffect(unittest.TestCase): @@ -61,8 +58,8 @@ def make_problem(): inputs = AviaryValues({ 'angle_of_attack': (np.array([0., 2., 6]), 'deg'), - Dynamic.ALTITUDE: (np.array([100.0, 132, 155]), 'm'), - Dynamic.FLIGHT_PATH_ANGLE: (np.array([0., 0.5, 1.0]), 'deg'), + Dynamic.Mission.ALTITUDE: (np.array([100.0, 132, 155]), 'm'), + Dynamic.Mission.FLIGHT_PATH_ANGLE: (np.array([0., 0.5, 1.0]), 'deg'), 'minimum_drag_coefficient': minimum_drag_coefficient, 'base_lift_coefficient': base_lift_coefficient, 'base_drag_coefficient': base_drag_coefficient, diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py index e16c92fe4..076e84eaf 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py @@ -9,13 +9,9 @@ from aviary.utils.aviary_values import AviaryValues, get_items from aviary.models.N3CC.N3CC_data import ( N3CC, takeoff_subsystem_options, takeoff_subsystem_options_spoilers) -from aviary.variable_info.variables import Aircraft -from aviary.variable_info.variables import Dynamic as _Dynamic -from aviary.variable_info.variables import Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.enums import LegacyCode -Dynamic = _Dynamic.Mission - class TestTakeoffAeroGroup(unittest.TestCase): @@ -80,18 +76,19 @@ def make_problem(subsystem_options={}): dynamic_inputs = AviaryValues({ 'angle_of_attack': (np.array([0., 2., 6.]), 'deg'), - Dynamic.ALTITUDE: (np.array([0., 32., 55.]), 'm'), - Dynamic.FLIGHT_PATH_ANGLE: (np.array([0., 0.5, 1.]), 'deg')}) + Dynamic.Mission.ALTITUDE: (np.array([0., 32., 55.]), 'm'), + Dynamic.Mission.FLIGHT_PATH_ANGLE: (np.array([0., 0.5, 1.]), 'deg')}) prob = om.Problem() prob.model.add_subsystem( "USatm", USatm1976Comp(num_nodes=nn), - promotes_inputs=[("h", Dynamic.ALTITUDE)], + promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], promotes_outputs=[ - "rho", ("sos", Dynamic.SPEED_OF_SOUND), ("temp", Dynamic.TEMPERATURE), - ("pres", Dynamic.STATIC_PRESSURE), "viscosity"]) + "rho", ("sos", Dynamic.Mission.SPEED_OF_SOUND), ("temp", + Dynamic.Mission.TEMPERATURE), + ("pres", Dynamic.Mission.STATIC_PRESSURE), "viscosity"]) aero_builder = CoreAerodynamicsBuilder(code_origin=LegacyCode.FLOPS) @@ -104,7 +101,7 @@ def make_problem(subsystem_options={}): **subsystem_options['core_aerodynamics']), promotes_outputs=aero_builder.mission_outputs(**subsystem_options['core_aerodynamics'])) - prob.model.set_input_defaults(Dynamic.ALTITUDE, np.zeros(nn), 'm') + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn), 'm') prob.setup(force_alloc_complex=True) @@ -135,9 +132,9 @@ def make_problem(subsystem_options={}): # - generate new regression data if, and only if, takeoff aero group is updated with a # more trusted implementation _regression_data = AviaryValues({ - Dynamic.LIFT: ( + Dynamic.Mission.LIFT: ( [3028.138891962988, 4072.059743068957, 6240.85493286], _units_lift), - Dynamic.DRAG: ( + Dynamic.Mission.DRAG: ( [434.6285684000267, 481.5245555324278, 586.0976806512001], _units_drag)}) # NOTE: @@ -146,9 +143,9 @@ def make_problem(subsystem_options={}): # - generate new regression data if, and only if, takeoff aero group is updated with a # more trusted implementation _regression_data_spoiler = AviaryValues({ - Dynamic.LIFT: ( + Dynamic.Mission.LIFT: ( [-1367.5937129210124, -323.67286181504335, 1845.1223279759993], _units_lift), - Dynamic.DRAG: ( + Dynamic.Mission.DRAG: ( [895.9091503940268, 942.8051375264279, 1047.3782626452], _units_drag)}) @@ -204,8 +201,8 @@ def _generate_regression_data(subsystem_options={}): prob.run_model() - lift = prob.get_val(Dynamic.LIFT, _units_lift) - drag = prob.get_val(Dynamic.DRAG, _units_drag) + lift = prob.get_val(Dynamic.Mission.LIFT, _units_lift) + drag = prob.get_val(Dynamic.Mission.DRAG, _units_drag) prob.check_partials(compact_print=True, method="cs") diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index c6ed1c751..0bfeafbce 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -168,7 +168,7 @@ def test_custom_engine(self): 'altitude': ([35.e3, 35.e3], 'ft'), 'velocity': ([455.49, 455.49], 'kn'), 'mass': ([130.e3, 128.e3], 'lbm'), - 'range': ([0., 300.], 'nmi'), + 'distance': ([0., 300.], 'nmi'), 'velocity_rate': ([0., 0.], 'm/s**2'), 'throttle': ([0.6, 0.6], 'unitless'), } @@ -235,7 +235,7 @@ def test_custom_engine(self): 'traj.phases.cruise.indep_states.states:altitude', 'traj.phases.cruise.indep_states.states:velocity', 'traj.phases.cruise.indep_states.states:mass', - 'traj.phases.cruise.indep_states.states:range', + 'traj.phases.cruise.indep_states.states:distance', ] # Check that all expected variable names are present in design_vars @@ -250,7 +250,7 @@ def test_custom_engine(self): # print the mass and range assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:mass']['val'], [ 58967.0081, 58805.95966377, 58583.74569223, 58513.41573, 58352.36729377, 58130.15332223, 58059.82336], tolerance=tol) - assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:range']['val'], [ + assert_near_equal(design_vars_dict['traj.phases.cruise.indep_states.states:distance']['val'], [ 0., 98633.17494548, 234726.82505452, 277800., 376433.17494548, 512526.82505452, 555600.], tolerance=tol) diff --git a/aviary/utils/report.py b/aviary/utils/report.py index df0e2b08e..c0076e17e 100644 --- a/aviary/utils/report.py +++ b/aviary/utils/report.py @@ -234,7 +234,7 @@ def report_benchmark_comparison( # check_val = no_size_yes_pyCycle if base == 'FLOPS': check_val = FLOPS_base - distance_name = 'traj.descent.timeseries.states:range' + distance_name = 'traj.descent.timeseries.states:distance' landing_dist_name = Mission.Landing.GROUND_DISTANCE else: distance_name = "traj.desc2.timeseries.states:distance" diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index aff3bb72c..a3908a1da 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -18,13 +18,11 @@ balanced_trajectory_builder as _takeoff_trajectory_builder from aviary.models.N3CC.N3CC_data import \ inputs as _inputs -from aviary.variable_info.variables import Dynamic as _Dynamic +from aviary.variable_info.variables import Dynamic from aviary.variable_info.variables_in import VariablesIn from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.subsystems.premission import CorePreMission -Dynamic = _Dynamic.Mission - @use_tempdirs class TestFLOPSBalancedFieldLength(unittest.TestCase): @@ -95,7 +93,7 @@ def _do_run(self, driver: Driver, optimizer, *args): liftoff = takeoff_trajectory_builder.get_phase('balanced_liftoff') liftoff.add_objective( - Dynamic.RANGE, loc='final', ref=max_range, units=units) + Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units) takeoff.model.add_subsystem( 'input_sink', @@ -128,7 +126,7 @@ def _do_run(self, driver: Driver, optimizer, *args): # N3CC FLOPS output Line 2282 desired = 7032.65 actual = takeoff.model.get_val( - 'traj.balanced_liftoff.states:range', units='ft')[-1] + 'traj.balanced_liftoff.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 2e-2) # Decision Time diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py index 7041b7cb8..53264e0d9 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py @@ -253,9 +253,9 @@ def run_trajectory(driver: Driver, sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -293,7 +293,7 @@ def run_trajectory(driver: Driver, sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', + prob.model.connect('traj.climb.states:distance', 'takeoff_constraints.climb_start_range', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) @@ -303,7 +303,7 @@ def run_trajectory(driver: Driver, sim=True): prob.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') + 'traj.climb.initial_states:distance') prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, 'traj.climb.initial_states:velocity') prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, @@ -371,8 +371,8 @@ def run_trajectory(driver: Driver, sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + prob.set_val('traj.climb.states:distance', climb.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]), @@ -390,8 +390,8 @@ def run_trajectory(driver: Driver, sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -409,8 +409,8 @@ def run_trajectory(driver: Driver, sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), @@ -446,7 +446,7 @@ def _do_run(self, driver): altitudes_climb = prob.get_val( 'traj.climb.timeseries.states:altitude', units='m') masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities_climb = prob.get_val( 'traj.climb.timeseries.states:velocity', units='m/s') thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') @@ -454,7 +454,7 @@ def _do_run(self, driver): altitudes_cruise = prob.get_val( 'traj.cruise.timeseries.states:altitude', units='m') masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities_cruise = prob.get_val( 'traj.cruise.timeseries.states:velocity', units='m/s') thrusts_cruise = prob.get_val( @@ -463,7 +463,8 @@ def _do_run(self, driver): altitudes_descent = prob.get_val( 'traj.descent.timeseries.states:altitude', units='m') masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges_descent = prob.get_val( + 'traj.descent.timeseries.states:distance', units='m') velocities_descent = prob.get_val( 'traj.descent.timeseries.states:velocity', units='m/s') thrusts_descent = prob.get_val( diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py index 55bfd2fbd..b7143e37c 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py @@ -259,9 +259,9 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -299,7 +299,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', + prob.model.connect('traj.climb.states:distance', 'takeoff_constraints.climb_start_range', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) @@ -309,7 +309,7 @@ def run_trajectory(sim=True): prob.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') + 'traj.climb.initial_states:distance') prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, 'traj.climb.initial_states:velocity') prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, @@ -377,8 +377,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + prob.set_val('traj.climb.states:distance', climb.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -396,8 +396,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -415,8 +415,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.05]), @@ -447,7 +447,7 @@ def bench_test_full_mission_large_single_aisle_1(self): altitudes_climb = prob.get_val( 'traj.climb.timeseries.states:altitude', units='m') masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities_climb = prob.get_val( 'traj.climb.timeseries.states:velocity', units='m/s') thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') @@ -455,7 +455,7 @@ def bench_test_full_mission_large_single_aisle_1(self): altitudes_cruise = prob.get_val( 'traj.cruise.timeseries.states:altitude', units='m') masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities_cruise = prob.get_val( 'traj.cruise.timeseries.states:velocity', units='m/s') thrusts_cruise = prob.get_val( @@ -464,7 +464,8 @@ def bench_test_full_mission_large_single_aisle_1(self): altitudes_descent = prob.get_val( 'traj.descent.timeseries.states:altitude', units='m') masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges_descent = prob.get_val( + 'traj.descent.timeseries.states:distance', units='m') velocities_descent = prob.get_val( 'traj.descent.timeseries.states:velocity', units='m/s') thrusts_descent = prob.get_val( diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py index 7a8c71ba1..37b176bc6 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py @@ -253,9 +253,9 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj.link_phases(["cruise", "descent"], ["time", Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.RANGE], connected=strong_couple) + Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -293,7 +293,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', + prob.model.connect('traj.climb.states:distance', 'takeoff_constraints.climb_start_range', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) @@ -303,7 +303,7 @@ def run_trajectory(sim=True): prob.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') + 'traj.climb.initial_states:distance') prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, 'traj.climb.initial_states:velocity') prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, @@ -363,8 +363,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - Dynamic.Mission.RANGE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + prob.set_val('traj.climb.states:distance', climb.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -382,8 +382,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - Dynamic.Mission.RANGE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -401,8 +401,8 @@ def run_trajectory(sim=True): Dynamic.Mission.VELOCITY, ys=[v_i_descent, v_f_descent]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - Dynamic.Mission.RANGE, ys=[range_i_descent, range_f_descent]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), @@ -433,7 +433,7 @@ def bench_test_full_mission_large_single_aisle_2(self): altitudes_climb = prob.get_val( 'traj.climb.timeseries.states:altitude', units='m') masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities_climb = prob.get_val( 'traj.climb.timeseries.states:velocity', units='m/s') thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') @@ -441,7 +441,7 @@ def bench_test_full_mission_large_single_aisle_2(self): altitudes_cruise = prob.get_val( 'traj.cruise.timeseries.states:altitude', units='m') masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities_cruise = prob.get_val( 'traj.cruise.timeseries.states:velocity', units='m/s') thrusts_cruise = prob.get_val( @@ -450,7 +450,8 @@ def bench_test_full_mission_large_single_aisle_2(self): altitudes_descent = prob.get_val( 'traj.descent.timeseries.states:altitude', units='m') masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges_descent = prob.get_val( + 'traj.descent.timeseries.states:distance', units='m') velocities_descent = prob.get_val( 'traj.descent.timeseries.states:velocity', units='m/s') thrusts_descent = prob.get_val( diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 042f00fc1..d94000a25 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -292,9 +292,9 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise"], ["time", "altitude", - "velocity", "mass", Dynamic.Mission.RANGE], connected=strong_couple) + "velocity", "mass", Dynamic.Mission.DISTANCE], connected=strong_couple) traj.link_phases(["cruise", "descent"], ["time", "altitude", - "velocity", "mass", Dynamic.Mission.RANGE], connected=strong_couple) + "velocity", "mass", Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -332,7 +332,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) - prob.model.connect('traj.climb.states:range', + prob.model.connect('traj.climb.states:distance', 'takeoff_constraints.climb_start_range', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) @@ -342,7 +342,7 @@ def run_trajectory(sim=True): prob.model.connect(Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass') prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:range') + 'traj.climb.initial_states:distance') prob.model.connect(Mission.Takeoff.FINAL_VELOCITY, 'traj.climb.initial_states:velocity') prob.model.connect(Mission.Takeoff.FINAL_ALTITUDE, @@ -453,8 +453,8 @@ def run_trajectory(sim=True): 'velocity', ys=[v_i_climb, v_f_climb]), units='m/s') prob.set_val('traj.climb.states:mass', climb.interp( 'mass', ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:range', climb.interp( - 'range', ys=[range_i_climb, range_f_climb]), units='m') # nmi + prob.set_val('traj.climb.states:distance', climb.interp( + 'distance', ys=[range_i_climb, range_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp('velocity_rate', ys=[0.25, 0.05]), @@ -472,8 +472,8 @@ def run_trajectory(sim=True): 'velocity', ys=[v_i_cruise, v_f_cruise]), units='m/s') prob.set_val('traj.cruise.states:mass', cruise.interp( 'mass', ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:range', cruise.interp( - 'range', ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + prob.set_val('traj.cruise.states:distance', cruise.interp( + 'distance', ys=[range_i_cruise, range_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp('velocity_rate', ys=[0.0, 0.0]), @@ -491,8 +491,8 @@ def run_trajectory(sim=True): 'velocity', ys=[v_i_descent, v_f_descent]), units='m/s') prob.set_val('traj.descent.states:mass', descent.interp( 'mass', ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:range', descent.interp( - 'range', ys=[range_i_descent, range_f_descent]), units='m') + prob.set_val('traj.descent.states:distance', descent.interp( + 'distance', ys=[range_i_descent, range_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp('velocity_rate', ys=[-0.25, 0.05]), @@ -526,7 +526,7 @@ def bench_test_sizing_N3CC(self): altitudes_climb = prob.get_val( 'traj.climb.timeseries.states:altitude', units='m') masses_climb = prob.get_val('traj.climb.timeseries.states:mass', units='kg') - ranges_climb = prob.get_val('traj.climb.timeseries.states:range', units='m') + ranges_climb = prob.get_val('traj.climb.timeseries.states:distance', units='m') velocities_climb = prob.get_val( 'traj.climb.timeseries.states:velocity', units='m/s') thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') @@ -534,7 +534,7 @@ def bench_test_sizing_N3CC(self): altitudes_cruise = prob.get_val( 'traj.cruise.timeseries.states:altitude', units='m') masses_cruise = prob.get_val('traj.cruise.timeseries.states:mass', units='kg') - ranges_cruise = prob.get_val('traj.cruise.timeseries.states:range', units='m') + ranges_cruise = prob.get_val('traj.cruise.timeseries.states:distance', units='m') velocities_cruise = prob.get_val( 'traj.cruise.timeseries.states:velocity', units='m/s') thrusts_cruise = prob.get_val( @@ -543,7 +543,8 @@ def bench_test_sizing_N3CC(self): altitudes_descent = prob.get_val( 'traj.descent.timeseries.states:altitude', units='m') masses_descent = prob.get_val('traj.descent.timeseries.states:mass', units='kg') - ranges_descent = prob.get_val('traj.descent.timeseries.states:range', units='m') + ranges_descent = prob.get_val( + 'traj.descent.timeseries.states:distance', units='m') velocities_descent = prob.get_val( 'traj.descent.timeseries.states:velocity', units='m/s') thrusts_descent = prob.get_val( diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 512b710d8..3da1a98ba 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -17,15 +17,12 @@ landing_trajectory_builder as _landing_trajectory_builder, landing_fullstop_user_options as _landing_fullstop_user_options) -from aviary.variable_info.variables import Dynamic as _Dynamic +from aviary.variable_info.variables import Dynamic from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn -Dynamic = _Dynamic.Mission - - @use_tempdirs class TestFLOPSDetailedLanding(unittest.TestCase): # @require_pyoptsparse(optimizer='IPOPT') @@ -90,7 +87,8 @@ def _do_run(self, driver: Driver, optimizer, *args): max_range, units = landing_fullstop_user_options.get_item('max_range') fullstop = landing_trajectory_builder.get_phase('landing_fullstop') - fullstop.add_objective(Dynamic.RANGE, loc='final', ref=max_range, units=units) + fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', + ref=max_range, units=units) landing.model.add_subsystem( 'input_sink', @@ -123,7 +121,7 @@ def _do_run(self, driver: Driver, optimizer, *args): desired = 3409.47 # ft actual = landing.model.get_val( - 'traj.landing_fullstop.states:range', units='ft')[-1] + 'traj.landing_fullstop.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 0.05) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index bc403ccbf..c16facd15 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -17,15 +17,12 @@ takeoff_trajectory_builder as _takeoff_trajectory_builder, takeoff_liftoff_user_options as _takeoff_liftoff_user_options) -from aviary.variable_info.variables import Aircraft, Dynamic as _Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic from aviary.interface.default_phase_info.height_energy import default_premission_subsystems from aviary.utils.preprocessors import preprocess_crewpayload from aviary.variable_info.variables_in import VariablesIn -Dynamic = _Dynamic.Mission - - @use_tempdirs class TestFLOPSDetailedTakeoff(unittest.TestCase): @require_pyoptsparse(optimizer='IPOPT') @@ -97,7 +94,7 @@ def _do_run(self, driver: Driver, optimizer, *args): liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff') liftoff.add_objective( - Dynamic.RANGE, loc='final', ref=max_range, units=units) + Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units) # Insert a constraint for a fake decision speed, until abort is added. takeoff.model.add_constraint( @@ -140,7 +137,7 @@ def _do_run(self, driver: Driver, optimizer, *args): desired = 5649.9 # ft actual = takeoff.model.get_val( - 'traj.takeoff_liftoff.states:range', units='ft')[-1] + 'traj.takeoff_liftoff.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 2e-2) diff --git a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py index f09ffd6ed..e5f7c4ca9 100644 --- a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py +++ b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py @@ -293,7 +293,7 @@ def run_mission(optimizer): phase.set_state_options("mass", rate_source="dmass_dv", fix_initial=True, fix_final=False, lower=1, upper=195_000, ref=takeoff_mass, defect_ref=takeoff_mass) - phase.set_state_options(Dynamic.Mission.RANGE, rate_source="over_a", + phase.set_state_options(Dynamic.Mission.DISTANCE, rate_source="over_a", fix_initial=True, fix_final=False, lower=0, upper=2000., ref=1.e2, defect_ref=1.e2) phase.add_parameter("t_init_gear", units="s", @@ -330,7 +330,7 @@ def run_mission(optimizer): static_target=False) phase.set_time_options(fix_initial=False, fix_duration=False, - units="range_units", name=Dynamic.Mission.RANGE, + units="range_units", name=Dynamic.Mission.DISTANCE, duration_bounds=duration_bounds, duration_ref=duration_ref, initial_bounds=initial_bounds, initial_ref=initial_ref) @@ -425,7 +425,7 @@ def run_mission(optimizer): pass elif phase_name == "descent": phase.add_boundary_constraint( - Dynamic.Mission.RANGE, + Dynamic.Mission.DISTANCE, loc="final", equals=target_range, units="NM", @@ -510,7 +510,7 @@ def run_mission(optimizer): traj.link_phases(phases[6:], vars=[Dynamic.Mission.ALTITUDE], ref=10.e3) traj.link_phases(phases, vars=['time'], ref=100.) traj.link_phases(phases, vars=['mass'], ref=10.e3) - traj.link_phases(phases, vars=[Dynamic.Mission.RANGE], units='m', ref=10.e3) + traj.link_phases(phases, vars=[Dynamic.Mission.DISTANCE], units='m', ref=10.e3) traj.link_phases(phases[:7], vars=['TAS'], units='kn', ref=200.) # traj.link_phases(phases[7:], vars=['TAS'], units='kn', ref=200.) @@ -641,9 +641,9 @@ def run_mission(optimizer): if phase_name == "groundroll": ranges.extend( - p.get_val(f"traj.{phase_name}.timeseries.states:range", units="m")[0]) + p.get_val(f"traj.{phase_name}.timeseries.states:distance", units="m")[0]) ranges.extend( - p.get_val(f"traj.{phase_name}.timeseries.states:range", units="m")[-1]) + p.get_val(f"traj.{phase_name}.timeseries.states:distance", units="m")[-1]) masses.extend( p.get_val(f"traj.{phase_name}.timeseries.mass", units="lbm")[0]) diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index f4491a79a..9158440ad 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -53,7 +53,7 @@ def setUp(self): 'altitude': ([35.e3, 35.e3], 'ft'), 'velocity': ([455.49, 455.49], 'kn'), 'mass': ([130.e3, 120.e3], 'lbm'), - 'range': ([0., 3000.], 'NM'), + 'distance': ([0., 3000.], 'NM'), 'velocity_rate': ([0., 0.], 'm/s**2'), 'throttle': ([0.6, 0.6], 'unitless'), } diff --git a/aviary/validation_cases/benchmark_utils.py b/aviary/validation_cases/benchmark_utils.py index 8540817a2..a5a66b39f 100644 --- a/aviary/validation_cases/benchmark_utils.py +++ b/aviary/validation_cases/benchmark_utils.py @@ -27,7 +27,7 @@ def compare_against_expected_values(prob, expected_dict): masses.extend( prob.get_val(f'traj.{phase}.timeseries.states:mass', units='kg')) ranges.extend( - prob.get_val(f'traj.{phase}.timeseries.states:range', units='m')) + prob.get_val(f'traj.{phase}.timeseries.states:distance', units='m')) velocities.extend(prob.get_val( f'traj.{phase}.timeseries.states:velocity', units='m/s')) diff --git a/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py b/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py index 7e09b2d2b..02aca9e40 100644 --- a/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py +++ b/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py @@ -123,7 +123,7 @@ data.set_val( # state_rates:range - Dynamic.Mission.RANGE_RATE, + Dynamic.Mission.DISTANCE_RATE, val=[163.776550884386, 232.775306059091, 117.631414542995, ], units='m/s', ) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 94d66ccdc..580c381be 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -5852,7 +5852,7 @@ add_meta_data( Dynamic.Mission.DISTANCE, meta_data=_MetaData, - historical_name={"GASP": None, + historical_name={"GASP": 'range', "FLOPS": None, "LEAPS1": None }, @@ -5863,7 +5863,7 @@ add_meta_data( Dynamic.Mission.DISTANCE_RATE, meta_data=_MetaData, - historical_name={"GASP": None, + historical_name={"GASP": 'range_rate', "FLOPS": None, "LEAPS1": None }, @@ -6078,29 +6078,6 @@ desc='Current total rate of nitrous oxide (NOx) production by the vehicle' ) -add_meta_data( - Dynamic.Mission.RANGE, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='nm', - desc='Current cumulative ground distance the vehicle has flown' -) - -add_meta_data( - Dynamic.Mission.RANGE_RATE, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='nm/s', - desc='Current rate of change in cumulative ground distance (ground velocity) for ' - 'the vehicle' -) - add_meta_data( Dynamic.Mission.SPECIFIC_ENERGY_RATE, meta_data=_MetaData, diff --git a/aviary/xdsm/statics_xdsm.py b/aviary/xdsm/statics_xdsm.py index e10333dee..e4583c487 100644 --- a/aviary/xdsm/statics_xdsm.py +++ b/aviary/xdsm/statics_xdsm.py @@ -28,7 +28,7 @@ x.add_system("landing", GROUP, [r"\textbf{Landing}"]) x.add_system("fuelburn", FUNC, ["FuelBurn"]) x.add_system("mass_diff", FUNC, ["MassDifference"]) -x.add_system(Dynamic.Mission.RANGE, FUNC, ["RangeConstraint"]) +x.add_system(Dynamic.Mission.DISTANCE, FUNC, ["RangeConstraint"]) if simplified is False: # independent vars input to ParamPort, common to all phases @@ -339,7 +339,7 @@ ) x.add_input("fuelburn", [Aircraft.Fuel.FUEL_MARGIN, Mission.Summary.GROSS_MASS]) - x.add_input(Dynamic.Mission.RANGE, [Mission.Design.RANGE]) + x.add_input(Dynamic.Mission.DISTANCE, [Mission.Design.RANGE]) # Create outputs x.add_output("landing", [Mission.Landing.GROUND_DISTANCE], side="right") @@ -367,7 +367,7 @@ ) x.connect("dymos", "descent1", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) x.connect("dymos", "fuelburn", [Mission.Landing.TOUCHDOWN_MASS]) -x.connect("dymos", Dynamic.Mission.RANGE, [Mission.Summary.RANGE]) +x.connect("dymos", Dynamic.Mission.DISTANCE, [Mission.Summary.RANGE]) x.connect("cruise", "dymos", ["cruise_time_final", "cruise_range_final"]) # Add Design Variables @@ -405,7 +405,7 @@ # Add Constraints x.connect("dymos", "opt", [r"\mathcal{R}"]) x.connect("mass_diff", "opt", [Mission.Constraints.MASS_RESIDUAL]) -x.connect(Dynamic.Mission.RANGE, "opt", [Mission.Constraints.RANGE_RESIDUAL]) +x.connect(Dynamic.Mission.DISTANCE, "opt", [Mission.Constraints.RANGE_RESIDUAL]) x.connect("poly", "opt", ["h_init_gear", "h_init_flaps"]) # Connect State Rates From 40db5168f38a6473f46d97caddb871493cd1d0b0 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Tue, 16 Jan 2024 16:35:59 -0500 Subject: [PATCH 050/111] Modified test to use loading inputs from AviaryValues Doc update --- .../getting_started/onboarding_level2.ipynb | 13 ++++++++----- aviary/docs/user_guide/input_files.ipynb | 2 +- .../benchmark_tests/test_0_iters.py | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index 0d47cdf7f..4f07f7394 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -206,11 +206,14 @@ "source": [ "is a function that has a few tasks:\n", "\n", - "- read aircraft deck file `aircraft_filename`\n", - "- read phase info file `phase_info`\n", - "- build core subsystems, including setting up engines\n", + "- Read aircraft deck file `aircraft_filename`\n", + "- Read phase info file `phase_info`\n", + "- Build core subsystems\n", "\n", - "We have seen `aircraft_filename` file (a `.csv` file) in our level 1 examples. In [level 1](onboarding_level1), we simply called it input file. Engine is built by using `aircraft:engine:data_file` in the .csv file. For example in `aircraft_for_bench_GwGm.csv` file, we see:\n", + "We have seen `aircraft_filename` file (a `.csv` file) in our level 1 examples. In [level 1](onboarding_level1), we simply called it input file. An aircraft model can also be directly defined in Python, by setting up an `AviaryValues` object with the desired inputs and options normally found in an input file. That object can be provided in the place of `aircraft_filename`.\n", + "\n", + "\n", + "Engines are built by using `aircraft:engine:data_file` in the .csv file. For example in `aircraft_for_bench_GwGm.csv` file, we see:\n", "\n", "```\n", "aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless\n", @@ -226,7 +229,7 @@ "| 0.0, | 0.0, | 42.0, | 21214.0, | 0.0, | 5979.1, | 19.8547 |\n", "| 0.0, | 0.0, | 38.0, | 17356.9, | 0.0, | 4795.2, | 17.5877 |\n", "\n", - "The engine builder allows users to provide an `EngineModel` instance of their own to use in Aviary's propulsion systems.\n", + "Users can provide an `EngineModel` instance of their own to use in Aviary's propulsion systems by adding it to `engine_models`.\n", "\n", "Other subsystems, including mass, geometry, and aerodynamics, are set up according to which legacy code options the user has specified in their input file, using `settings:equations_of_motion` and `settings:mass_method`. Aerodynamics is set up to match the selected equations of motion, while geometry will use either GASP, FLOPS, or both methods as required to calculate all values needed by other subsystems.\n", "\n", diff --git a/aviary/docs/user_guide/input_files.ipynb b/aviary/docs/user_guide/input_files.ipynb index 39e37182e..cf8a12fb5 100644 --- a/aviary/docs/user_guide/input_files.ipynb +++ b/aviary/docs/user_guide/input_files.ipynb @@ -18,7 +18,7 @@ "source": [ "## Aviary Aircraft Input Files\n", "\n", - "Aviary uses a .csv file to load in information about the aircraft to be designed.\n", + "Aviary can use a .csv file to load in information about the aircraft to be designed.\n", "The file format is straightforward and follows the convention of `name, value, units` for each row.\n", "The names of the variables are detailed in the [Understanding Variable Metadata doc page](variable_metadata).\n", "\n", diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 31761bd19..6121652f6 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -7,6 +7,9 @@ from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info +from aviary.interface.default_phase_info.simple import phase_info as simple_phase_info +from aviary.models.N3CC.N3CC_data import inputs +from aviary.variable_info.variables import Settings from aviary.variable_info.enums import EquationsOfMotion @@ -35,7 +38,7 @@ def build_and_run_problem(self, input_filename, phase_info, objective_type=None) class TwoDOFZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") - def test_gasp_zero_iters(self): + def test_zero_iters_2DOF(self): local_phase_info = deepcopy(two_dof_phase_info) self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_GwGm.csv', local_phase_info) @@ -45,14 +48,14 @@ def test_gasp_zero_iters(self): class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") - def test_height_energy_zero_iters(self): - local_phase_info = deepcopy(height_energy_phase_info) - self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm.csv', - local_phase_info) + def test_zero_iters_height_energy(self): + local_phase_info = deepcopy(simple_phase_info) + inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) + self.build_and_run_problem(inputs, local_phase_info) @use_tempdirs -class SolvedProblemTestCase(BaseProblemPhaseTestCase): +class SolvedZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_zero_iters_solved(self): @@ -64,5 +67,5 @@ def test_zero_iters_solved(self): if __name__ == "__main__": # unittest.main() - test = SolvedProblemTestCase() - test.test_zero_iters_solved() + test = HEZeroItersTestCase() + test.test_zero_iters_height_energy() From 4eed4b23de8df2b067bfb01c10aa68056c703a94 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Tue, 16 Jan 2024 16:43:02 -0500 Subject: [PATCH 051/111] touched up variables.py --- aviary/variable_info/variable_meta_data.py | 8 ++++---- aviary/variable_info/variables.py | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 580c381be..f3d6e8ae6 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -5852,8 +5852,8 @@ add_meta_data( Dynamic.Mission.DISTANCE, meta_data=_MetaData, - historical_name={"GASP": 'range', - "FLOPS": None, + historical_name={"GASP": None, + "FLOPS": 'range', "LEAPS1": None }, units='NM', @@ -5863,8 +5863,8 @@ add_meta_data( Dynamic.Mission.DISTANCE_RATE, meta_data=_MetaData, - historical_name={"GASP": 'range_rate', - "FLOPS": None, + historical_name={"GASP": None, + "FLOPS": 'range_rate', "LEAPS1": None }, units='NM/s', diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index a64d774f4..9b0923133 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -598,8 +598,6 @@ class Mission: MASS_RATE = 'mass_rate' NOX_RATE = 'nox_rate' NOX_RATE_TOTAL = 'nox_rate_total' - RANGE = 'range' - RANGE_RATE = 'range_rate' SPECIFIC_ENERGY = 'specific_energy' SPECIFIC_ENERGY_RATE = 'specific_energy_rate' SPECIFIC_ENERGY_RATE_EXCESS = 'specific_energy_rate_excess' From 80cf3b67b998c31901cf964e12f98c54f02b6848 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Tue, 16 Jan 2024 23:11:24 -0600 Subject: [PATCH 052/111] Fixed benches and docs --- .../FLOPS_based_detailed_takeoff_and_landing.ipynb | 4 ++-- ...xamples_of_the_same_mission_at_different_UI_levels.ipynb | 6 +++--- aviary/validation_cases/benchmark_utils.py | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb index f89d2d31e..e13abbf88 100644 --- a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb @@ -144,7 +144,7 @@ "takeoff_brake_release_initial_guesses = av.AviaryValues()\n", "\n", "takeoff_brake_release_initial_guesses.set_val('times', [0., 30.], 's')\n", - "takeoff_brake_release_initial_guesses.set_val('range', [0., 4100.], 'ft')\n", + "takeoff_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft')\n", "takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn')\n", "\n", "gross_mass_units = 'lbm'\n", @@ -449,7 +449,7 @@ "landing_approach_to_mic_p3_initial_guesses = av.AviaryValues()\n", "\n", "landing_approach_to_mic_p3_initial_guesses.set_val('times', [-42., 15.], 's')\n", - "landing_approach_to_mic_p3_initial_guesses.set_val('range', [-4000., -2000.], 'ft')\n", + "landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000., -2000.], 'ft')\n", "landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140., 'kn')\n", "landing_approach_to_mic_p3_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm')\n", "landing_approach_to_mic_p3_initial_guesses.set_val('throttle', throttle)\n", diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index e2ea405ec..c4b1637cf 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -90,7 +90,7 @@ " 'altitude': ([0., 35.e3], 'ft'),\n", " 'velocity': ([220., 455.49], 'kn'),\n", " 'mass': ([170.e3, 165.e3], 'lbm'),\n", - " 'range': ([0., 160.3], 'nmi'),\n", + " 'distance': ([0., 160.3], 'nmi'),\n", " 'velocity_rate': ([0.25, 0.05], 'm/s**2'),\n", " 'throttle': ([0.5, 0.5], 'unitless'),\n", " }\n", @@ -122,7 +122,7 @@ " 'altitude': ([35.e3, 35.e3], 'ft'),\n", " 'velocity': ([455.49, 455.49], 'kn'),\n", " 'mass': ([165.e3, 140.e3], 'lbm'),\n", - " 'range': ([160.3, 3243.9], 'nmi'),\n", + " 'distance': ([160.3, 3243.9], 'nmi'),\n", " 'velocity_rate': ([0., 0.], 'm/s**2'),\n", " 'throttle': ([0.95, 0.9], 'unitless'),\n", " }\n", @@ -152,7 +152,7 @@ " 'altitude': ([35.e3, 35.], 'ft'),\n", " 'velocity': ([455.49, 198.44], 'kn'),\n", " 'mass': ([120.e3, 115.e3], 'lbm'),\n", - " 'range': ([3243.9, 3378.7], 'nmi'),\n", + " 'distance': ([3243.9, 3378.7], 'nmi'),\n", " 'velocity_rate': ([-0.25, 0.0], 'm/s**2'),\n", " 'throttle': ([0., 0.], 'unitless'),\n", " }\n", diff --git a/aviary/validation_cases/benchmark_utils.py b/aviary/validation_cases/benchmark_utils.py index 082047908..0d2186576 100644 --- a/aviary/validation_cases/benchmark_utils.py +++ b/aviary/validation_cases/benchmark_utils.py @@ -40,8 +40,6 @@ def compare_against_expected_values(prob, expected_dict, simple_flag=False): prob.get_val(f'traj.{phase}.timeseries.states:mass', units='kg')) ranges.extend( prob.get_val(f'traj.{phase}.timeseries.states:distance', units='m')) - velocities.extend(prob.get_val( - f'traj.{phase}.timeseries.states:velocity', units='m/s')) times = np.array(times) altitudes = np.array(altitudes) From a1974e28d0b90b1d8f0b990d80540dc87490e912 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Wed, 17 Jan 2024 09:44:06 -0600 Subject: [PATCH 053/111] Updated more range->distance calls --- aviary/constants.py | 2 +- aviary/docs/examples/OAS_subsystem.ipynb | 6 +-- .../examples/additional_flight_phases.ipynb | 14 +++--- ...oupled_aircraft_mission_optimization.ipynb | 6 +-- .../docs/examples/more_advanced_example.ipynb | 6 +-- .../examples/simple_mission_example.ipynb | 6 +-- .../onboarding_ext_subsystem.ipynb | 6 +-- .../getting_started/onboarding_level3.ipynb | 48 +++++++++---------- ..._same_mission_at_different_UI_levels.ipynb | 27 +++++------ .../OAS_weight/run_simple_OAS_mission.py | 6 +-- aviary/examples/run_aviary_example.py | 6 +-- aviary/interface/default_phase_info/simple.py | 6 +-- aviary/interface/graphical_input.py | 10 ++-- aviary/interface/methods_for_level2.py | 14 +++--- aviary/interface/test/test_simple_mission.py | 14 +++--- .../flops_based/phases/simple_energy_phase.py | 6 +-- .../ode/unsteady_solved/gamma_comp.py | 6 +-- .../unsteady_solved/unsteady_solved_eom.py | 6 +-- .../unsteady_solved_flight_conditions.py | 4 +- .../unsteady_solved/unsteady_solved_ode.py | 9 ++-- aviary/utils/Fortran_to_Aviary.py | 4 +- .../benchmark_tests/test_bench_FwFm.py | 6 +-- .../benchmark_tests/test_bench_GwFm.py | 6 +-- .../test_full_mission_solved_ode.py | 10 ++-- 24 files changed, 117 insertions(+), 117 deletions(-) diff --git a/aviary/constants.py b/aviary/constants.py index 55dfca1d5..c7770d804 100644 --- a/aviary/constants.py +++ b/aviary/constants.py @@ -1,6 +1,6 @@ import openmdao.utils.units as units -units.add_unit('range_units', '1*m') +units.add_unit('distance_units', '1*m') GRAV_METRIC_GASP = 9.81 # m/s^2 GRAV_ENGLISH_GASP = 32.2 # ft/s^2 diff --git a/aviary/docs/examples/OAS_subsystem.ipynb b/aviary/docs/examples/OAS_subsystem.ipynb index 3e7db68f6..cff6691c7 100644 --- a/aviary/docs/examples/OAS_subsystem.ipynb +++ b/aviary/docs/examples/OAS_subsystem.ipynb @@ -254,7 +254,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.2, 'unitless'),\n", " 'final_mach': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", @@ -278,7 +278,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.72, 'unitless'),\n", " 'final_mach': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", @@ -302,7 +302,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.72, 'unitless'),\n", " 'final_mach': (0.36, 'unitless'),\n", " 'mach_bounds': ((0.34, 0.74), 'unitless'),\n", diff --git a/aviary/docs/examples/additional_flight_phases.ipynb b/aviary/docs/examples/additional_flight_phases.ipynb index a28066d63..7a5cf85a8 100644 --- a/aviary/docs/examples/additional_flight_phases.ipynb +++ b/aviary/docs/examples/additional_flight_phases.ipynb @@ -38,7 +38,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.2, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", @@ -62,7 +62,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", @@ -86,7 +86,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.74, \"unitless\"),\n", " \"mach_bounds\": ((0.7, 0.76), \"unitless\"),\n", @@ -110,7 +110,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.74, \"unitless\"),\n", " \"final_mach\": (0.74, \"unitless\"),\n", " \"mach_bounds\": ((0.72, 0.76), \"unitless\"),\n", @@ -134,7 +134,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.74, \"unitless\"),\n", " \"final_mach\": (0.76, \"unitless\"),\n", " \"mach_bounds\": ((0.72, 0.78), \"unitless\"),\n", @@ -158,7 +158,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.76, \"unitless\"),\n", " \"final_mach\": (0.76, \"unitless\"),\n", " \"mach_bounds\": ((0.74, 0.78), \"unitless\"),\n", @@ -182,7 +182,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.76, \"unitless\"),\n", " \"final_mach\": (0.2, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.78), \"unitless\"),\n", diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index 850f8a627..b39e7217d 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -54,7 +54,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 5,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.2, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.84), \"unitless\"),\n", @@ -78,7 +78,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 5,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.80, \"unitless\"),\n", " \"mach_bounds\": ((0.7, 0.84), \"unitless\"),\n", @@ -102,7 +102,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 5,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.21, \"unitless\"),\n", " \"mach_bounds\": ((0.19, 0.84), \"unitless\"),\n", diff --git a/aviary/docs/examples/more_advanced_example.ipynb b/aviary/docs/examples/more_advanced_example.ipynb index ee8e50ece..bd2875bca 100644 --- a/aviary/docs/examples/more_advanced_example.ipynb +++ b/aviary/docs/examples/more_advanced_example.ipynb @@ -36,7 +36,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.2, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", @@ -60,7 +60,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", @@ -84,7 +84,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 3,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.2, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", diff --git a/aviary/docs/examples/simple_mission_example.ipynb b/aviary/docs/examples/simple_mission_example.ipynb index 40556809d..6c3f17509 100644 --- a/aviary/docs/examples/simple_mission_example.ipynb +++ b/aviary/docs/examples/simple_mission_example.ipynb @@ -143,7 +143,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 2,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.2, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", @@ -167,7 +167,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 2,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.72, \"unitless\"),\n", " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", @@ -191,7 +191,7 @@ " \"polynomial_control_order\": 1,\n", " \"num_segments\": 2,\n", " \"order\": 3,\n", - " \"solve_for_range\": False,\n", + " \"solve_for_distance\": False,\n", " \"initial_mach\": (0.72, \"unitless\"),\n", " \"final_mach\": (0.2, \"unitless\"),\n", " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index 5b6ac3718..e9a66393a 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -532,7 +532,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.2, 'unitless'),\n", " 'final_mach': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", @@ -556,7 +556,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.72, 'unitless'),\n", " 'final_mach': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", @@ -580,7 +580,7 @@ " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_range': False,\n", + " 'solve_for_distance': False,\n", " 'initial_mach': (0.72, 'unitless'),\n", " 'final_mach': (0.36, 'unitless'),\n", " 'mach_bounds': ((0.34, 0.74), 'unitless'),\n", diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index 38a6bc929..6d8915358 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -136,8 +136,8 @@ "# mach_i_climb = 0.3\n", "mach_i_climb = 0.2\n", "mach_f_climb = cruise_mach\n", - "range_i_climb = 0*_units.nautical_mile # m\n", - "range_f_climb = 160.3*_units.nautical_mile # m\n", + "distance_i_climb = 0*_units.nautical_mile # m\n", + "distance_f_climb = 160.3*_units.nautical_mile # m\n", "t_i_climb = 2 * _units.minute # sec\n", "t_f_climb = 26.20*_units.minute # sec\n", "t_duration_climb = t_f_climb - t_i_climb\n", @@ -152,8 +152,8 @@ "v_f_cruise = 455.49*_units.knot # m/s\n", "mach_min_cruise = cruise_mach\n", "mach_max_cruise = cruise_mach\n", - "range_i_cruise = 160.3*_units.nautical_mile # m\n", - "range_f_cruise = 3243.9*_units.nautical_mile # m\n", + "distance_i_cruise = 160.3*_units.nautical_mile # m\n", + "distance_f_cruise = 3243.9*_units.nautical_mile # m\n", "t_i_cruise = 26.20*_units.minute # sec\n", "t_f_cruise = 432.38*_units.minute # sec\n", "t_duration_cruise = t_f_cruise - t_i_cruise\n", @@ -168,8 +168,8 @@ "mach_f_descent = 0.3\n", "mass_i_descent = 102000*_units.pound\n", "mass_f_descent = 101000*_units.pound\n", - "range_i_descent = 3243.9*_units.nautical_mile\n", - "range_f_descent = 3378.7*_units.nautical_mile\n", + "distance_i_descent = 3243.9*_units.nautical_mile\n", + "distance_f_descent = 3378.7*_units.nautical_mile\n", "t_i_descent = 432.38*_units.minute\n", "t_f_descent = 461.62*_units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", @@ -340,13 +340,13 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_range_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", - " takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", + " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", " climb_start_range={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", @@ -359,7 +359,7 @@ " (\"takeoff_vel\", Mission.Takeoff.FINAL_VELOCITY),\n", " (\"takeoff_alt\", Mission.Takeoff.FINAL_ALTITUDE),\n", " ],\n", - " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_range_con\",\n", + " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_distance_con\",\n", " \"takeoff_vel_con\", \"takeoff_alt_con\"],\n", ")\n", "\n", @@ -444,7 +444,7 @@ "prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi\n", "\n", "prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -463,7 +463,7 @@ "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi\n", "\n", "prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -482,7 +482,7 @@ "prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", "\n", "prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", @@ -605,8 +605,8 @@ "# mach_i_climb = 0.3\n", "mach_i_climb = 0.2\n", "mach_f_climb = cruise_mach\n", - "range_i_climb = 0*_units.nautical_mile # m\n", - "range_f_climb = 160.3*_units.nautical_mile # m\n", + "distance_i_climb = 0*_units.nautical_mile # m\n", + "distance_f_climb = 160.3*_units.nautical_mile # m\n", "t_i_climb = 2 * _units.minute # sec\n", "t_f_climb = 26.20*_units.minute # sec\n", "t_duration_climb = t_f_climb - t_i_climb\n", @@ -621,8 +621,8 @@ "v_f_cruise = 455.49*_units.knot # m/s\n", "mach_min_cruise = cruise_mach\n", "mach_max_cruise = cruise_mach\n", - "range_i_cruise = 160.3*_units.nautical_mile # m\n", - "range_f_cruise = 3243.9*_units.nautical_mile # m\n", + "distance_i_cruise = 160.3*_units.nautical_mile # m\n", + "distance_f_cruise = 3243.9*_units.nautical_mile # m\n", "t_i_cruise = 26.20*_units.minute # sec\n", "t_f_cruise = 432.38*_units.minute # sec\n", "t_duration_cruise = t_f_cruise - t_i_cruise\n", @@ -637,8 +637,8 @@ "mach_f_descent = 0.3\n", "mass_i_descent = 102000*_units.pound\n", "mass_f_descent = 101000*_units.pound\n", - "range_i_descent = 3243.9*_units.nautical_mile\n", - "range_f_descent = 3378.7*_units.nautical_mile\n", + "distance_i_descent = 3243.9*_units.nautical_mile\n", + "distance_f_descent = 3378.7*_units.nautical_mile\n", "t_i_descent = 432.38*_units.minute\n", "t_f_descent = 461.62*_units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", @@ -695,13 +695,13 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_range_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", - " takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", + " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", " climb_start_range={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", @@ -714,7 +714,7 @@ " (\"takeoff_vel\", Mission.Takeoff.FINAL_VELOCITY),\n", " (\"takeoff_alt\", Mission.Takeoff.FINAL_ALTITUDE),\n", " ],\n", - " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_range_con\",\n", + " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_distance_con\",\n", " \"takeoff_vel_con\", \"takeoff_alt_con\"],\n", " )\n", "\n", @@ -769,7 +769,7 @@ " prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", " prob.set_val('traj.climb.states:distance', climb.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi\n", "\n", " prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -788,7 +788,7 @@ " prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", " prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi\n", "\n", " prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -807,7 +807,7 @@ " prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", " prob.set_val('traj.descent.states:distance', descent.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", "\n", " prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index c4b1637cf..11ae2115a 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -115,7 +115,7 @@ " 'max_mach': 0.79,\n", " 'required_available_climb_rate': (1.524, 'm/s'),\n", " 'mass_f_cruise': (1.e4, 'kg'),\n", - " 'range_f_cruise': (1.e6, 'm'),\n", + " 'distance_f_cruise': (1.e6, 'm'),\n", " },\n", " 'initial_guesses': {\n", " 'times': ([26.2, 406.18], 'min'),\n", @@ -170,7 +170,6 @@ "# Allow for user overrides here\n", "prob.load_inputs(csv_path, phase_info)\n", "\n", - "prob.check_and_preprocess_inputs()\n", "\n", "prob.add_pre_mission_systems()\n", @@ -261,8 +260,8 @@ "# mach_i_climb = 0.3\n", "mach_i_climb = 0.2\n", "mach_f_climb = 0.79\n", - "range_i_climb = 0*_units.nautical_mile # m\n", - "range_f_climb = 160.3*_units.nautical_mile # m\n", + "distance_i_climb = 0*_units.nautical_mile # m\n", + "distance_f_climb = 160.3*_units.nautical_mile # m\n", "t_i_climb = 2 * _units.minute # sec\n", "t_f_climb = 26.20*_units.minute # sec\n", "t_duration_climb = t_f_climb - t_i_climb\n", @@ -279,8 +278,8 @@ "# mach_f_cruise = 0.79\n", "mach_min_cruise = 0.79\n", "mach_max_cruise = 0.79\n", - "range_i_cruise = 160.3*_units.nautical_mile # m\n", - "range_f_cruise = 3243.9*_units.nautical_mile # m\n", + "distance_i_cruise = 160.3*_units.nautical_mile # m\n", + "distance_f_cruise = 3243.9*_units.nautical_mile # m\n", "t_i_cruise = 26.20*_units.minute # sec\n", "t_f_cruise = 432.38*_units.minute # sec\n", "t_duration_cruise = t_f_cruise - t_i_cruise\n", @@ -295,8 +294,8 @@ "mach_f_descent = 0.3\n", "mass_i_descent = 143521*_units.pound\n", "mass_f_descent = 143035*_units.pound\n", - "range_i_descent = 3243.9*_units.nautical_mile\n", - "range_f_descent = 3378.7*_units.nautical_mile\n", + "distance_i_descent = 3243.9*_units.nautical_mile\n", + "distance_f_descent = 3378.7*_units.nautical_mile\n", "t_i_descent = 432.38*_units.minute\n", "t_f_descent = 461.62*_units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", @@ -449,13 +448,13 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_range_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", - " takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", + " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", " climb_start_range={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", @@ -468,7 +467,7 @@ " (\"takeoff_vel\", Mission.Takeoff.FINAL_VELOCITY),\n", " (\"takeoff_alt\", Mission.Takeoff.FINAL_ALTITUDE),\n", " ],\n", - " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_range_con\",\n", + " promotes_outputs=[\"takeoff_mass_con\", \"takeoff_distance_con\",\n", " \"takeoff_vel_con\", \"takeoff_alt_con\"],\n", ")\n", "\n", @@ -553,7 +552,7 @@ "prob.set_val('traj.climb.states:mass', climb.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi\n", "\n", "prob.set_val('traj.climb.controls:velocity_rate',\n", " climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]),\n", @@ -572,7 +571,7 @@ "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi\n", "\n", "prob.set_val('traj.cruise.controls:velocity_rate',\n", " cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]),\n", @@ -591,7 +590,7 @@ "prob.set_val('traj.descent.states:mass', descent.interp(\n", " Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m')\n", + " Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", "\n", "prob.set_val('traj.descent.controls:velocity_rate',\n", " descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]),\n", diff --git a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py index 064c86985..156676327 100644 --- a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py +++ b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py @@ -33,7 +33,7 @@ 'polynomial_control_order': 1, 'num_segments': 5, 'order': 3, - 'solve_for_range': False, + 'solve_for_distance': False, 'initial_mach': (0.2, 'unitless'), 'final_mach': (0.72, 'unitless'), 'mach_bounds': ((0.18, 0.74), 'unitless'), @@ -57,7 +57,7 @@ 'polynomial_control_order': 1, 'num_segments': 5, 'order': 3, - 'solve_for_range': False, + 'solve_for_distance': False, 'initial_mach': (0.72, 'unitless'), 'final_mach': (0.72, 'unitless'), 'mach_bounds': ((0.7, 0.74), 'unitless'), @@ -81,7 +81,7 @@ 'polynomial_control_order': 1, 'num_segments': 5, 'order': 3, - 'solve_for_range': False, + 'solve_for_distance': False, 'initial_mach': (0.72, 'unitless'), 'final_mach': (0.36, 'unitless'), 'mach_bounds': ((0.34, 0.74), 'unitless'), diff --git a/aviary/examples/run_aviary_example.py b/aviary/examples/run_aviary_example.py index 73d80aa7e..875a5f456 100644 --- a/aviary/examples/run_aviary_example.py +++ b/aviary/examples/run_aviary_example.py @@ -21,7 +21,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.2, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.18, 0.74), "unitless"), @@ -45,7 +45,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.7, 0.74), "unitless"), @@ -69,7 +69,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.36, "unitless"), "mach_bounds": ((0.34, 0.74), "unitless"), diff --git a/aviary/interface/default_phase_info/simple.py b/aviary/interface/default_phase_info/simple.py index 29dcd56ea..4aceafb61 100644 --- a/aviary/interface/default_phase_info/simple.py +++ b/aviary/interface/default_phase_info/simple.py @@ -26,7 +26,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.2, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.18, 0.74), "unitless"), @@ -51,7 +51,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.7, 0.74), "unitless"), @@ -75,7 +75,7 @@ "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.36, "unitless"), "mach_bounds": ((0.34, 0.74), "unitless"), diff --git a/aviary/interface/graphical_input.py b/aviary/interface/graphical_input.py index 1fb3c7c18..eae7cea41 100644 --- a/aviary/interface/graphical_input.py +++ b/aviary/interface/graphical_input.py @@ -148,7 +148,7 @@ def create_bounds(center): 'use_polynomial_control': True, 'num_segments': num_segments, 'order': 3, - 'solve_for_range': False, + 'solve_for_distance': False, 'initial_mach': (mach_values[i], 'unitless'), 'final_mach': (mach_values[i+1], 'unitless'), 'mach_bounds': ((np.min(mach_values[i:i+2]) - 0.02, np.max(mach_values[i:i+2]) + 0.02), 'unitless'), @@ -178,7 +178,7 @@ def create_bounds(center): if 'pre_mission' in phase_name or 'post_mission' in phase_name: continue phase_info[phase_name]['user_options'].update({ - 'solve_for_range': user_choices.get('solve_for_range', False), + 'solve_for_distance': user_choices.get('solve_for_distance', False), }) # Apply global settings if required @@ -307,9 +307,9 @@ def __init__(self): tk.Checkbutton(checkbox_frame, text="Constrain Range", variable=self.constrain_range_var).pack(anchor="w") self.constrain_range_var.set(True) - self.solve_for_range_var = tk.BooleanVar() + self.solve_for_distance_var = tk.BooleanVar() tk.Checkbutton(checkbox_frame, text="Solve for Range", - variable=self.solve_for_range_var).pack(anchor="w") + variable=self.solve_for_distance_var).pack(anchor="w") # Textbox for Polynomial Control Order self.polynomial_order_var = tk.StringVar() @@ -458,7 +458,7 @@ def on_done(self, event=None): # event=None to handle both button click and key # Retrieve user choices from checkboxes user_choices = { "constrain_range": self.constrain_range_var.get(), - "solve_for_range": self.solve_for_range_var.get() + "solve_for_distance": self.solve_for_distance_var.get() } polynomial_order = int(self.polynomial_order_var.get()) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index b61d11d24..de2413cdf 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -882,15 +882,15 @@ def _get_solved_phase(self, phase_name): static_target=False) phase.set_time_options(fix_initial=False, fix_duration=False, - units="range_units", name=Dynamic.Mission.DISTANCE, + units="distance_units", name=Dynamic.Mission.DISTANCE, duration_bounds=wrapped_convert_units( - phase_options['duration_bounds'], "range_units"), + phase_options['duration_bounds'], "distance_units"), duration_ref=wrapped_convert_units( - phase_options['duration_ref'], "range_units"), + phase_options['duration_ref'], "distance_units"), initial_bounds=wrapped_convert_units( - phase_options['initial_bounds'], "range_units"), + phase_options['initial_bounds'], "distance_units"), initial_ref=wrapped_convert_units( - phase_options['initial_ref'], "range_units"), + phase_options['initial_ref'], "distance_units"), ) if phase_name == "cruise" or phase_name == "descent": @@ -2250,9 +2250,9 @@ def _add_solved_guesses(self, idx, phase_name, phase): if phase_name != "groundroll": range_initial = range_guesses[idx] self.set_val(f"traj.{phase_name}.t_initial", - range_initial, units='range_units') + range_initial, units='distance_units') self.set_val(f"traj.{phase_name}.t_duration", - range_guesses[idx+1] - range_initial, units='range_units') + range_guesses[idx+1] - range_initial, units='distance_units') self.set_val( f"traj.{phase_name}.polynomial_controls:altitude", diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index 74ad71aa8..d5643c06a 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -23,7 +23,7 @@ def setUp(self): "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.2, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.18, 0.74), "unitless"), @@ -47,7 +47,7 @@ def setUp(self): "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.72, "unitless"), "mach_bounds": ((0.7, 0.74), "unitless"), @@ -71,7 +71,7 @@ def setUp(self): "polynomial_control_order": 1, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.72, "unitless"), "final_mach": (0.36, "unitless"), "mach_bounds": ((0.34, 0.74), "unitless"), @@ -163,17 +163,17 @@ def test_mission_optimize_altitude_only(self): self.assertFalse(prob.failed) @require_pyoptsparse(optimizer="IPOPT") - def test_mission_solve_for_range(self): + def test_mission_solve_for_distance(self): modified_phase_info = self.phase_info.copy() for phase in ["climb_1", "climb_2", "descent_1"]: - modified_phase_info[phase]["user_options"]["solve_for_range"] = True + modified_phase_info[phase]["user_options"]["solve_for_distance"] = True prob = self.run_mission(modified_phase_info, "IPOPT") self.assertFalse(prob.failed) - def test_mission_solve_for_range(self): + def test_mission_solve_for_distance(self): modified_phase_info = self.phase_info.copy() for phase in ["climb_1", "climb_2", "descent_1"]: - modified_phase_info[phase]["user_options"]["solve_for_range"] = True + modified_phase_info[phase]["user_options"]["solve_for_distance"] = True prob = self.run_mission(modified_phase_info, "SLSQP") self.assertFalse(prob.failed) diff --git a/aviary/mission/flops_based/phases/simple_energy_phase.py b/aviary/mission/flops_based/phases/simple_energy_phase.py index ae0a2192d..65782f9f0 100644 --- a/aviary/mission/flops_based/phases/simple_energy_phase.py +++ b/aviary/mission/flops_based/phases/simple_energy_phase.py @@ -160,7 +160,7 @@ def build_phase(self, aviary_options: AviaryValues = None): final_mach = user_options.get_item('final_mach')[0] initial_altitude = user_options.get_item('initial_altitude')[0] final_altitude = user_options.get_item('final_altitude')[0] - solve_for_range = user_options.get_val('solve_for_range') + solve_for_distance = user_options.get_val('solve_for_distance') no_descent = user_options.get_val('no_descent') no_climb = user_options.get_val('no_climb') @@ -197,7 +197,7 @@ def build_phase(self, aviary_options: AviaryValues = None): lower=0.0, ref=1e6, defect_ref=1e8, units='m', rate_source=Dynamic.Mission.DISTANCE_RATE, input_initial=input_initial_distance, - solve_segments='forward' if solve_for_range else None, + solve_segments='forward' if solve_for_distance else None, ) phase = add_subsystem_variables_to_phase( @@ -416,7 +416,7 @@ def _extra_ode_init_kwargs(self): EnergyPhase._add_meta_data('altitude_bounds', val=(0., 60.e3), units='ft') -EnergyPhase._add_meta_data('solve_for_range', val=False) +EnergyPhase._add_meta_data('solve_for_distance', val=False) EnergyPhase._add_initial_guess_meta_data( InitialGuessTime(), diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py b/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py index 7155905ea..527a049d8 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py @@ -15,16 +15,16 @@ def initialize(self): def setup(self): nn = self.options["num_nodes"] - self.add_input("dh_dr", shape=nn, units="m/range_units", + self.add_input("dh_dr", shape=nn, units="m/distance_units", desc="change in altitude wrt range") - self.add_input("d2h_dr2", shape=nn, units="m/range_units**2", + self.add_input("d2h_dr2", shape=nn, units="m/distance_units**2", desc="second derivative of altitude wrt range") self.add_output(Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units="rad", desc="flight path angle") - self.add_output("dgam_dr", shape=nn, units="rad/range_units", + self.add_output("dgam_dr", shape=nn, units="rad/distance_units", desc="change in flight path angle per unit range traversed") def setup_partials(self): diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py index 8a87a968d..aefd0f5e5 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py @@ -46,12 +46,12 @@ def setup(self): self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros( nn), desc="flight path angle", units="rad") self.add_input("dh_dr", val=np.zeros( - nn), desc="d(alt)/d(range)", units="m/range_units") + nn), desc="d(alt)/d(range)", units="m/distance_units") self.add_input("d2h_dr2", val=np.zeros( - nn), desc="d(climb_rate)/d(range)", units="1/range_units") + nn), desc="d(climb_rate)/d(range)", units="1/distance_units") # Outputs - self.add_output("dt_dr", shape=nn, units="s/range_units", + self.add_output("dt_dr", shape=nn, units="s/distance_units", desc="Seconds passed per each meter of range covered.", tags=['dymos.state_rate_source:time', 'dymos.state_units:s']) self.add_output("normal_force", val=np.ones(nn), units="N", diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py index 008393c10..f1cdbbc31 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py @@ -107,7 +107,7 @@ def setup(self): self.add_input( "dTAS_dr", val=np.zeros(nn), - units="m/s/range_units", + units="m/s/distance_units", desc="change in true air speed per unit range", ) @@ -206,7 +206,7 @@ def setup(self): self.add_input( "dmach_dr", val=np.zeros(nn), - units="unitless/range_units", + units="unitless/distance_units", desc="change in mach number per unit range", ) self.add_input( diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py index 591f0c7a7..5ad1015b5 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py @@ -214,8 +214,8 @@ def setup(self): self.add_subsystem("mass_rate", om.ExecComp("dmass_dr = fuelflow * dt_dr", fuelflow={"units": "lbm/s", "shape": nn}, - dt_dr={"units": "s/range_units", "shape": nn}, - dmass_dr={"units": "lbm/range_units", + dt_dr={"units": "s/distance_units", "shape": nn}, + dmass_dr={"units": "lbm/distance_units", "shape": nn, "tags": ['dymos.state_rate_source:mass', 'dymos.state_units:lbm']}, @@ -241,5 +241,6 @@ def setup(self): name=Dynamic.Mission.ALTITUDE, val=10000. * onn, units="ft") - self.set_input_defaults(name="dh_dr", val=0. * onn, units="ft/range_units") - self.set_input_defaults(name="d2h_dr2", val=0. * onn, units="ft/range_units**2") + self.set_input_defaults(name="dh_dr", val=0. * onn, units="ft/distance_units") + self.set_input_defaults(name="d2h_dr2", val=0. * onn, + units="ft/distance_units**2") diff --git a/aviary/utils/Fortran_to_Aviary.py b/aviary/utils/Fortran_to_Aviary.py index 3273f0ee5..468b8745a 100644 --- a/aviary/utils/Fortran_to_Aviary.py +++ b/aviary/utils/Fortran_to_Aviary.py @@ -352,7 +352,7 @@ def update_gasp_options(vehicle_data): ## PROBLEM TYPE ## # if multiple values of target_range are specified, use the one that corresponds to the problem_type - design_range, range_units = input_values.get_item(Mission.Design.RANGE) + design_range, distance_units = input_values.get_item(Mission.Design.RANGE) try: problem_type = input_values.get_val('problem_type')[0] except KeyError: @@ -372,7 +372,7 @@ def update_gasp_options(vehicle_data): else: if design_range == 0: input_values.set_val('problem_type', ['fallout']) - input_values.set_val(Mission.Design.RANGE, [design_range], range_units) + input_values.set_val(Mission.Design.RANGE, [design_range], distance_units) ## STRUT AND FOLD ## strut_loc = input_values.get_val(Aircraft.Strut.ATTACHMENT_LOCATION, 'ft')[0] diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 4a38398fb..0f588f9f0 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -284,7 +284,7 @@ def bench_test_swap_4_FwFm_simple(self): "use_polynomial_control": False, "num_segments": 6, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.2, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.1, 0.8), "unitless"), @@ -310,7 +310,7 @@ def bench_test_swap_4_FwFm_simple(self): "use_polynomial_control": True, "num_segments": 1, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.79, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.78, 0.8), "unitless"), @@ -335,7 +335,7 @@ def bench_test_swap_4_FwFm_simple(self): "use_polynomial_control": False, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.79, "unitless"), "final_mach": (0.3, "unitless"), "mach_bounds": ((0.2, 0.8), "unitless"), diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 73a21c057..78945eeba 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -289,7 +289,7 @@ def bench_test_swap_1_GwFm_simple(self): "use_polynomial_control": False, "num_segments": 6, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.2, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.1, 0.8), "unitless"), @@ -315,7 +315,7 @@ def bench_test_swap_1_GwFm_simple(self): "use_polynomial_control": True, "num_segments": 1, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.79, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.78, 0.8), "unitless"), @@ -339,7 +339,7 @@ def bench_test_swap_1_GwFm_simple(self): "use_polynomial_control": False, "num_segments": 5, "order": 3, - "solve_for_range": False, + "solve_for_distance": False, "initial_mach": (0.79, "unitless"), "final_mach": (0.3, "unitless"), "mach_bounds": ((0.2, 0.8), "unitless"), diff --git a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py index e5f7c4ca9..f6ae77aa5 100644 --- a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py +++ b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py @@ -330,7 +330,7 @@ def run_mission(optimizer): static_target=False) phase.set_time_options(fix_initial=False, fix_duration=False, - units="range_units", name=Dynamic.Mission.DISTANCE, + units="distance_units", name=Dynamic.Mission.DISTANCE, duration_bounds=duration_bounds, duration_ref=duration_ref, initial_bounds=initial_bounds, initial_ref=initial_ref) @@ -590,9 +590,9 @@ def run_mission(optimizer): if phase_name != "groundroll": range_initial = range_guesses[idx] p.set_val(f"traj.{phase_name}.t_initial", - range_initial, units='range_units') + range_initial, units='distance_units') p.set_val(f"traj.{phase_name}.t_duration", - range_guesses[idx+1] - range_initial, units='range_units') + range_guesses[idx+1] - range_initial, units='distance_units') p.set_val( f"traj.{phase_name}.polynomial_controls:altitude", @@ -658,12 +658,12 @@ def run_mission(optimizer): p.get_val(f"traj.{phase_name}.timeseries.TAS", units="kn")[-1]) else: range_initial = p.get_val( - f"traj.{phase_name}.t_initial", units='range_units') + f"traj.{phase_name}.t_initial", units='distance_units') if idx > 1: ranges.extend(range_initial) if idx == (len(traj._phases) - 1): ranges.extend( - p.get_val(f"traj.{phase_name}.t_duration", units='range_units') + range_initial) + p.get_val(f"traj.{phase_name}.t_duration", units='distance_units') + range_initial) masses.extend( p.get_val(f"traj.{phase_name}.timeseries.mass", units="lbm")[-1]) alts.extend( From e58da6187c3c8bbd2e9c42fc07de1cffde3d65cb Mon Sep 17 00:00:00 2001 From: johnjasa Date: Wed, 17 Jan 2024 09:52:42 -0600 Subject: [PATCH 054/111] More range->distance --- ...e_same_mission_at_different_UI_levels.ipynb | 2 +- .../default_phase_info/height_energy.py | 2 +- aviary/interface/methods_for_level2.py | 6 +++--- aviary/interface/utils/check_phase_info.py | 2 +- .../test_bench_climb_large_single_aisle_1.py | 6 +++--- .../test_bench_climb_large_single_aisle_2.py | 6 +++--- ..._bench_cruise_climb_large_single_aisle_1.py | 8 ++++---- .../test_bench_cruise_large_single_aisle_1.py | 6 +++--- .../test_bench_cruise_large_single_aisle_2.py | 6 +++--- .../test_bench_descent_large_single_aisle_1.py | 6 +++--- .../test_bench_descent_large_single_aisle_2.py | 6 +++--- .../mission/flops_based/phases/cruise_phase.py | 6 +++--- .../gasp_based/ode/breguet_cruise_ode.py | 2 +- aviary/mission/gasp_based/phases/breguet.py | 6 +++--- .../test/test_custom_engine_model.py | 2 +- .../test_FLOPS_based_full_mission_N3CC.py | 18 +++++++++--------- ..._based_full_mission_large_single_aisle_1.py | 18 +++++++++--------- ..._based_full_mission_large_single_aisle_2.py | 18 +++++++++--------- .../test_FLOPS_based_sizing_N3CC.py | 18 +++++++++--------- .../test_full_mission_solved_ode.py | 12 ++++++------ .../test_subsystems_within_a_mission.py | 2 +- aviary/xdsm/cruise_xdsm.py | 2 +- aviary/xdsm/statics_xdsm.py | 4 ++-- 23 files changed, 82 insertions(+), 82 deletions(-) diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 11ae2115a..1cbe7da34 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -536,7 +536,7 @@ "prob.setup()\n", "\n", "###########################################\n", - "# Intial Settings for States and Controls #\n", + "# Initial Settings for States and Controls #\n", "###########################################\n", "\n", "prob.set_val('traj.climb.t_initial', t_i_climb, units='s')\n", diff --git a/aviary/interface/default_phase_info/height_energy.py b/aviary/interface/default_phase_info/height_energy.py index 1b233943c..c6504dd4c 100644 --- a/aviary/interface/default_phase_info/height_energy.py +++ b/aviary/interface/default_phase_info/height_energy.py @@ -75,7 +75,7 @@ 'max_mach': 0.79, 'required_available_climb_rate': (1.524, 'm/s'), 'mass_f_cruise': (1.e4, 'kg'), - 'range_f_cruise': (1.e6, 'm'), + 'distance_f_cruise': (1.e6, 'm'), }, 'initial_guesses': { 'times': ([26.2, 406.18], 'min'), diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index de2413cdf..e1e0665da 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2248,11 +2248,11 @@ def _add_solved_guesses(self, idx, phase_name, phase): time_guesses = np.hstack((0., np.cumsum(range_durations / mean_TAS))) if phase_name != "groundroll": - range_initial = range_guesses[idx] + distance_initial = range_guesses[idx] self.set_val(f"traj.{phase_name}.t_initial", - range_initial, units='distance_units') + distance_initial, units='distance_units') self.set_val(f"traj.{phase_name}.t_duration", - range_guesses[idx+1] - range_initial, units='distance_units') + range_guesses[idx+1] - distance_initial, units='distance_units') self.set_val( f"traj.{phase_name}.polynomial_controls:altitude", diff --git a/aviary/interface/utils/check_phase_info.py b/aviary/interface/utils/check_phase_info.py index cc40add8b..bf50c25b0 100644 --- a/aviary/interface/utils/check_phase_info.py +++ b/aviary/interface/utils/check_phase_info.py @@ -40,7 +40,7 @@ def check_phase_info(phase_info, mission_method): 'max_mach': float, 'required_available_climb_rate': tuple, 'mass_f_cruise': tuple, - 'range_f_cruise': tuple, + 'distance_f_cruise': tuple, 'fix_final': bool, } diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py index 7c7c97277..bea55f9e3 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_1.py @@ -84,8 +84,8 @@ def run_trajectory(): v_f_climb = 455.49*_units.knot # m/s mach_i_climb = 0.3 mach_f_climb = 0.79 - range_i_climb = 0*_units.nautical_mile # m - range_f_climb = 160.3*_units.nautical_mile # m + distance_i_climb = 0*_units.nautical_mile # m + distance_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 @@ -150,7 +150,7 @@ def run_trajectory(): prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py index 761b30e97..571762eed 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_climb_large_single_aisle_2.py @@ -78,8 +78,8 @@ def run_trajectory(): v_f_climb = 452.61 * _units.knot # m/s mach_i_climb = 0.3 mach_f_climb = 0.775 - range_i_climb = 0 * _units.nautical_mile # m - range_f_climb = 124 * _units.nautical_mile # m + distance_i_climb = 0 * _units.nautical_mile # m + distance_f_climb = 124 * _units.nautical_mile # m t_i_climb = 0 t_f_climb = 20.14 * _units.minute # sec @@ -153,7 +153,7 @@ def run_trajectory(): prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py index 7e6249379..3b4fa232b 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_climb_large_single_aisle_1.py @@ -84,8 +84,8 @@ def run_trajectory(): mach_f_cruise = 0.79 mach_min_cruise = 0.78999 mach_max_cruise = 0.79001 - range_i_cruise = 160.3*_units.nautical_mile # m - range_f_cruise = 3243.9*_units.nautical_mile # m + distance_i_cruise = 160.3*_units.nautical_mile # m + distance_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 @@ -116,7 +116,7 @@ def run_trajectory(): no_descent=True, velocity_f_cruise=velocity_f_cruise, mass_f_cruise=mass_f_cruise, - range_f_cruise=range_f_cruise, + distance_f_cruise=distance_f_cruise, ) @@ -173,7 +173,7 @@ def run_trajectory(): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py index 353a9acc0..396b54d0f 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_1.py @@ -88,8 +88,8 @@ def run_trajectory(): mach_f_cruise = 0.79 mach_min_cruise = 0.79 mach_max_cruise = 0.79 - range_i_cruise = 160.3*_units.nautical_mile # m - range_f_cruise = 3243.9*_units.nautical_mile # m + distance_i_cruise = 160.3*_units.nautical_mile # m + distance_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 @@ -172,7 +172,7 @@ def run_trajectory(): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py index 26f8a4a1b..fa568f67f 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_cruise_large_single_aisle_2.py @@ -91,8 +91,8 @@ def run_trajectory(): mach_f_cruise = 0.785 mach_min_cruise = 0.785 mach_max_cruise = 0.785 - range_i_cruise = 116.6*_units.nautical_mile # m - range_f_cruise = 2558.3*_units.nautical_mile # m + distance_i_cruise = 116.6*_units.nautical_mile # m + distance_f_cruise = 2558.3*_units.nautical_mile # m t_i_cruise = 19.08*_units.minute # sec t_f_cruise = 342.77*_units.minute # sec t_duration_cruise = t_f_cruise - t_i_cruise # sec @@ -163,7 +163,7 @@ def run_trajectory(): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py index 811648701..1ee66a43d 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_1.py @@ -86,8 +86,8 @@ def run_trajectory(): mach_f_descent = 0.3 mass_i_descent = 143521*_units.pound mass_f_descent = 143035*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_f_descent = 3378.7*_units.nautical_mile + 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 @@ -148,7 +148,7 @@ def run_trajectory(): prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), diff --git a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py index 251b86944..1395dfbc8 100644 --- a/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py +++ b/aviary/mission/flops_based/phases/benchmark_tests/test_bench_descent_large_single_aisle_2.py @@ -89,8 +89,8 @@ def run_trajectory(): mach_f = 0.3 mass_i = 140515*_units.pound mass_f = 140002*_units.pound - range_i = 2830.8*_units.nautical_mile - range_f = 2960.0*_units.nautical_mile + distance_i = 2830.8*_units.nautical_mile + distance_f = 2960.0*_units.nautical_mile t_i_descent = 0.0 t_f_descent = 2000.0 @@ -148,7 +148,7 @@ def run_trajectory(): prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i, mass_f]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[range_i, range_f]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i, distance_f]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), diff --git a/aviary/mission/flops_based/phases/cruise_phase.py b/aviary/mission/flops_based/phases/cruise_phase.py index 4bc0f4796..184297c14 100644 --- a/aviary/mission/flops_based/phases/cruise_phase.py +++ b/aviary/mission/flops_based/phases/cruise_phase.py @@ -177,7 +177,7 @@ def build_phase(self, aviary_options: AviaryValues = None): num_engines = len(aviary_options.get_val('engine_models')) input_initial = user_options.get_val('input_initial') mass_f_cruise = user_options.get_val('mass_f_cruise', units='kg') - range_f_cruise = user_options.get_val('range_f_cruise', units='m') + distance_f_cruise = user_options.get_val('distance_f_cruise', units='m') polynomial_control_order = user_options.get_item('polynomial_control_order')[0] ############## @@ -216,7 +216,7 @@ def build_phase(self, aviary_options: AviaryValues = None): fix_initial_distance = get_initial(fix_initial, Dynamic.Mission.DISTANCE, True) phase.add_state( Dynamic.Mission.DISTANCE, fix_initial=fix_initial_distance, fix_final=fix_final, - lower=0.0, ref=range_f_cruise, defect_ref=range_f_cruise, units='m', + lower=0.0, ref=distance_f_cruise, defect_ref=distance_f_cruise, units='m', rate_source=Dynamic.Mission.DISTANCE_RATE, input_initial=input_initial_distance ) @@ -396,7 +396,7 @@ def _extra_ode_init_kwargs(self): Cruise._add_meta_data('mass_f_cruise', val=1.e4, units='kg') -Cruise._add_meta_data('range_f_cruise', val=1.e6, units='m') +Cruise._add_meta_data('distance_f_cruise', val=1.e6, units='m') Cruise._add_meta_data( 'required_available_climb_rate', val=None, units='m/s', diff --git a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py index 8097210ac..a67cca601 100644 --- a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py @@ -125,7 +125,7 @@ def setup(self): "eom", RangeComp(num_nodes=nn), promotes_inputs=[ - ("cruise_range_initial", "initial_distance"), + ("cruise_distance_initial", "initial_distance"), ("cruise_time_initial", "initial_time"), "mass", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, diff --git a/aviary/mission/gasp_based/phases/breguet.py b/aviary/mission/gasp_based/phases/breguet.py index 762dd8278..f798d3735 100644 --- a/aviary/mission/gasp_based/phases/breguet.py +++ b/aviary/mission/gasp_based/phases/breguet.py @@ -15,7 +15,7 @@ def setup(self): self.add_input("cruise_time_initial", val=0.0, units="s", desc="time at which cruise begins") - self.add_input("cruise_range_initial", val=0.0, units="NM", + self.add_input("cruise_distance_initial", val=0.0, units="NM", desc="range reference at which cruise begins") self.add_input("TAS_cruise", val=0.8 * np.ones(nn), @@ -64,7 +64,7 @@ def setup_partials(self): self.declare_partials( "cruise_time", [Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "mass", "TAS_cruise"], rows=rs, cols=cs) - self.declare_partials("cruise_range", "cruise_range_initial", val=1.0) + self.declare_partials("cruise_range", "cruise_distance_initial", val=1.0) self.declare_partials("cruise_time", "cruise_time_initial", val=1.0) # Allocated memory so we don't have to repeatedly do it in compute_partials @@ -78,7 +78,7 @@ def compute(self, inputs, outputs): v_x = inputs["TAS_cruise"] m = inputs["mass"] FF = -inputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] - r0 = inputs["cruise_range_initial"] + r0 = inputs["cruise_distance_initial"] t0 = inputs["cruise_time_initial"] FF_1 = FF[:-1] # Initial fuel flow across each two-node pair diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index 0bfeafbce..693c7871c 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -161,7 +161,7 @@ def test_custom_engine(self): 'required_available_climb_rate': (1.524, 'm/s'), 'input_initial': False, 'mass_f_cruise': (1.e4, 'lbm'), - 'range_f_cruise': (1.e6, 'm'), + 'distance_f_cruise': (1.e6, 'm'), }, 'initial_guesses': { 'times': ([0., 30.], 'min'), diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py index 53264e0d9..4ae6d3e1d 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py @@ -81,8 +81,8 @@ def run_trajectory(driver: Driver, sim=True): # 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 + distance_i_climb = 0*_units.nautical_mile # m + distance_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 @@ -97,8 +97,8 @@ def run_trajectory(driver: Driver, sim=True): v_f_cruise = 455.49*_units.knot # m/s mach_min_cruise = cruise_mach mach_max_cruise = cruise_mach - range_i_cruise = 160.3*_units.nautical_mile # m - range_f_cruise = 3243.9*_units.nautical_mile # m + distance_i_cruise = 160.3*_units.nautical_mile # m + distance_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 @@ -113,8 +113,8 @@ def run_trajectory(driver: Driver, sim=True): mach_f_descent = 0.3 mass_i_descent = 102000*_units.pound mass_f_descent = 101000*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_f_descent = 3378.7*_units.nautical_mile + 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 @@ -372,7 +372,7 @@ def run_trajectory(driver: Driver, sim=True): prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.0]), @@ -391,7 +391,7 @@ def run_trajectory(driver: Driver, sim=True): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -410,7 +410,7 @@ def run_trajectory(driver: Driver, sim=True): prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py index b7143e37c..a5b6cca94 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py @@ -87,8 +87,8 @@ def run_trajectory(sim=True): # mach_i_climb = 0.3 mach_i_climb = 0.2 mach_f_climb = 0.79 - range_i_climb = 0*_units.nautical_mile # m - range_f_climb = 160.3*_units.nautical_mile # m + distance_i_climb = 0*_units.nautical_mile # m + distance_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 @@ -105,8 +105,8 @@ def run_trajectory(sim=True): # mach_f_cruise = 0.79 mach_min_cruise = 0.79 mach_max_cruise = 0.79 - range_i_cruise = 160.3*_units.nautical_mile # m - range_f_cruise = 3243.9*_units.nautical_mile # m + distance_i_cruise = 160.3*_units.nautical_mile # m + distance_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 @@ -121,8 +121,8 @@ def run_trajectory(sim=True): mach_f_descent = 0.3 mass_i_descent = 143521*_units.pound mass_f_descent = 143035*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_f_descent = 3378.7*_units.nautical_mile + 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 @@ -378,7 +378,7 @@ def run_trajectory(sim=True): prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -397,7 +397,7 @@ def run_trajectory(sim=True): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -416,7 +416,7 @@ def run_trajectory(sim=True): prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.05]), diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py index 37b176bc6..76566f394 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py @@ -85,8 +85,8 @@ def run_trajectory(sim=True): v_f_climb = 452.61*_units.knot # m/s mach_i_climb = 0.2 # TODO: (need to compute this in takeoff) mach_f_climb = 0.785 - range_i_climb = 0*_units.nautical_mile # m (comes from takeoff) - range_f_climb = 124*_units.nautical_mile # m + distance_i_climb = 0*_units.nautical_mile # m (comes from takeoff) + distance_f_climb = 124*_units.nautical_mile # m t_i_climb = 0 t_duration_climb = 20.14*_units.minute # sec @@ -101,8 +101,8 @@ def run_trajectory(sim=True): mach_f_cruise = 0.785 mach_min_cruise = 0.785 mach_max_cruise = 0.785 - range_i_cruise = 124*_units.nautical_mile # m - range_f_cruise = 2830.8*_units.nautical_mile # m + distance_i_cruise = 124*_units.nautical_mile # m + distance_f_cruise = 2830.8*_units.nautical_mile # m t_i_cruise = t_i_climb + t_duration_climb # sec t_duration_cruise = (378.95)*_units.minute - t_duration_climb # sec @@ -114,8 +114,8 @@ def run_trajectory(sim=True): mass_f_descent = 140002*_units.pound # kg mach_i_descent = mach_f_cruise mach_f_descent = 0.3 - range_i_descent = 2830.8*_units.nautical_mile # m - range_f_descent = 2960.0*_units.nautical_mile # m + distance_i_descent = 2830.8*_units.nautical_mile # m + distance_f_descent = 2960.0*_units.nautical_mile # m t_i_descent = t_duration_cruise+t_duration_climb # sec t_duration_descent = 2000 # sec @@ -364,7 +364,7 @@ def run_trajectory(sim=True): prob.set_val('traj.climb.states:mass', climb.interp( Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.25, 0.05]), @@ -383,7 +383,7 @@ def run_trajectory(sim=True): prob.set_val('traj.cruise.states:mass', cruise.interp( Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp(Dynamic.Mission.VELOCITY_RATE, ys=[0.0, 0.0]), @@ -402,7 +402,7 @@ def run_trajectory(sim=True): prob.set_val('traj.descent.states:mass', descent.interp( Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[range_i_descent, range_f_descent]), units='m') + Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp(Dynamic.Mission.VELOCITY_RATE, ys=[-0.25, 0.0]), diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index d94000a25..4d05ca9f4 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -101,8 +101,8 @@ def run_trajectory(sim=True): # mach_i_climb = 0.3 mach_i_climb = 0.2 mach_f_climb = 0.79 - range_i_climb = 0*_units.nautical_mile # m - range_f_climb = 160.3*_units.nautical_mile # m + distance_i_climb = 0*_units.nautical_mile # m + distance_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 @@ -117,8 +117,8 @@ def run_trajectory(sim=True): v_f_cruise = 455.49*_units.knot # m/s mach_min_cruise = 0.79 mach_max_cruise = 0.79 - range_i_cruise = 160.3*_units.nautical_mile # m - range_f_cruise = 3243.9*_units.nautical_mile # m + distance_i_cruise = 160.3*_units.nautical_mile # m + distance_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 @@ -133,8 +133,8 @@ def run_trajectory(sim=True): mach_f_descent = 0.3 mass_i_descent = 102000*_units.pound mass_f_descent = 101000*_units.pound - range_i_descent = 3243.9*_units.nautical_mile - range_f_descent = 3378.7*_units.nautical_mile + 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 @@ -454,7 +454,7 @@ def run_trajectory(sim=True): prob.set_val('traj.climb.states:mass', climb.interp( 'mass', ys=[mass_i_climb, mass_f_climb]), units='kg') prob.set_val('traj.climb.states:distance', climb.interp( - 'distance', ys=[range_i_climb, range_f_climb]), units='m') # nmi + 'distance', ys=[distance_i_climb, distance_f_climb]), units='m') # nmi prob.set_val('traj.climb.controls:velocity_rate', climb.interp('velocity_rate', ys=[0.25, 0.05]), @@ -473,7 +473,7 @@ def run_trajectory(sim=True): prob.set_val('traj.cruise.states:mass', cruise.interp( 'mass', ys=[mass_i_cruise, mass_f_cruise]), units='kg') prob.set_val('traj.cruise.states:distance', cruise.interp( - 'distance', ys=[range_i_cruise, range_f_cruise]), units='m') # nmi + 'distance', ys=[distance_i_cruise, distance_f_cruise]), units='m') # nmi prob.set_val('traj.cruise.controls:velocity_rate', cruise.interp('velocity_rate', ys=[0.0, 0.0]), @@ -492,7 +492,7 @@ def run_trajectory(sim=True): prob.set_val('traj.descent.states:mass', descent.interp( 'mass', ys=[mass_i_descent, mass_f_descent]), units='kg') prob.set_val('traj.descent.states:distance', descent.interp( - 'distance', ys=[range_i_descent, range_f_descent]), units='m') + 'distance', ys=[distance_i_descent, distance_f_descent]), units='m') prob.set_val('traj.descent.controls:velocity_rate', descent.interp('velocity_rate', ys=[-0.25, 0.05]), diff --git a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py index f6ae77aa5..e1894f237 100644 --- a/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py +++ b/aviary/validation_cases/benchmark_tests/test_full_mission_solved_ode.py @@ -588,11 +588,11 @@ def run_mission(optimizer): for idx, (phase_name, phase) in enumerate(traj._phases.items()): if phase_name != "groundroll": - range_initial = range_guesses[idx] + distance_initial = range_guesses[idx] p.set_val(f"traj.{phase_name}.t_initial", - range_initial, units='distance_units') + distance_initial, units='distance_units') p.set_val(f"traj.{phase_name}.t_duration", - range_guesses[idx+1] - range_initial, units='distance_units') + range_guesses[idx+1] - distance_initial, units='distance_units') p.set_val( f"traj.{phase_name}.polynomial_controls:altitude", @@ -657,13 +657,13 @@ def run_mission(optimizer): TASs.extend( p.get_val(f"traj.{phase_name}.timeseries.TAS", units="kn")[-1]) else: - range_initial = p.get_val( + distance_initial = p.get_val( f"traj.{phase_name}.t_initial", units='distance_units') if idx > 1: - ranges.extend(range_initial) + ranges.extend(distance_initial) if idx == (len(traj._phases) - 1): ranges.extend( - p.get_val(f"traj.{phase_name}.t_duration", units='distance_units') + range_initial) + p.get_val(f"traj.{phase_name}.t_duration", units='distance_units') + distance_initial) masses.extend( p.get_val(f"traj.{phase_name}.timeseries.mass", units="lbm")[-1]) alts.extend( diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index 9158440ad..f1b16fb74 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -46,7 +46,7 @@ def setUp(self): 'required_available_climb_rate': (1.524, 'm/s'), 'input_initial': False, 'mass_f_cruise': (1.e4, 'lbm'), - 'range_f_cruise': (1.e6, 'm'), + 'distance_f_cruise': (1.e6, 'm'), }, 'initial_guesses': { 'times': ([0., 15000.], 's'), diff --git a/aviary/xdsm/cruise_xdsm.py b/aviary/xdsm/cruise_xdsm.py index 73ff201cc..2f7b5675f 100644 --- a/aviary/xdsm/cruise_xdsm.py +++ b/aviary/xdsm/cruise_xdsm.py @@ -40,7 +40,7 @@ ]) x.add_input("breguet_eom", [ Dynamic.Mission.MASS, - "cruise_range_initial", + "cruise_distance_initial", "cruise_time_initial", ]) x.add_input("weight", ["mass"]) diff --git a/aviary/xdsm/statics_xdsm.py b/aviary/xdsm/statics_xdsm.py index e4583c487..2d5c5eed5 100644 --- a/aviary/xdsm/statics_xdsm.py +++ b/aviary/xdsm/statics_xdsm.py @@ -363,12 +363,12 @@ Dynamic.Mission.MACH, "mass_initial", "cruise_time_initial", - "cruise_range_initial"], + "cruise_distance_initial"], ) x.connect("dymos", "descent1", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) x.connect("dymos", "fuelburn", [Mission.Landing.TOUCHDOWN_MASS]) x.connect("dymos", Dynamic.Mission.DISTANCE, [Mission.Summary.RANGE]) -x.connect("cruise", "dymos", ["cruise_time_final", "cruise_range_final"]) +x.connect("cruise", "dymos", ["cruise_time_final", "cruise_distance_final"]) # Add Design Variables x.connect( From cae8c66ce562297b3aab0619e4037f26d213f95f Mon Sep 17 00:00:00 2001 From: Gregory Wrenn Date: Wed, 17 Jan 2024 11:03:25 -0500 Subject: [PATCH 055/111] [no ci] Changed NUM_PASSENGERS to 169 from 180 in one test file to match passenger class entries. Reinstated the test to check that passenger class data match the total number of passengers when both types are input. --- aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- aviary/utils/preprocessors.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 5c0d0b8a0..92d47e871 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -21,7 +21,7 @@ aircraft:crew_and_payload:num_flight_attendants,3,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,0,unitless aircraft:crew_and_payload:num_non_flight_crew,3,unitless -aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_passengers,169,unitless aircraft:crew_and_payload:num_tourist_class,158,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 28f222f7b..c2cce0604 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -55,9 +55,10 @@ def preprocess_crewpayload(aviary_options: AviaryValues): passenger_check += aviary_options.get_val( Aircraft.CrewPayload.NUM_BUSINESS_CLASS) passenger_check += aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS) - # if passenger_count != passenger_check: - # raise om.AnalysisError( - # "ERROR: In preprocesssors.py: passenger_count does not equal the sum of firt class + business class + tourist class passengers.") + # only perform check if at least one passenger class is entered + if passenger_check > 0 and passenger_count != passenger_check: + raise om.AnalysisError( + "ERROR: In preprocesssors.py: passenger_count does not equal the sum of firt class + business class + tourist class passengers.") if Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS not in aviary_options: flight_attendants_count = 0 # assume no passengers From e41821f29c50650d41d431dd021bf0e15ba75f49 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Wed, 17 Jan 2024 10:16:36 -0600 Subject: [PATCH 056/111] Fixed doc --- aviary/docs/getting_started/onboarding_level2.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index 5bb5fb516..3a4fd85ce 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -651,7 +651,7 @@ " 'fix_final': False,\n", " 'required_available_climb_rate': (1.524, 'm/s'),\n", " 'mass_f_cruise': (1.e4, 'lbm'),\n", - " 'range_f_cruise': (1.e6, 'm'),\n", + " 'distance_f_cruise': (1.e6, 'm'),\n", " },\n", " 'initial_guesses': {\n", " 'times': ([26.2, 406.18], 'min'),\n", From 733ccf150c19cbf411f1436a2cbcea677d6bd3c4 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Wed, 17 Jan 2024 14:14:31 -0500 Subject: [PATCH 057/111] upd climb_ode with Altitude_rate_max output --- aviary/mission/gasp_based/ode/climb_ode.py | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index e9182e92b..2a7ea910e 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -14,6 +14,8 @@ from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType from aviary.variable_info.variables import Dynamic +from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate class ClimbODE(BaseODE): @@ -197,6 +199,28 @@ def setup(self): ], ) + lift_balance_group.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=["TAS", Dynamic.Mission.MASS, + Dynamic.Mission.THRUST_MAX_TOTAL, Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + # Note when TAS_rate = 0, SPECIFIC_ENERGY_RATE_EXCESS = ALTITUDE_RATE_MAX + lift_balance_group.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + "TAS_rate", + "TAS"], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + self.AddAlphaControl( alpha_group=lift_balance_group, alpha_mode=AlphaModes.REQUIRED_LIFT, From 70c5d4494ad29a4852f593409995f6eb660f9a82 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Wed, 17 Jan 2024 14:35:08 -0500 Subject: [PATCH 058/111] moved ALTITUDE_RATE_MAX calc outside of balance, climb tests failing cannot find THRUST_MAX_TOTAL --- aviary/mission/gasp_based/ode/climb_ode.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index 2a7ea910e..c85752ac4 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -199,24 +199,25 @@ def setup(self): ], ) - lift_balance_group.add_subsystem( + # defalting to outside the balance to minimize calcs. + self.add_subsystem( name='SPECIFIC_ENERGY_RATE_EXCESS', subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=["TAS", Dynamic.Mission.MASS, + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, Dynamic.Mission.THRUST_MAX_TOTAL, Dynamic.Mission.DRAG], promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] ) # Note when TAS_rate = 0, SPECIFIC_ENERGY_RATE_EXCESS = ALTITUDE_RATE_MAX - lift_balance_group.add_subsystem( + self.add_subsystem( name='ALTITUDE_RATE_MAX', subsys=AltitudeRate(num_nodes=nn), promotes_inputs=[ (Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), - "TAS_rate", - "TAS"], + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], promotes_outputs=[ (Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)]) From 808e673d5a17636876ed1f0c645e1d6a2391257b Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Wed, 17 Jan 2024 14:41:18 -0500 Subject: [PATCH 059/111] Adding tmate session --- .github/workflows/test_workflow.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 3edbe2f3e..6927d7b51 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,6 +213,10 @@ jobs: python run_all.py cd ../.. + # - name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + + - name: Run tests if: matrix.MAKE_DOCS == 0 shell: bash -l {0} From c6216fffc8e6be89e4d6178eb78da1dfb88b7bdf Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Wed, 17 Jan 2024 14:45:18 -0500 Subject: [PATCH 060/111] Adding and uncommentingtmate session --- .github/workflows/test_workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 6927d7b51..436b1947c 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,8 +213,8 @@ jobs: python run_all.py cd ../.. - # - name: Setup tmate session - # uses: mxschmitt/action-tmate@v3 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: Run tests From 07267c0c9daa11426c084e6ac34154442bfc3303 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Wed, 17 Jan 2024 16:52:22 -0600 Subject: [PATCH 061/111] Added battery data for example --- .github/install_env_from_github.sh | 4 +--- .../onboarding_ext_subsystem.ipynb | 2 +- .../model/reg_thevenin_interp_group.py | 23 +++++++++++++------ setup.py | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.github/install_env_from_github.sh b/.github/install_env_from_github.sh index fb5eb9cf9..a87cd103f 100755 --- a/.github/install_env_from_github.sh +++ b/.github/install_env_from_github.sh @@ -49,7 +49,7 @@ fi # pyoptsparse_line=$(grep ' pyoptsparse' $input_yaml | sed 's/^ //') # Remove specified packages and write to an intermediate file -grep -v -e 'aviary' -e 'om-aviary' -e 'build-pyoptsparse' -e 'pyoptsparse' -e 'boring-battery' -e 'networkx' -e ' - pip:' $input_yaml > $intermediate_yaml +grep -v -e 'aviary' -e 'om-aviary' -e 'build-pyoptsparse' -e 'pyoptsparse' -e 'networkx' -e ' - pip:' $input_yaml > $intermediate_yaml # Check for 'dev' versions of OpenMDAO and Dymos if grep -q -e 'openmdao.*dev' $intermediate_yaml; then @@ -99,8 +99,6 @@ conda activate $env_name # Check flags and install special packages if needed pip install -r $requirements_txt -pip install "boring_battery @ git+https://github.com/jcchin/boring.git" - if [ "$install_openmdao_from_git" = true ]; then pip install git+https://github.com/OpenMDAO/OpenMDAO.git fi diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index 5b6ac3718..e9052b03b 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -755,7 +755,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.8.17" } }, "nbformat": 4, diff --git a/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py b/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py index d9096214f..ed271a289 100644 --- a/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py +++ b/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py @@ -2,7 +2,16 @@ from openmdao.api import Group, MetaModelStructuredComp -from boring.src.model.maps.s18650_battery import battery + +# These battery values are entirely fabricated and not representative of any real battery. +# This model is used as an example of how to integrate external subsystems in Aviary. +T_bp = np.array([0., 60.]) +SOC_bp = np.linspace(0., 1., 32) + +tU_oc = np.vstack((np.linspace(2.8, 4.2, 32), np.linspace(2.7, 4.1, 32))) +tC_Th = np.ones((2, 32)) * 1000.0 +tR_Th = np.vstack((np.linspace(0.06, 0.03, 32), np.linspace(0.04, 0.02, 32))) +tR_0 = np.vstack((np.linspace(0.06, 0.03, 32), np.linspace(0.04, 0.02, 32))) class RegTheveninInterpGroup(Group): @@ -16,13 +25,13 @@ def setup(self): thevenin_interp_comp = MetaModelStructuredComp(method='slinear', vec_size=n, training_data_gradients=False, extrapolate=True) - thevenin_interp_comp.add_input('T_batt', 1.0, battery.T_bp, units='degC') - thevenin_interp_comp.add_input('SOC', 1.0, battery.SOC_bp, units=None) - thevenin_interp_comp.add_output('C_Th', 1.0, battery.tC_Th, units='F') + thevenin_interp_comp.add_input('T_batt', 1.0, T_bp, units='degC') + thevenin_interp_comp.add_input('SOC', 1.0, SOC_bp, units=None) + thevenin_interp_comp.add_output('C_Th', 1.0, tC_Th, units='F') # add R_th and R_0 to get total R - thevenin_interp_comp.add_output('R_Th', 1.0, battery.tR_Th, units='ohm') - thevenin_interp_comp.add_output('R_0', 1.0, battery.tR_0, units='ohm') - thevenin_interp_comp.add_output('U_oc', 1.0, battery.tU_oc, units='V') + thevenin_interp_comp.add_output('R_Th', 1.0, tR_Th, units='ohm') + thevenin_interp_comp.add_output('R_0', 1.0, tR_0, units='ohm') + thevenin_interp_comp.add_output('U_oc', 1.0, tU_oc, units='V') self.add_subsystem(name='interp_comp', subsys=thevenin_interp_comp, diff --git a/setup.py b/setup.py index 4412061a9..52eaa3235 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ pkgname = "aviary" extras_require = { "test": ["testflo", "pyxdsm", "pre-commit"], - "examples": ["openaerostruct", "ambiance", "boring_battery @ git+https://github.com/jcchin/boring.git"], + "examples": ["openaerostruct", "ambiance"], } all_packages = [] From 5bc9b4eea8898945ff3c3bf38f60cfd8e4613dac Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 18 Jan 2024 09:59:30 -0500 Subject: [PATCH 062/111] fix bug in subsytem tester --- aviary/subsystems/test/subsystem_tester.py | 5 ++++- setup.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aviary/subsystems/test/subsystem_tester.py b/aviary/subsystems/test/subsystem_tester.py index 4a65edb0d..0f16f37db 100644 --- a/aviary/subsystems/test/subsystem_tester.py +++ b/aviary/subsystems/test/subsystem_tester.py @@ -23,7 +23,10 @@ def import_builder(path_to_builder: str, base_package='aviary.examples.external_ ''' try: package, method = path_to_builder.rsplit('.', 1) - module = import_module(package, base_package) + package_path, package_name = package.rsplit('.', 1) + module_path = '.'.join([path_to_builder, package_path]) if package_path \ + else path_to_builder + module = import_module(package_name, module_path) builder = getattr(module, method) except ImportError: builder = 'Skipping due to missing dependencies' diff --git a/setup.py b/setup.py index 4412061a9..35cb14eaa 100644 --- a/setup.py +++ b/setup.py @@ -65,7 +65,7 @@ "visualization/assets/*", "visualization/assets/aviary_vars/*" ], - 'aviary.docs': ['*.py', + f"{pkgname}.docs": ['*.py', 'tests/*.py', '*/*.md', '*/*.ipynb', From d840553ffa002a5db7dbc40675a67a522d2e8dd8 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 18 Jan 2024 10:42:18 -0500 Subject: [PATCH 063/111] small cleanups --- aviary/interface/methods_for_level2.py | 1 - aviary/utils/process_input_decks.py | 4 ---- 2 files changed, 5 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 3cb04126c..0b2a87cce 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -167,7 +167,6 @@ def load_inputs(self, aviary_inputs, phase_info=None, engine_builder=None): # Create AviaryValues object from file (or process existing AviaryValues object # with default values from metadata) and generate initial guesses aviary_inputs, initial_guesses = create_vehicle(aviary_inputs) - # aviary_inputs = self.aviary_inputs # pull which methods will be used for subsystems and mission self.mission_method = mission_method = aviary_inputs.get_val( diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 840d254f6..469a1224b 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -160,10 +160,6 @@ def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): GASP_defaults.update(aircraft_values) aircraft_values = GASP_defaults - for var in initial_guesses: - if var in aircraft_values: - initial_guesses[var], _ = aircraft_values.get_item(var) - # update the options that depend on variables update_dependent_options(aircraft_values, dependent_options) From 3d69eb2fa437f0ac1744498dc7ecce1c64cce48e Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 18 Jan 2024 10:59:12 -0500 Subject: [PATCH 064/111] fix indent in setup.py --- setup.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 35cb14eaa..822a255b5 100644 --- a/setup.py +++ b/setup.py @@ -65,12 +65,14 @@ "visualization/assets/*", "visualization/assets/aviary_vars/*" ], - f"{pkgname}.docs": ['*.py', - 'tests/*.py', - '*/*.md', - '*/*.ipynb', - '*/*/*.md', - '*/*/*.ipynb',], + f"{pkgname}.docs": [ + "*.py", + "tests/*.py", + "*/*.md", + "*/*.ipynb", + "*/*/*.md", + "*/*/*.ipynb", + ], f"{pkgname}.subsystems.aero.test.data": ["*.csv"], f"{pkgname}.subsystems.prop.test": ["*.csv"], }, From 10e436b45e9717dc45842db0614d349926c04faa Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 11:21:28 -0500 Subject: [PATCH 065/111] successfully moved ClimbODE edits out of balance --- aviary/mission/gasp_based/ode/accel_ode.py | 25 +++++++++++ aviary/mission/gasp_based/ode/climb_ode.py | 49 +++++++++++----------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/aviary/mission/gasp_based/ode/accel_ode.py b/aviary/mission/gasp_based/ode/accel_ode.py index eae09fe28..f47fc29e2 100644 --- a/aviary/mission/gasp_based/ode/accel_ode.py +++ b/aviary/mission/gasp_based/ode/accel_ode.py @@ -9,6 +9,8 @@ from aviary.subsystems.mass.mass_to_weight import MassToWeight from aviary.variable_info.enums import AnalysisScheme, SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate class AccelODE(BaseODE): @@ -93,6 +95,29 @@ def setup(self): + sgm_outputs, ) + # the last two subsystems will also be used for constraints + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + ParamPort.set_default_vals(self) self.set_input_defaults(Dynamic.Mission.MASS, val=14e4 * np.ones(nn), units="lbm") diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index c85752ac4..f112ea38c 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -199,29 +199,6 @@ def setup(self): ], ) - # defalting to outside the balance to minimize calcs. - self.add_subsystem( - name='SPECIFIC_ENERGY_RATE_EXCESS', - subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_MAX_TOTAL, Dynamic.Mission.DRAG], - promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] - ) - - # Note when TAS_rate = 0, SPECIFIC_ENERGY_RATE_EXCESS = ALTITUDE_RATE_MAX - self.add_subsystem( - name='ALTITUDE_RATE_MAX', - subsys=AltitudeRate(num_nodes=nn), - promotes_inputs=[ - (Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), - (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), - (Dynamic.Mission.VELOCITY, "TAS")], - promotes_outputs=[ - (Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.ALTITUDE_RATE_MAX)]) - self.AddAlphaControl( alpha_group=lift_balance_group, alpha_mode=AlphaModes.REQUIRED_LIFT, @@ -243,9 +220,33 @@ def setup(self): + constraint_inputs, promotes_outputs=["theta", "TAS_violation"], ) + + # the last two subsystems will also be used for constraints + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + if analysis_scheme is AnalysisScheme.COLLOCATION: self.set_order(['params', 'USatm', 'mach_balance_group'] + prop_groups + - ['lift_balance_group', 'constraints']) + ['lift_balance_group', 'constraints', 'SPECIFIC_ENERGY_RATE_EXCESS', 'ALTITUDE_RATE_MAX']) ParamPort.set_default_vals(self) self.set_input_defaults("CL_max", val=5 * np.ones(nn), units="unitless") From 281266d0db63a17d51b579cfe148e4c93ebca50f Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Thu, 18 Jan 2024 11:43:10 -0500 Subject: [PATCH 066/111] Commented out tmate --- .github/workflows/test_workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 436b1947c..6927d7b51 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,8 +213,8 @@ jobs: python run_all.py cd ../.. - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + # - name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 - name: Run tests From 97688d687d86f2df1ab57d28c80fcb5e563c7e64 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 11:47:58 -0500 Subject: [PATCH 067/111] climb_start_range to climb_start_distance --- aviary/docs/getting_started/onboarding_level3.ipynb | 12 ++++++------ ..._of_the_same_mission_at_different_UI_levels.ipynb | 6 +++--- .../test_FLOPS_based_full_mission_N3CC.py | 6 +++--- ..._FLOPS_based_full_mission_large_single_aisle_1.py | 6 +++--- ..._FLOPS_based_full_mission_large_single_aisle_2.py | 6 +++--- .../benchmark_tests/test_FLOPS_based_sizing_N3CC.py | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index 6d8915358..249a167d1 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -340,14 +340,14 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_distance\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", - " climb_start_range={'units': 'ft'},\n", + " climb_start_distance={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", " takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'},\n", @@ -366,7 +366,7 @@ "prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", "prob.model.connect('traj.climb.states:distance',\n", - " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", + " 'takeoff_constraints.climb_start_distance', src_indices=[0])\n", "prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", "prob.model.connect('traj.climb.states:altitude',\n", @@ -695,14 +695,14 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_distance\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", - " climb_start_range={'units': 'ft'},\n", + " climb_start_distance={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", " takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'},\n", @@ -977,7 +977,7 @@ " prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", " prob.model.connect('traj.climb.states:distance',\n", - " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", + " 'takeoff_constraints.climb_start_distance', src_indices=[0])\n", " prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", " prob.model.connect('traj.climb.states:altitude',\n", diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 1cbe7da34..711c18eec 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -448,14 +448,14 @@ " om.ExecComp(\n", " [\n", " \"takeoff_mass_con=takeoff_mass-climb_start_mass\",\n", - " \"takeoff_distance_con=takeoff_range-climb_start_range\",\n", + " \"takeoff_distance_con=takeoff_range-climb_start_distance\",\n", " \"takeoff_vel_con=takeoff_vel-climb_start_vel\",\n", " \"takeoff_alt_con=takeoff_alt-climb_start_alt\"\n", " ],\n", " takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'},\n", " climb_start_mass={'units': 'lbm'},\n", " takeoff_distance_con={'units': 'ft'}, takeoff_range={'units': 'ft'},\n", - " climb_start_range={'units': 'ft'},\n", + " climb_start_distance={'units': 'ft'},\n", " takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'},\n", " climb_start_vel={'units': 'm/s'},\n", " takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'},\n", @@ -474,7 +474,7 @@ "prob.model.connect('traj.climb.states:mass',\n", " 'takeoff_constraints.climb_start_mass', src_indices=[0])\n", "prob.model.connect('traj.climb.states:distance',\n", - " 'takeoff_constraints.climb_start_range', src_indices=[0])\n", + " 'takeoff_constraints.climb_start_distance', src_indices=[0])\n", "prob.model.connect('traj.climb.states:velocity',\n", " 'takeoff_constraints.climb_start_vel', src_indices=[0])\n", "prob.model.connect('traj.climb.states:altitude',\n", diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py index 4ae6d3e1d..8698766b9 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_N3CC.py @@ -268,14 +268,14 @@ def run_trajectory(driver: Driver, sim=True): om.ExecComp( [ "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", + "takeoff_range_con=takeoff_range-climb_start_distance", "takeoff_vel_con=takeoff_vel-climb_start_vel", "takeoff_alt_con=takeoff_alt-climb_start_alt" ], takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, climb_start_mass={'units': 'lbm'}, takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, + climb_start_distance={'units': 'ft'}, takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, climb_start_vel={'units': 'm/s'}, takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, @@ -294,7 +294,7 @@ def run_trajectory(driver: Driver, sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) prob.model.connect('traj.climb.states:distance', - 'takeoff_constraints.climb_start_range', src_indices=[0]) + 'takeoff_constraints.climb_start_distance', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) prob.model.connect('traj.climb.states:altitude', diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py index a5b6cca94..376c50158 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_1.py @@ -274,14 +274,14 @@ def run_trajectory(sim=True): om.ExecComp( [ "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", + "takeoff_range_con=takeoff_range-climb_start_distance", "takeoff_vel_con=takeoff_vel-climb_start_vel", "takeoff_alt_con=takeoff_alt-climb_start_alt" ], takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, climb_start_mass={'units': 'lbm'}, takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, + climb_start_distance={'units': 'ft'}, takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, climb_start_vel={'units': 'm/s'}, takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, @@ -300,7 +300,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) prob.model.connect('traj.climb.states:distance', - 'takeoff_constraints.climb_start_range', src_indices=[0]) + 'takeoff_constraints.climb_start_distance', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) prob.model.connect('traj.climb.states:altitude', diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py index 76566f394..84ed5bbc7 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_full_mission_large_single_aisle_2.py @@ -268,14 +268,14 @@ def run_trajectory(sim=True): om.ExecComp( [ "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", + "takeoff_range_con=takeoff_range-climb_start_distance", "takeoff_vel_con=takeoff_vel-climb_start_vel", "takeoff_alt_con=takeoff_alt-climb_start_alt" ], takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, climb_start_mass={'units': 'lbm'}, takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, + climb_start_distance={'units': 'ft'}, takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, climb_start_vel={'units': 'm/s'}, takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, @@ -294,7 +294,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) prob.model.connect('traj.climb.states:distance', - 'takeoff_constraints.climb_start_range', src_indices=[0]) + 'takeoff_constraints.climb_start_distance', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) prob.model.connect('traj.climb.states:altitude', diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 4d05ca9f4..4e248b306 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -307,14 +307,14 @@ def run_trajectory(sim=True): om.ExecComp( [ "takeoff_mass_con=takeoff_mass-climb_start_mass", - "takeoff_range_con=takeoff_range-climb_start_range", + "takeoff_range_con=takeoff_range-climb_start_distance", "takeoff_vel_con=takeoff_vel-climb_start_vel", "takeoff_alt_con=takeoff_alt-climb_start_alt" ], takeoff_mass_con={'units': 'lbm'}, takeoff_mass={'units': 'lbm'}, climb_start_mass={'units': 'lbm'}, takeoff_range_con={'units': 'ft'}, takeoff_range={'units': 'ft'}, - climb_start_range={'units': 'ft'}, + climb_start_distance={'units': 'ft'}, takeoff_vel_con={'units': 'm/s'}, takeoff_vel={'units': 'm/s'}, climb_start_vel={'units': 'm/s'}, takeoff_alt_con={'units': 'ft'}, takeoff_alt={'units': 'ft'}, @@ -333,7 +333,7 @@ def run_trajectory(sim=True): prob.model.connect('traj.climb.states:mass', 'takeoff_constraints.climb_start_mass', src_indices=[0]) prob.model.connect('traj.climb.states:distance', - 'takeoff_constraints.climb_start_range', src_indices=[0]) + 'takeoff_constraints.climb_start_distance', src_indices=[0]) prob.model.connect('traj.climb.states:velocity', 'takeoff_constraints.climb_start_vel', src_indices=[0]) prob.model.connect('traj.climb.states:altitude', From 579c5135114a12f1b9bc82320c76fd4c0336e8b0 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 12:02:10 -0500 Subject: [PATCH 068/111] changed max_range to distance_max --- ...S_based_detailed_takeoff_and_landing.ipynb | 12 +- .../phases/detailed_landing_phases.py | 52 ++++----- .../phases/detailed_takeoff_phases.py | 108 +++++++++--------- aviary/models/N3CC/N3CC_data.py | 46 ++++---- .../test_FLOPS_balanced_field_length.py | 4 +- .../test_FLOPS_detailed_landing.py | 4 +- .../test_FLOPS_detailed_takeoff.py | 4 +- 7 files changed, 115 insertions(+), 115 deletions(-) diff --git a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb index e13abbf88..97de4a087 100644 --- a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb @@ -138,7 +138,7 @@ "\n", "takeoff_brake_release_user_options.set_val('max_duration', val=60.0, units='s')\n", "takeoff_brake_release_user_options.set_val('duration_ref', val=60.0, units='s')\n", - "takeoff_brake_release_user_options.set_val('max_range', val=7500.0, units='ft')\n", + "takeoff_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft')\n", "takeoff_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn')\n", "\n", "takeoff_brake_release_initial_guesses = av.AviaryValues()\n", @@ -295,11 +295,11 @@ "takeoff_trajectory_builder.build_trajectory(\n", " aviary_options=aviary_options, model=takeoff.model, traj=traj)\n", "\n", - "max_range, units = takeoff_liftoff_user_options.get_item('max_range')\n", + "distance_max, units = takeoff_liftoff_user_options.get_item('distance_max')\n", "liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff')\n", "\n", "liftoff.add_objective(\n", - " Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units)\n", + " Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units)\n", "\n", "# Insert a constraint for a fake decision speed, until abort is added.\n", "takeoff.model.add_constraint(\n", @@ -431,7 +431,7 @@ "landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50., units='s')\n", "landing_approach_to_mic_p3_user_options.set_val('duration_ref', val=50., units='s')\n", "landing_approach_to_mic_p3_user_options.set_val('initial_ref', val=50.0, units='s')\n", - "landing_approach_to_mic_p3_user_options.set_val('max_range', val=10000., units='ft')\n", + "landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000., units='ft')\n", "landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140., units='kn')\n", "landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800., units='ft')\n", "\n", @@ -548,10 +548,10 @@ "landing_trajectory_builder.build_trajectory(\n", " aviary_options=aviary_options, model=landing.model, traj=traj)\n", "\n", - "max_range, units = landing_fullstop_user_options.get_item('max_range')\n", + "distance_max, units = landing_fullstop_user_options.get_item('distance_max')\n", "fullstop = landing_trajectory_builder.get_phase('landing_fullstop')\n", "\n", - "fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units)\n", + "fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units)\n", "\n", "landing.model.add_subsystem(\n", " 'input_sink',\n", diff --git a/aviary/mission/flops_based/phases/detailed_landing_phases.py b/aviary/mission/flops_based/phases/detailed_landing_phases.py index ee46b4a1e..c569ef794 100644 --- a/aviary/mission/flops_based/phases/detailed_landing_phases.py +++ b/aviary/mission/flops_based/phases/detailed_landing_phases.py @@ -61,7 +61,7 @@ class LandingApproachToMicP3(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - lower_angle_of_attack (-10.0, 'deg') @@ -145,12 +145,12 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, - upper=0, ref=max_range, - defect_ref=max_range, units=units, + upper=0, ref=distance_max, + defect_ref=distance_max, units=units, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -239,7 +239,7 @@ def _extra_ode_init_kwargs(self): LandingApproachToMicP3._add_meta_data('initial_ref', val=10.0, units='s') -LandingApproachToMicP3._add_meta_data('max_range', val=1000., units='ft') +LandingApproachToMicP3._add_meta_data('distance_max', val=1000., units='ft') LandingApproachToMicP3._add_meta_data('max_velocity', val=100., units='ft/s') @@ -284,7 +284,7 @@ class LandingMicP3ToObstacle(LandingApproachToMicP3): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - lower_angle_of_attack (-10.0, 'deg') @@ -384,7 +384,7 @@ class LandingObstacleToFlare(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -461,11 +461,11 @@ def build_phase(self, aviary_options: AviaryValues = None): fix_initial=True, duration_bounds=(1, max_duration), units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=max_range, - defect_ref=max_range, units=units, + Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -545,7 +545,7 @@ def _extra_ode_init_kwargs(self): LandingObstacleToFlare._add_meta_data('max_duration', val=100., units='s') -LandingObstacleToFlare._add_meta_data('max_range', val=1000., units='ft') +LandingObstacleToFlare._add_meta_data('distance_max', val=1000., units='ft') LandingObstacleToFlare._add_meta_data('max_velocity', val=100., units='ft/s') @@ -581,7 +581,7 @@ class LandingFlareToTouchdown(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - lower_angle_of_attack (-10.0, 'deg') @@ -664,11 +664,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -764,7 +764,7 @@ def _extra_ode_init_kwargs(self): LandingFlareToTouchdown._add_meta_data('initial_ref', val=10.0, units='s') -LandingFlareToTouchdown._add_meta_data('max_range', val=1000., units='ft') +LandingFlareToTouchdown._add_meta_data('distance_max', val=1000., units='ft') LandingFlareToTouchdown._add_meta_data('max_velocity', val=100., units='ft/s') @@ -805,7 +805,7 @@ class LandingTouchdownToNoseDown(PhaseBuilderBase): - max_duration (5.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - max_angle_of_attack (10.0, 'deg') @@ -883,11 +883,11 @@ def build_phase(self, aviary_options=None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -952,7 +952,7 @@ def _extra_ode_init_kwargs(self): LandingTouchdownToNoseDown._add_meta_data('initial_ref', val=10.0, units='s') -LandingTouchdownToNoseDown._add_meta_data('max_range', val=1000.0, units='ft') +LandingTouchdownToNoseDown._add_meta_data('distance_max', val=1000.0, units='ft') LandingTouchdownToNoseDown._add_meta_data('max_velocity', val=100.0, units='ft/s') @@ -981,7 +981,7 @@ class LandingNoseDownToStop(PhaseBuilderBase): supported options: - max_duration - duration_ref - - max_range + - distance_max - max_velocity initial_guesses : AviaryValues () @@ -1058,12 +1058,12 @@ def build_phase(self, aviary_options=None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, - lower=0, ref=max_range, - defect_ref=max_range, units=units, + lower=0, ref=distance_max, + defect_ref=distance_max, units=units, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -1124,7 +1124,7 @@ def _extra_ode_init_kwargs(self): LandingNoseDownToStop._add_meta_data('initial_ref', val=10.0, units='s') -LandingNoseDownToStop._add_meta_data('max_range', val=1000.0, units='ft') +LandingNoseDownToStop._add_meta_data('distance_max', val=1000.0, units='ft') LandingNoseDownToStop._add_meta_data('max_velocity', val=100.0, units='ft/s') diff --git a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py index e637c2a46..068157ae1 100644 --- a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py +++ b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py @@ -104,7 +104,7 @@ class TakeoffBrakeReleaseToDecisionSpeed(PhaseBuilderBase): supported options: - max_duration (1000.0, 's') - duration_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') initial_guesses : AviaryValues () @@ -179,11 +179,11 @@ def build_phase(self, aviary_options=None): fix_initial=True, duration_bounds=(1, max_duration), duration_ref=duration_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -241,7 +241,7 @@ def _extra_ode_init_kwargs(self): TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('duration_ref', val=10.0, units='s') -TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('max_range', val=1000.0, units='ft') +TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('distance_max', val=1000.0, units='ft') TakeoffBrakeReleaseToDecisionSpeed._add_meta_data( 'max_velocity', val=100.0, units='ft/s') @@ -271,7 +271,7 @@ class TakeoffDecisionSpeedToRotate(PhaseBuilderBase): - max_duration (1000.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') initial_guesses : AviaryValues () @@ -349,11 +349,11 @@ def build_phase(self, aviary_options=None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -419,7 +419,7 @@ def _extra_ode_init_kwargs(self): TakeoffDecisionSpeedToRotate._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffDecisionSpeedToRotate._add_meta_data('max_range', val=1000.0, units='ft') +TakeoffDecisionSpeedToRotate._add_meta_data('distance_max', val=1000.0, units='ft') TakeoffDecisionSpeedToRotate._add_meta_data('max_velocity', val=100.0, units='ft/s') @@ -448,7 +448,7 @@ class TakeoffDecisionSpeedBrakeDelay(TakeoffDecisionSpeedToRotate): - max_duration (1000.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') initial_guesses : AviaryValues () @@ -523,7 +523,7 @@ def build_phase(self, aviary_options=None): TakeoffDecisionSpeedBrakeDelay._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffDecisionSpeedBrakeDelay._add_meta_data('max_range', val=1000.0, units='ft') +TakeoffDecisionSpeedBrakeDelay._add_meta_data('distance_max', val=1000.0, units='ft') TakeoffDecisionSpeedBrakeDelay._add_meta_data('max_velocity', val=100.0, units='ft/s') @@ -551,7 +551,7 @@ class TakeoffRotateToLiftoff(PhaseBuilderBase): - max_duration (5.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - max_angle_of_attack (10.0, 'deg') @@ -630,11 +630,11 @@ def build_phase(self, aviary_options=None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -702,7 +702,7 @@ def _extra_ode_init_kwargs(self): TakeoffRotateToLiftoff._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffRotateToLiftoff._add_meta_data('max_range', val=1000.0, units='ft') +TakeoffRotateToLiftoff._add_meta_data('distance_max', val=1000.0, units='ft') TakeoffRotateToLiftoff._add_meta_data('max_velocity', val=100.0, units='ft/s') @@ -733,7 +733,7 @@ class TakeoffLiftoffToObstacle(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -818,11 +818,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -924,7 +924,7 @@ def _extra_ode_init_kwargs(self): TakeoffLiftoffToObstacle._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffLiftoffToObstacle._add_meta_data('max_range', val=1000., units='ft') +TakeoffLiftoffToObstacle._add_meta_data('distance_max', val=1000., units='ft') TakeoffLiftoffToObstacle._add_meta_data('max_velocity', val=100., units='ft/s') @@ -968,7 +968,7 @@ class TakeoffObstacleToMicP2(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -1054,11 +1054,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -1154,7 +1154,7 @@ def _extra_ode_init_kwargs(self): TakeoffObstacleToMicP2._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffObstacleToMicP2._add_meta_data('max_range', val=1000., units='ft') +TakeoffObstacleToMicP2._add_meta_data('distance_max', val=1000., units='ft') TakeoffObstacleToMicP2._add_meta_data('max_velocity', val=100., units='ft/s') @@ -1200,7 +1200,7 @@ class TakeoffMicP2ToEngineCutback(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -1286,11 +1286,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -1347,8 +1347,8 @@ def build_phase(self, aviary_options: AviaryValues = None): ) # start engine cutback phase at this range, where this phase ends - # TODO: what is the difference between max_range and final_range? - # - should final_range replace max_range? + # TODO: what is the difference between distance_max and final_range? + # - should final_range replace distance_max? # - is there any reason to support both in this phase? final_range, units = user_options.get_item('final_range') @@ -1386,7 +1386,7 @@ def _extra_ode_init_kwargs(self): TakeoffMicP2ToEngineCutback._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffMicP2ToEngineCutback._add_meta_data('max_range', val=1000., units='ft') +TakeoffMicP2ToEngineCutback._add_meta_data('distance_max', val=1000., units='ft') TakeoffMicP2ToEngineCutback._add_meta_data('max_velocity', val=100., units='ft/s') @@ -1431,7 +1431,7 @@ class TakeoffEngineCutback(PhaseBuilderBase): supported options: - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -1514,11 +1514,11 @@ def build_phase(self, aviary_options: AviaryValues = None): initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -1600,7 +1600,7 @@ def _extra_ode_init_kwargs(self): TakeoffEngineCutback._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffEngineCutback._add_meta_data('max_range', val=1000., units='ft') +TakeoffEngineCutback._add_meta_data('distance_max', val=1000., units='ft') TakeoffEngineCutback._add_meta_data('max_velocity', val=100., units='ft/s') @@ -1644,7 +1644,7 @@ class TakeoffEngineCutbackToMicP1(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -1730,11 +1730,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -1826,7 +1826,7 @@ def _extra_ode_init_kwargs(self): TakeoffEngineCutbackToMicP1._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffEngineCutbackToMicP1._add_meta_data('max_range', val=1000., units='ft') +TakeoffEngineCutbackToMicP1._add_meta_data('distance_max', val=1000., units='ft') TakeoffEngineCutbackToMicP1._add_meta_data('max_velocity', val=100., units='ft/s') @@ -1873,7 +1873,7 @@ class TakeoffMicP1ToClimb(PhaseBuilderBase): - max_duration (100.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') - flight_path_angle_ref (5., 'deg') @@ -1959,11 +1959,11 @@ def build_phase(self, aviary_options: AviaryValues = None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) altitude_ref, units = user_options.get_item('altitude_ref') @@ -2055,7 +2055,7 @@ def _extra_ode_init_kwargs(self): TakeoffMicP1ToClimb._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffMicP1ToClimb._add_meta_data('max_range', val=1000., units='ft') +TakeoffMicP1ToClimb._add_meta_data('distance_max', val=1000., units='ft') TakeoffMicP1ToClimb._add_meta_data('max_velocity', val=100., units='ft/s') @@ -2101,7 +2101,7 @@ class TakeoffBrakeToAbort(PhaseBuilderBase): - max_duration (1000.0, 's') - duration_ref (1.0, 's') - initial_ref (10.0, 's') - - max_range (1000.0, 'ft') + - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') initial_guesses : AviaryValues () @@ -2179,11 +2179,11 @@ def build_phase(self, aviary_options=None): duration_ref=duration_ref, initial_ref=initial_ref, units=units) - max_range, units = user_options.get_item('max_range') + distance_max, units = user_options.get_item('distance_max') phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=max_range, - defect_ref=max_range, units=units, upper=max_range, + Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, + defect_ref=distance_max, units=units, upper=distance_max, rate_source=Dynamic.Mission.DISTANCE_RATE) max_velocity, units = user_options.get_item('max_velocity') @@ -2234,7 +2234,7 @@ def _extra_ode_init_kwargs(self): TakeoffBrakeToAbort._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffBrakeToAbort._add_meta_data('max_range', val=1000.0, units='ft') +TakeoffBrakeToAbort._add_meta_data('distance_max', val=1000.0, units='ft') TakeoffBrakeToAbort._add_meta_data('max_velocity', val=100.0, units='ft/s') diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index c8cce58c9..764d4d43f 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -480,7 +480,7 @@ takeoff_brake_release_user_options.set_val('max_duration', val=60.0, units='s') takeoff_brake_release_user_options.set_val('duration_ref', val=60.0, units='s') -takeoff_brake_release_user_options.set_val('max_range', val=7500.0, units='ft') +takeoff_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_brake_release_initial_guesses = AviaryValues() @@ -513,7 +513,7 @@ takeoff_decision_speed_user_options.set_val('max_duration', val=60.0, units='s') takeoff_decision_speed_user_options.set_val('duration_ref', val=60.0, units='s') takeoff_decision_speed_user_options.set_val('initial_ref', val=35.0, units='s') -takeoff_decision_speed_user_options.set_val('max_range', val=7500.0, units='ft') +takeoff_decision_speed_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_decision_speed_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_decision_speed_initial_guesses = AviaryValues() @@ -541,7 +541,7 @@ takeoff_rotate_user_options.set_val('max_duration', val=60.0, units='s') takeoff_rotate_user_options.set_val('duration_ref', val=60.0, units='s') takeoff_rotate_user_options.set_val('initial_ref', val=38.0, units='s') -takeoff_rotate_user_options.set_val('max_range', val=7500.0, units='ft') +takeoff_rotate_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_rotate_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_rotate_user_options.set_val('max_angle_of_attack', val=10.0, units='deg') @@ -570,7 +570,7 @@ takeoff_liftoff_user_options.set_val('max_duration', val=12., units='s') takeoff_liftoff_user_options.set_val('duration_ref', val=12., units='s') takeoff_liftoff_user_options.set_val('initial_ref', val=39.0, units='s') -takeoff_liftoff_user_options.set_val('max_range', val=7500., units='ft') +takeoff_liftoff_user_options.set_val('distance_max', val=7500., units='ft') takeoff_liftoff_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_liftoff_user_options.set_val('altitude_ref', val=35., units='ft') takeoff_liftoff_user_options.set_val('flight_path_angle_ref', val=10., units='deg') @@ -606,7 +606,7 @@ takeoff_mic_p2_user_options.set_val('max_duration', val=25., units='s') takeoff_mic_p2_user_options.set_val('duration_ref', val=25., units='s') takeoff_mic_p2_user_options.set_val('initial_ref', val=50.0, units='s') -takeoff_mic_p2_user_options.set_val('max_range', val=12000., units='ft') +takeoff_mic_p2_user_options.set_val('distance_max', val=12000., units='ft') takeoff_mic_p2_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_mic_p2_user_options.set_val('altitude_ref', val=1500., units='ft') takeoff_mic_p2_user_options.set_val('mic_altitude', val=985., units='ft') @@ -651,7 +651,7 @@ takeoff_mic_p2_to_engine_cutback_user_options.set_val('initial_ref', val=65.0, units='s') takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'max_range', val=20000., units='ft') + 'distance_max', val=20000., units='ft') takeoff_mic_p2_to_engine_cutback_user_options.set_val( 'max_velocity', val=167.85, units='kn') @@ -717,7 +717,7 @@ cutback_duration = (1.0 - cutback_throttle) / cutback_rate takeoff_engine_cutback_user_options.set_val('initial_ref', val=95.0, units='s') -takeoff_engine_cutback_user_options.set_val('max_range', val=21000., units='ft') +takeoff_engine_cutback_user_options.set_val('distance_max', val=21000., units='ft') takeoff_engine_cutback_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_engine_cutback_user_options.set_val('altitude_ref', val=4000., units='ft') @@ -762,7 +762,7 @@ takeoff_engine_cutback_to_mic_p1_user_options.set_val('initial_ref', val=97.0, units='s') takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'max_range', val=22000., units='ft') + 'distance_max', val=22000., units='ft') takeoff_engine_cutback_to_mic_p1_user_options.set_val( 'max_velocity', val=167.85, units='kn') @@ -823,7 +823,7 @@ takeoff_mic_p1_to_climb_user_options.set_val('max_duration', val=40., units='s') takeoff_mic_p1_to_climb_user_options.set_val('duration_ref', val=40., units='s') takeoff_mic_p1_to_climb_user_options.set_val('initial_ref', val=100.0, units='s') -takeoff_mic_p1_to_climb_user_options.set_val('max_range', val=30000., units='ft') +takeoff_mic_p1_to_climb_user_options.set_val('distance_max', val=30000., units='ft') takeoff_mic_p1_to_climb_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_mic_p1_to_climb_user_options.set_val('altitude_ref', val=4000., units='ft') @@ -939,7 +939,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_brake_release_user_options.set_val('max_duration', val=60.0, units='s') balanced_brake_release_user_options.set_val('duration_ref', val=60.0, units='s') -balanced_brake_release_user_options.set_val('max_range', val=7500.0, units='ft') +balanced_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_brake_release_initial_guesses = AviaryValues() @@ -966,7 +966,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_decision_speed_user_options.set_val('max_duration', val=60.0, units='s') balanced_decision_speed_user_options.set_val('duration_ref', val=5.0, units='s') balanced_decision_speed_user_options.set_val('initial_ref', val=35.0, units='s') -balanced_decision_speed_user_options.set_val('max_range', val=7500.0, units='ft') +balanced_decision_speed_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_decision_speed_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_decision_speed_initial_guesses = AviaryValues() @@ -996,7 +996,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_rotate_user_options.set_val('max_duration', val=20.0, units='s') balanced_rotate_user_options.set_val('duration_ref', val=5.0, units='s') balanced_rotate_user_options.set_val('initial_ref', val=35.0, units='s') -balanced_rotate_user_options.set_val('max_range', val=7500.0, units='ft') +balanced_rotate_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_rotate_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_rotate_user_options.set_val('max_angle_of_attack', val=8.117, units='deg') @@ -1024,7 +1024,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_liftoff_user_options.set_val('max_duration', val=20., units='s') balanced_liftoff_user_options.set_val('duration_ref', val=20., units='s') balanced_liftoff_user_options.set_val('initial_ref', val=40.0, units='s') -balanced_liftoff_user_options.set_val('max_range', val=7500., units='ft') +balanced_liftoff_user_options.set_val('distance_max', val=7500., units='ft') balanced_liftoff_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_liftoff_user_options.set_val('altitude_ref', val=35., units='ft') balanced_liftoff_user_options.set_val('flight_path_angle_ref', val=5., units='deg') @@ -1058,7 +1058,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_delayed_brake_user_options.set_val('duration_ref', val=4.0, units='s') balanced_delayed_brake_user_options.set_val('initial_ref', val=35.0, units='s') -balanced_delayed_brake_user_options.set_val('max_range', val=7500.0, units='ft') +balanced_delayed_brake_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_delayed_brake_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_delayed_brake_initial_guesses = AviaryValues() @@ -1085,7 +1085,7 @@ def _split_aviary_values(aviary_values, slicing): balanced_abort_user_options.set_val('max_duration', val=60.0, units='s') balanced_abort_user_options.set_val('initial_ref', val=35.0, units='s') balanced_abort_user_options.set_val('duration_ref', val=60.0, units='s') -balanced_abort_user_options.set_val('max_range', val=7500.0, units='ft') +balanced_abort_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_abort_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_abort_initial_guesses = AviaryValues() @@ -1104,10 +1104,10 @@ def _split_aviary_values(aviary_values, slicing): user_options=balanced_abort_user_options, initial_guesses=balanced_abort_initial_guesses) -max_range = balanced_liftoff_user_options.get_val('max_range', 'ft') +distance_max = balanced_liftoff_user_options.get_val('distance_max', 'ft') balanced_trajectory_builder.set_brake_to_abort( - balanced_abort_builder, balanced_field_ref=max_range) + balanced_abort_builder, balanced_field_ref=distance_max) # endregion balanced field length # region - detailed landing @@ -1325,7 +1325,7 @@ def _split_aviary_values(aviary_values, slicing): landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50., units='s') landing_approach_to_mic_p3_user_options.set_val('duration_ref', val=50., units='s') landing_approach_to_mic_p3_user_options.set_val('initial_ref', val=50.0, units='s') -landing_approach_to_mic_p3_user_options.set_val('max_range', val=10000., units='ft') +landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000., units='ft') landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140., units='kn') landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800., units='ft') @@ -1376,7 +1376,7 @@ def _split_aviary_values(aviary_values, slicing): landing_mic_p3_to_obstacle_user_options.set_val('max_duration', val=50., units='s') landing_mic_p3_to_obstacle_user_options.set_val('duration_ref', val=50., units='s') landing_mic_p3_to_obstacle_user_options.set_val('initial_ref', val=50.0, units='s') -landing_mic_p3_to_obstacle_user_options.set_val('max_range', val=6000., units='ft') +landing_mic_p3_to_obstacle_user_options.set_val('distance_max', val=6000., units='ft') landing_mic_p3_to_obstacle_user_options.set_val('max_velocity', val=140., units='kn') landing_mic_p3_to_obstacle_user_options.set_val('altitude_ref', val=400., units='ft') @@ -1425,7 +1425,7 @@ def _split_aviary_values(aviary_values, slicing): landing_obstacle_user_options = AviaryValues() landing_obstacle_user_options.set_val('max_duration', val=5., units='s') -landing_obstacle_user_options.set_val('max_range', val=800., units='ft') +landing_obstacle_user_options.set_val('distance_max', val=800., units='ft') landing_obstacle_user_options.set_val('max_velocity', val=140., units='kn') landing_obstacle_user_options.set_val('altitude_ref', val=50., units='ft') @@ -1463,7 +1463,7 @@ def _split_aviary_values(aviary_values, slicing): landing_flare_user_options.set_val('max_duration', val=7., units='s') landing_flare_user_options.set_val('duration_ref', val=7., units='s') landing_flare_user_options.set_val('initial_ref', val=4., units='s') -landing_flare_user_options.set_val('max_range', val=1000., units='ft') +landing_flare_user_options.set_val('distance_max', val=1000., units='ft') landing_flare_user_options.set_val('max_velocity', val=140., units='kn') landing_flare_user_options.set_val('altitude_ref', val=15., units='ft') @@ -1503,7 +1503,7 @@ def _split_aviary_values(aviary_values, slicing): landing_touchdown_user_options.set_val('max_duration', val=10., units='s') landing_touchdown_user_options.set_val('duration_ref', val=10., units='s') landing_touchdown_user_options.set_val('initial_ref', val=6., units='s') -landing_touchdown_user_options.set_val('max_range', val=3000., units='ft') +landing_touchdown_user_options.set_val('distance_max', val=3000., units='ft') landing_touchdown_user_options.set_val('max_velocity', val=140., units='kn') landing_touchdown_user_options.set_val('max_angle_of_attack', val=8., units='deg') @@ -1536,7 +1536,7 @@ def _split_aviary_values(aviary_values, slicing): landing_fullstop_user_options.set_val('max_duration', val=30., units='s') landing_fullstop_user_options.set_val('duration_ref', val=30., units='s') landing_fullstop_user_options.set_val('initial_ref', val=14., units='s') -landing_fullstop_user_options.set_val('max_range', val=4400., units='ft') +landing_fullstop_user_options.set_val('distance_max', val=4400., units='ft') landing_fullstop_user_options.set_val('max_velocity', val=140., units='kn') landing_fullstop_initial_guesses = AviaryValues() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index a3908a1da..f30f6d812 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -89,11 +89,11 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff_trajectory_builder.build_trajectory( aviary_options=aviary_options, model=takeoff.model, traj=traj) - max_range, units = takeoff_liftoff_user_options.get_item('max_range') + distance_max, units = takeoff_liftoff_user_options.get_item('distance_max') liftoff = takeoff_trajectory_builder.get_phase('balanced_liftoff') liftoff.add_objective( - Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units) + Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) takeoff.model.add_subsystem( 'input_sink', diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 3da1a98ba..bc4b16846 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -84,11 +84,11 @@ def _do_run(self, driver: Driver, optimizer, *args): landing_trajectory_builder.build_trajectory( aviary_options=aviary_options, model=landing.model, traj=traj) - max_range, units = landing_fullstop_user_options.get_item('max_range') + distance_max, units = landing_fullstop_user_options.get_item('distance_max') fullstop = landing_trajectory_builder.get_phase('landing_fullstop') fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', - ref=max_range, units=units) + ref=distance_max, units=units) landing.model.add_subsystem( 'input_sink', diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index c16facd15..e0752de37 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -90,11 +90,11 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff_trajectory_builder.build_trajectory( aviary_options=aviary_options, model=takeoff.model, traj=traj) - max_range, units = takeoff_liftoff_user_options.get_item('max_range') + distance_max, units = takeoff_liftoff_user_options.get_item('distance_max') liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff') liftoff.add_objective( - Dynamic.Mission.DISTANCE, loc='final', ref=max_range, units=units) + Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) # Insert a constraint for a fake decision speed, until abort is added. takeoff.model.add_constraint( From 875ae0cd7b7451b4e97d432aca4d5fdc830e0a6b Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 12:28:27 -0500 Subject: [PATCH 069/111] accel_ode upd and tests passing --- aviary/mission/gasp_based/ode/accel_ode.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aviary/mission/gasp_based/ode/accel_ode.py b/aviary/mission/gasp_based/ode/accel_ode.py index f47fc29e2..6a3418309 100644 --- a/aviary/mission/gasp_based/ode/accel_ode.py +++ b/aviary/mission/gasp_based/ode/accel_ode.py @@ -95,7 +95,6 @@ def setup(self): + sgm_outputs, ) - # the last two subsystems will also be used for constraints self.add_subsystem( name='SPECIFIC_ENERGY_RATE_EXCESS', subsys=SpecificEnergyRate(num_nodes=nn), @@ -123,3 +122,5 @@ def setup(self): np.ones(nn), units="lbm") self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=500 * np.ones(nn), units="ft") + self.set_input_defaults("TAS", val=200*np.ones(nn), + units="m/s") # val here is nominal From 8d3caa07d3e45a22753cb8477fdc54aac540bd7a Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 12:42:08 -0500 Subject: [PATCH 070/111] ascent updated with altitude_rate_max output --- aviary/mission/gasp_based/ode/ascent_ode.py | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/aviary/mission/gasp_based/ode/ascent_ode.py b/aviary/mission/gasp_based/ode/ascent_ode.py index 51223c42d..a98dee62b 100644 --- a/aviary/mission/gasp_based/ode/ascent_ode.py +++ b/aviary/mission/gasp_based/ode/ascent_ode.py @@ -13,6 +13,8 @@ from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.variable_info.enums import AlphaModes from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate class AscentODE(BaseODE): @@ -116,6 +118,28 @@ def setup(self): ], ) + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + ParamPort.set_default_vals(self) self.set_input_defaults("t_init_flaps", val=47.5) self.set_input_defaults("t_init_gear", val=37.3) @@ -129,3 +153,5 @@ def setup(self): self.set_input_defaults('aero_ramps.gear_factor:final_val', val=0.) self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.) self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.) + self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones( + nn), units='kg') # val here is nominal From a50f06e8db4519b7ba7b6e7176e755b4270f11a4 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 12:50:26 -0500 Subject: [PATCH 071/111] ALTITUDE_RATE_MAX calc added --- .../gasp_based/ode/breguet_cruise_ode.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py index 8097210ac..306b41f44 100644 --- a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py @@ -10,6 +10,8 @@ from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Dynamic +from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate class BreguetCruiseODESolution(BaseODE): @@ -135,6 +137,28 @@ def setup(self): ("cruise_time", "time")], ) + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + ParamPort.set_default_vals(self) self.set_input_defaults( Dynamic.Mission.ALTITUDE, From 2f1d14a431ca3a7eff82e4f1c03ccfe230ae0ea7 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 18 Jan 2024 11:59:19 -0600 Subject: [PATCH 072/111] fix for run all examples test --- aviary/examples/test/test_all_examples.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/aviary/examples/test/test_all_examples.py b/aviary/examples/test/test_all_examples.py index 8393a27c7..efab5eed4 100644 --- a/aviary/examples/test/test_all_examples.py +++ b/aviary/examples/test/test_all_examples.py @@ -85,12 +85,13 @@ def run_script(self, script_path): Exception Any exception other than ImportError or TimeoutExpired that occurs while running the script. """ - try: - subprocess.check_call(['python', script_path], timeout=10) - except subprocess.TimeoutExpired: - pass # Test passes if it runs longer than 10 seconds - except subprocess.CalledProcessError as e: - if 'ImportError' in str(e): + proc = subprocess.Popen(['python', script_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc.wait() + (stdout, stderr) = proc.communicate() + + if proc.returncode != 0: + if 'ImportError' in str(stderr): self.skipTest(f"Skipped {script_path.name} due to ImportError") else: raise From 4b63fd651898668ee083f039fd9ad7a084a4a6cd Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 13:01:09 -0500 Subject: [PATCH 073/111] ALTITUDE_RATE_MAX added to descent_ode --- aviary/mission/gasp_based/ode/descent_ode.py | 34 ++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index 3257fbb14..ed10777d6 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -19,6 +19,8 @@ from aviary.variable_info.variables import Dynamic from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase +from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate class DescentODE(BaseODE): @@ -232,6 +234,29 @@ def setup(self): add_default_solver=False, num_nodes=nn) + # the last two subsystems will also be used for constraints + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + if analysis_scheme is AnalysisScheme.COLLOCATION: fc_loc = ['fc'] if input_speed_type is SpeedType.MACH: @@ -239,8 +264,13 @@ def setup(self): fc_loc = ['mach_balance_group'] # TODO this assumes the name of propulsion subsystem, need to pull from # the subsystem itself - self.set_order(['params', 'USatm',]+fc_loc+prop_groups+['lift_balance_group', - 'constraints']) + self.set_order(['params', + 'USatm',] + + fc_loc+prop_groups + + ['lift_balance_group', + 'constraints', + 'SPECIFIC_ENERGY_RATE_EXCESS', + 'ALTITUDE_RATE_MAX']) ParamPort.set_default_vals(self) self.set_input_defaults(Dynamic.Mission.ALTITUDE, From b7e9c6d14ba88d1a0129ae996764cdb6037df143 Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 13:36:44 -0500 Subject: [PATCH 074/111] moved altitude_rate.py and specific_energy_rate.py to non-flops-specific folder, upd flightpath.ode with ALTITUDE_RATE_MAX --- aviary/mission/flops_based/ode/mission_EOM.py | 4 ++-- .../flops_based/ode/simple_mission_EOM.py | 4 ++-- .../ode/test/test_altitude_rate.py | 2 +- .../ode/test/test_specific_energy_rate.py | 2 +- aviary/mission/gasp_based/ode/accel_ode.py | 4 ++-- aviary/mission/gasp_based/ode/ascent_ode.py | 4 ++-- .../gasp_based/ode/breguet_cruise_ode.py | 4 ++-- aviary/mission/gasp_based/ode/climb_ode.py | 4 ++-- aviary/mission/gasp_based/ode/descent_ode.py | 4 ++-- .../mission/gasp_based/ode/flight_path_ode.py | 24 +++++++++++++++++++ .../{flops_based => }/ode/altitude_rate.py | 0 .../ode/specific_energy_rate.py | 0 12 files changed, 40 insertions(+), 16 deletions(-) rename aviary/mission/{flops_based => }/ode/altitude_rate.py (100%) rename aviary/mission/{flops_based => }/ode/specific_energy_rate.py (100%) diff --git a/aviary/mission/flops_based/ode/mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py index 946a85468..8762aa428 100644 --- a/aviary/mission/flops_based/ode/mission_EOM.py +++ b/aviary/mission/flops_based/ode/mission_EOM.py @@ -1,8 +1,8 @@ import openmdao.api as om -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.altitude_rate import AltitudeRate from aviary.mission.flops_based.ode.range_rate import RangeRate -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate from aviary.variable_info.variables import Dynamic diff --git a/aviary/mission/flops_based/ode/simple_mission_EOM.py b/aviary/mission/flops_based/ode/simple_mission_EOM.py index 8e3e25e1f..eaccaa98d 100644 --- a/aviary/mission/flops_based/ode/simple_mission_EOM.py +++ b/aviary/mission/flops_based/ode/simple_mission_EOM.py @@ -1,9 +1,9 @@ import openmdao.api as om from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.altitude_rate import AltitudeRate from aviary.mission.flops_based.ode.range_rate import RangeRate -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate from aviary.mission.flops_based.ode.required_thrust import RequiredThrust diff --git a/aviary/mission/flops_based/ode/test/test_altitude_rate.py b/aviary/mission/flops_based/ode/test/test_altitude_rate.py index 5e6958b39..e6d33d548 100644 --- a/aviary/mission/flops_based/ode/test/test_altitude_rate.py +++ b/aviary/mission/flops_based/ode/test/test_altitude_rate.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.altitude_rate import AltitudeRate from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ data diff --git a/aviary/mission/flops_based/ode/test/test_specific_energy_rate.py b/aviary/mission/flops_based/ode/test/test_specific_energy_rate.py index 4c5afa7ec..19a2eca32 100644 --- a/aviary/mission/flops_based/ode/test/test_specific_energy_rate.py +++ b/aviary/mission/flops_based/ode/test/test_specific_energy_rate.py @@ -2,7 +2,7 @@ import openmdao.api as om -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ data diff --git a/aviary/mission/gasp_based/ode/accel_ode.py b/aviary/mission/gasp_based/ode/accel_ode.py index 6a3418309..c38df7971 100644 --- a/aviary/mission/gasp_based/ode/accel_ode.py +++ b/aviary/mission/gasp_based/ode/accel_ode.py @@ -9,8 +9,8 @@ from aviary.subsystems.mass.mass_to_weight import MassToWeight from aviary.variable_info.enums import AnalysisScheme, SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class AccelODE(BaseODE): diff --git a/aviary/mission/gasp_based/ode/ascent_ode.py b/aviary/mission/gasp_based/ode/ascent_ode.py index a98dee62b..1176e62d5 100644 --- a/aviary/mission/gasp_based/ode/ascent_ode.py +++ b/aviary/mission/gasp_based/ode/ascent_ode.py @@ -13,8 +13,8 @@ from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.variable_info.enums import AlphaModes from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class AscentODE(BaseODE): diff --git a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py index 306b41f44..fc5f594c9 100644 --- a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py @@ -10,8 +10,8 @@ from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class BreguetCruiseODESolution(BaseODE): diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index f112ea38c..c92d202e8 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -14,8 +14,8 @@ from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType from aviary.variable_info.variables import Dynamic -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class ClimbODE(BaseODE): diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index ed10777d6..9c11179a4 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -19,8 +19,8 @@ from aviary.variable_info.variables import Dynamic from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase -from aviary.mission.flops_based.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.flops_based.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class DescentODE(BaseODE): diff --git a/aviary/mission/gasp_based/ode/flight_path_ode.py b/aviary/mission/gasp_based/ode/flight_path_ode.py index 64542100b..112f280b3 100644 --- a/aviary/mission/gasp_based/ode/flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/flight_path_ode.py @@ -13,6 +13,8 @@ from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.ode.altitude_rate import AltitudeRate class FlightPathODE(BaseODE): @@ -209,6 +211,28 @@ def setup(self): self.promotes('eoms', outputs=[ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE]) + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[(Dynamic.Mission.VELOCITY, "TAS"), Dynamic.Mission.MASS, + (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + Dynamic.Mission.DRAG], + promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + (Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + (Dynamic.Mission.VELOCITY_RATE, "TAS_rate"), + (Dynamic.Mission.VELOCITY, "TAS")], + promotes_outputs=[ + (Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.ALTITUDE_RATE_MAX)]) + # Example of how to use a print_comp debug_comp = [] if False: diff --git a/aviary/mission/flops_based/ode/altitude_rate.py b/aviary/mission/ode/altitude_rate.py similarity index 100% rename from aviary/mission/flops_based/ode/altitude_rate.py rename to aviary/mission/ode/altitude_rate.py diff --git a/aviary/mission/flops_based/ode/specific_energy_rate.py b/aviary/mission/ode/specific_energy_rate.py similarity index 100% rename from aviary/mission/flops_based/ode/specific_energy_rate.py rename to aviary/mission/ode/specific_energy_rate.py From 8c3f87ef5e1ad9da9c387128b3970143eb874e23 Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 18 Jan 2024 13:42:10 -0500 Subject: [PATCH 075/111] Update version for v0.9.2 release --- .bumpversion.cfg | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- aviary/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a5f4cc007..cfe80c61d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.2-dev +current_version = 0.9.2 commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+))? diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b86321f76..b3b15494e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -21,7 +21,7 @@ body: attributes: label: Aviary Version description: What version of Aviary is being used. - placeholder: "0.9.2-dev" + placeholder: "0.9.2" validations: required: true - type: textarea diff --git a/aviary/__init__.py b/aviary/__init__.py index 99316d3f4..a2fecb457 100644 --- a/aviary/__init__.py +++ b/aviary/__init__.py @@ -1 +1 @@ -__version__ = "0.9.2-dev" +__version__ = "0.9.2" From 746a32c238fffac095ee0cc6b3300ab22c3148da Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 14:03:45 -0500 Subject: [PATCH 076/111] init file added to new folder --- aviary/mission/ode/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 aviary/mission/ode/__init__.py diff --git a/aviary/mission/ode/__init__.py b/aviary/mission/ode/__init__.py new file mode 100644 index 000000000..e69de29bb From b34e83bb3f4d58d4f5971ffd977c5095c5250dff Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 18 Jan 2024 14:10:13 -0500 Subject: [PATCH 077/111] increment version to 0.9.3-dev --- .bumpversion.cfg | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- aviary/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cfe80c61d..cb0597e80 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.2 +current_version = 0.9.3-dev commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+))? diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b3b15494e..e3fa89790 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -21,7 +21,7 @@ body: attributes: label: Aviary Version description: What version of Aviary is being used. - placeholder: "0.9.2" + placeholder: "0.9.3-dev" validations: required: true - type: textarea diff --git a/aviary/__init__.py b/aviary/__init__.py index a2fecb457..b6cf24f58 100644 --- a/aviary/__init__.py +++ b/aviary/__init__.py @@ -1 +1 @@ -__version__ = "0.9.2" +__version__ = "0.9.3-dev" From 0e3ecec2fd9ca3fdafa5ca28a0de2967f1d0a60f Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Thu, 18 Jan 2024 14:26:50 -0500 Subject: [PATCH 078/111] tmate on --- .github/workflows/test_workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 6927d7b51..436b1947c 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,8 +213,8 @@ jobs: python run_all.py cd ../.. - # - name: Setup tmate session - # uses: mxschmitt/action-tmate@v3 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 - name: Run tests From 5af33650bc42a184f8295363bc88426967fe6d2b Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Thu, 18 Jan 2024 14:45:27 -0500 Subject: [PATCH 079/111] moved tests to correct subfolder --- aviary/mission/ode/test/__init__.py | 0 aviary/mission/{flops_based => }/ode/test/test_altitude_rate.py | 0 .../{flops_based => }/ode/test/test_specific_energy_rate.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 aviary/mission/ode/test/__init__.py rename aviary/mission/{flops_based => }/ode/test/test_altitude_rate.py (100%) rename aviary/mission/{flops_based => }/ode/test/test_specific_energy_rate.py (100%) diff --git a/aviary/mission/ode/test/__init__.py b/aviary/mission/ode/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/aviary/mission/flops_based/ode/test/test_altitude_rate.py b/aviary/mission/ode/test/test_altitude_rate.py similarity index 100% rename from aviary/mission/flops_based/ode/test/test_altitude_rate.py rename to aviary/mission/ode/test/test_altitude_rate.py diff --git a/aviary/mission/flops_based/ode/test/test_specific_energy_rate.py b/aviary/mission/ode/test/test_specific_energy_rate.py similarity index 100% rename from aviary/mission/flops_based/ode/test/test_specific_energy_rate.py rename to aviary/mission/ode/test/test_specific_energy_rate.py From f896008fe7c5a67d658403316b96473e08ed2cd0 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 18 Jan 2024 17:48:33 -0600 Subject: [PATCH 080/111] updating benchmarks --- .../aircraft_for_bench_FwFm_simple.csv | 159 ---------- .../aircraft_for_bench_GwFm_simple.csv | 273 ------------------ .../benchmark_tests/test_bench_FwFm.py | 26 +- .../benchmark_tests/test_bench_GwFm.py | 12 +- 4 files changed, 19 insertions(+), 451 deletions(-) delete mode 100644 aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv delete mode 100644 aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv deleted file mode 100644 index 2d4ea4703..000000000 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_simple.csv +++ /dev/null @@ -1,159 +0,0 @@ -aircraft:air_conditioning:mass_scaler,1.0,unitless -aircraft:anti_icing:mass_scaler,1.0,unitless -aircraft:apu:mass_scaler,1.1,unitless -aircraft:avionics:mass_scaler,1.2,unitless -aircraft:canard:area,0.0,ft**2 -aircraft:canard:aspect_ratio,0.0,unitless -aircraft:canard:thickness_to_chord,0.0,unitless -aircraft:crew_and_payload:baggage_mass_per_passenger,45.0,lbm -aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless -aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:mass_per_passenger,180.0,lbm -aircraft:crew_and_payload:misc_cargo,0.0,lbm -aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:num_business_class,0,unitless -aircraft:crew_and_payload:num_first_class,11,unitless -aircraft:crew_and_payload:num_flight_attendants,3,unitless -aircraft:crew_and_payload:num_flight_crew,2,unitless -aircraft:crew_and_payload:num_galley_crew,0,unitless -aircraft:crew_and_payload:num_non_flight_crew,3,unitless -aircraft:crew_and_payload:num_passengers,169,unitless -aircraft:crew_and_payload:num_tourist_class,158,unitless -aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless -aircraft:crew_and_payload:wing_cargo,0.0,lbm -aircraft:design:base_area,0.0,ft**2 -aircraft:design:empty_mass_margin_scaler,0.0,unitless -aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless -aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:reserves,3000.,unitless -aircraft:design:subsonic_drag_coeff_factor,1.0,unitless -aircraft:design:supersonic_drag_coeff_factor,1.0,unitless -aircraft:design:use_alt_mass,False,unitless -aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless -aircraft:electrical:mass_scaler,1.25,unitless -aircraft:engine:additional_mass_fraction,0.,unitless -aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless -aircraft:engine:flight_idle_thrust_fraction,0.0,unitless -aircraft:engine:flight_idle_max_fraction,1.0,unitless -aircraft:engine:flight_idle_min_fraction,0.08,unitless -aircraft:engine:fuel_flow_scaler_constant_term,0.,unitless -aircraft:engine:fuel_flow_scaler_linear_term,0.,unitless -aircraft:engine:generate_flight_idle,True,unitless -aircraft:engine:geopotential_alt,False,unitless -aircraft:engine:ignore_negative_thrust,False,unitless -aircraft:engine:interpolation_method,slinear,unitless -aircraft:engine:mass_scaler,1.15,unitless -aircraft:engine:mass,7400,lbm -aircraft:engine:num_engines,2,unitless -aircraft:engine:num_fuselage_engines,0,unitless -aircraft:engine:num_wing_engines,2,unitless -aircraft:engine:reference_mass,7400,lbm -aircraft:engine:reference_sls_thrust,28928.1,lbf -aircraft:engine:scale_mass,True,unitless -aircraft:engine:scale_performance,True,unitless -aircraft:engine:scaled_sls_thrust,28928.1,lbf -aircraft:engine:subsonic_fuel_flow_scaler,1.,unitless -aircraft:engine:supersonic_fuel_flow_scaler,1.,unitless -aircraft:engine:thrust_reversers_mass_scaler,0.0,unitless -aircraft:engine:wing_locations,[0.26869218],unitless -aircraft:fins:area,0.0,ft**2 -aircraft:fins:mass_scaler,1.0,unitless -aircraft:fins:mass,0.0,lbm -aircraft:fins:num_fins,0,unitless -aircraft:fins:taper_ratio,10.0,unitless -aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless -aircraft:fuel:fuel_system_mass_scaler,1.0,unitless -aircraft:fuel:fuselage_fuel_capacity,0.0,lbm -aircraft:fuel:num_tanks,7,unitless -aircraft:fuel:total_capacity,45694.0,lbm -aircraft:fuel:unusable_fuel_mass_scaler,1.0,unitless -aircraft:furnishings:mass_scaler,1.1,unitless -aircraft:fuselage:length,128.0,ft -aircraft:fuselage:mass_scaler,1.05,unitless -aircraft:fuselage:max_height,13.17,ft -aircraft:fuselage:max_width,12.33,ft -aircraft:fuselage:military_cargo_floor,False,unitless -aircraft:fuselage:num_fuselages,1,unitless -aircraft:fuselage:passenger_compartment_length,85.5,ft -aircraft:fuselage:planform_area,1578.24,ft**2 -aircraft:fuselage:wetted_area_scaler,1.0,unitless -aircraft:fuselage:wetted_area,4158.62,ft**2 -aircraft:horizontal_tail:area,355.0,ft**2 -aircraft:horizontal_tail:aspect_ratio,6.0,unitless -aircraft:horizontal_tail:mass_scaler,1.2,unitless -aircraft:horizontal_tail:taper_ratio,0.22,unitless -aircraft:horizontal_tail:thickness_to_chord,0.125,unitless -aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless -aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless -aircraft:horizontal_tail:wetted_area,592.65,ft**2 -aircraft:hydraulics:mass_scaler,1.0,unitless -aircraft:hydraulics:system_pressure,3000.0,lbf/ft**2 -aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless -aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless -aircraft:landing_gear:main_gear_oleo_length,102.0,inch -aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless -aircraft:landing_gear:nose_gear_oleo_length,67.0,inch -aircraft:nacelle:avg_diameter,7.94,ft -aircraft:nacelle:avg_length,12.3,ft -aircraft:nacelle:count_factor,2,unitless -aircraft:nacelle:mass_scaler,1.0,unitless -aircraft:nacelle:wetted_area_scaler,1.0,unitless -aircraft:paint:mass_per_unit_area,0.037,lbm/ft**2 -aircraft:propulsion:engine_oil_mass_scaler,1.0,unitless -aircraft:propulsion:misc_mass_scaler,1.0,unitless -aircraft:vertical_tail:area,284.0,ft**2 -aircraft:vertical_tail:aspect_ratio,1.75,unitless -aircraft:vertical_tail:mass_scaler,1.0,unitless -aircraft:vertical_tail:num_tails,1,unitless -aircraft:vertical_tail:taper_ratio,0.33,unitless -aircraft:vertical_tail:thickness_to_chord,0.1195,unitless -aircraft:vertical_tail:wetted_area_scaler,1.0,unitless -aircraft:vertical_tail:wetted_area,581.13,ft**2 -aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless -aircraft:wing:airfoil_technology,1.92669766647637,unitless -aircraft:wing:area,1370.0,ft**2 -aircraft:wing:aspect_ratio,11.22091,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless -aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless -aircraft:wing:composite_fraction,0.2,unitless -aircraft:wing:control_surface_area,137,ft**2 -aircraft:wing:control_surface_area_ratio,0.1,unitless -aircraft:wing:glove_and_bat,134.0,ft**2 -aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless -aircraft:wing:load_distribution_control,2.0,unitless -aircraft:wing:load_fraction,1.0,unitless -aircraft:wing:load_path_sweep_dist,0.,22.,deg -aircraft:wing:mass_scaler,1.23,unitless -aircraft:wing:max_camber_at_70_semispan,0.0,unitless -aircraft:wing:misc_mass_scaler,1.0,unitless -aircraft:wing:num_integration_stations,50,unitless -aircraft:wing:shear_control_mass_scaler,1.0,unitless -aircraft:wing:span_efficiency_reduction,False,unitless -aircraft:wing:span,117.83,ft -aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless -aircraft:wing:sweep,25.0,deg -aircraft:wing:taper_ratio,0.278,unitless -aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless -aircraft:wing:thickness_to_chord,0.13,unitless -aircraft:wing:ultimate_load_factor,3.75,unitless -aircraft:wing:var_sweep_mass_penalty,0.0,unitless -aircraft:wing:wetted_area_scaler,1.0,unitless -aircraft:wing:wetted_area,2396.56,ft**2 -mission:constraints:max_mach,0.785,unitless -mission:design:cruise_altitude,35000,ft -mission:design:gross_mass,175400.0,lbm -mission:design:range,3500,NM -mission:design:thrust_takeoff_per_eng,28928.1,lbf -mission:landing:lift_coefficient_max,2.0,unitless -mission:summary:cruise_mach,0.785,unitless -mission:summary:fuel_flow_scaler,1.0,unitless -mission:takeoff:fuel_simple,577,lbm -mission:takeoff:lift_coefficient_max,3.0,unitless -mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,height_energy -settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv deleted file mode 100644 index 5c0d0b8a0..000000000 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm_simple.csv +++ /dev/null @@ -1,273 +0,0 @@ -aircraft:air_conditioning:mass_scaler,1.0,unitless -aircraft:anti_icing:mass_scaler,1.0,unitless -aircraft:apu:mass_scaler,1.1,unitless -aircraft:avionics:mass_scaler,1.2,unitless -aircraft:canard:area,0.0,ft**2 -aircraft:canard:aspect_ratio,0.0,unitless -aircraft:canard:thickness_to_chord,0.0,unitless -aircraft:controls:cockpit_control_mass_scaler,1,unitless -aircraft:controls:control_mass_increment,0,lbm -aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:controls:stability_augmentation_system_mass,0,lbm -aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless -aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:mass_per_passenger,180.0,lbm -aircraft:crew_and_payload:misc_cargo,0.0,lbm -aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:num_business_class,0,unitless -aircraft:crew_and_payload:num_first_class,11,unitless -aircraft:crew_and_payload:num_flight_attendants,3,unitless -aircraft:crew_and_payload:num_flight_crew,2,unitless -aircraft:crew_and_payload:num_galley_crew,0,unitless -aircraft:crew_and_payload:num_non_flight_crew,3,unitless -aircraft:crew_and_payload:num_passengers,180,unitless -aircraft:crew_and_payload:num_tourist_class,158,unitless -aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm -aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless -aircraft:crew_and_payload:wing_cargo,0.0,lbm -aircraft:design:base_area,0.0,ft**2 -aircraft:design:cg_delta,0.25,unitless -aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:compute_htail_volume_coeff,False,unitless -aircraft:design:compute_vtail_volume_coeff,False,unitless -aircraft:design:drag_increment,0.00175,unitless -aircraft:design:empty_mass_margin_scaler,0.0,unitless -aircraft:design:equipment_mass_coefficients,928.0,0.0736,0.112,0.14,1959.0,1.65,551.0,11192.0,5.0,3.0,50.0,7.6,12.0,unitless -aircraft:design:lift_curve_slope,7.1765,1/rad -aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless -aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:max_structural_speed,402.5,mi/h -aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserves,5000.,unitless -aircraft:design:smooth_mass_discontinuities,False,unitless -aircraft:design:static_margin,0.03,unitless -aircraft:design:structural_mass_increment,0,lbm -aircraft:design:subsonic_drag_coeff_factor,1.0,unitless -aircraft:design:supercritical_drag_shift,0.033,unitless -aircraft:design:supersonic_drag_coeff_factor,1.0,unitless -aircraft:design:ulf_calculated_from_maneuver,False,unitless -aircraft:design:use_alt_mass,False,unitless -aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless -aircraft:electrical:has_hybrid_system,False,unitless -aircraft:electrical:mass_scaler,1.25,unitless -aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless -aircraft:engine:engine_mass_specific,0.21366,lbm/lbf -aircraft:engine:flight_idle_thrust_fraction,0.0,unitless -aircraft:engine:flight_idle_max_fraction,1.0,unitless -aircraft:engine:flight_idle_min_fraction,0.08,unitless -aircraft:engine:fuel_flow_scaler_constant_term,0.,unitless -aircraft:engine:fuel_flow_scaler_linear_term,0.,unitless -aircraft:engine:generate_flight_idle,True,unitless -aircraft:engine:geopotential_alt,False,unitless -aircraft:engine:has_propellers,False,unitless -aircraft:engine:ignore_negative_thrust,False,unitless -aircraft:engine:interpolation_method,slinear,unitless -aircraft:engine:mass_scaler,1.0,unitless -aircraft:engine:mass,7400,lbm -aircraft:engine:additional_mass_fraction,0.14,unitless -aircraft:engine:num_engines,2,unitless -aircraft:engine:num_fuselage_engines,0,unitless -aircraft:engine:num_wing_engines,2,unitless -aircraft:engine:pod_mass_scaler,1,unitless -aircraft:engine:pylon_factor,1.25,unitless -aircraft:engine:reference_diameter,5.8,ft -aircraft:engine:reference_mass,7400,lbm -aircraft:engine:reference_sls_thrust,28928.1,lbf -aircraft:engine:scale_mass,True,unitless -aircraft:engine:scale_performance,True,unitless -aircraft:engine:scaled_sls_thrust,28928.1,lbf -aircraft:engine:subsonic_fuel_flow_scaler,1.,unitless -aircraft:engine:supersonic_fuel_flow_scaler,1.,unitless -aircraft:engine:thrust_reversers_mass_scaler,0.0,unitless -aircraft:engine:type,7,unitless -aircraft:engine:wing_locations,[0.26869218],unitless -aircraft:fins:area,0.0,ft**2 -aircraft:fins:mass_scaler,1.0,unitless -aircraft:fins:mass,0.0,lbm -aircraft:fins:num_fins,0,unitless -aircraft:fins:taper_ratio,10.0,unitless -aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless -aircraft:fuel:density,6.687,lbm/galUS -aircraft:fuel:fuel_margin,0,unitless -aircraft:fuel:fuel_system_mass_coefficient,0.041,unitless -aircraft:fuel:fuel_system_mass_scaler,1.0,unitless -aircraft:fuel:fuselage_fuel_capacity,0.0,lbm -aircraft:fuel:num_tanks,7,unitless -aircraft:fuel:total_capacity,45694.0,lbm -aircraft:fuel:unusable_fuel_mass_scaler,1.0,unitless -aircraft:fuel:wing_fuel_fraction,0,unitless -aircraft:fuel:wing_volume_geometric_max,1114.0,ft**3 -aircraft:furnishings:mass_scaler,1.1,unitless -aircraft:fuselage:aisle_width,24,inch -aircraft:fuselage:avg_diameter,12.75,ft -aircraft:fuselage:delta_diameter,4.5,ft -aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 -aircraft:fuselage:form_factor,1.25,unitless -aircraft:fuselage:length,128.0,ft -aircraft:fuselage:mass_coefficient,128,unitless -aircraft:fuselage:mass_scaler,1.0,unitless -aircraft:fuselage:mass,18357.13345514,lbm -aircraft:fuselage:max_height,13.17,ft -aircraft:fuselage:max_width,12.33,ft -aircraft:fuselage:military_cargo_floor,False,unitless -aircraft:fuselage:nose_fineness,1,unitless -aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_fuselages,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless -aircraft:fuselage:passenger_compartment_length,85.5,ft -aircraft:fuselage:pilot_compartment_length,9.5,ft -aircraft:fuselage:planform_area,1578.24,ft**2 -aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:provide_surface_area,True,unitless -aircraft:fuselage:seat_pitch,29,inch -aircraft:fuselage:seat_width,20.2,inch -aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless -aircraft:fuselage:wetted_area_scaler,1.0,unitless -aircraft:fuselage:wetted_area,4158.62,ft**2 -aircraft:horizontal_tail:area,355.0,ft**2 -aircraft:horizontal_tail:aspect_ratio,4.75,unitless -aircraft:horizontal_tail:average_chord,9.577,ft -aircraft:horizontal_tail:form_factor,1.25,unitless -aircraft:horizontal_tail:mass_coefficient,0.232,unitless -aircraft:horizontal_tail:mass_scaler,1.0,unitless -aircraft:horizontal_tail:moment_ratio,0.2307,unitless -aircraft:horizontal_tail:span,42.254,ft -aircraft:horizontal_tail:sweep,25,deg -aircraft:horizontal_tail:taper_ratio,0.22,unitless -aircraft:horizontal_tail:thickness_to_chord,0.125,unitless -aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless -aircraft:horizontal_tail:volume_coefficient,1.189,unitless -aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless -aircraft:horizontal_tail:wetted_area,592.65,ft**2 -aircraft:hydraulics:mass_scaler,1.0,unitless -aircraft:hydraulics:system_pressure,3000.0,lbf/ft**2 -aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless -aircraft:landing_gear:fixed_gear,True,unitless -aircraft:landing_gear:main_gear_location,0.15,unitless -aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless -aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless -aircraft:landing_gear:main_gear_mass,6366.615,lbm -aircraft:landing_gear:main_gear_oleo_length,102.0,inch -aircraft:landing_gear:mass_coefficient,0.04,unitless -aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless -aircraft:landing_gear:nose_gear_oleo_length,67.0,inch -aircraft:landing_gear:tail_hook_mass_scaler,1,unitless -aircraft:landing_gear:total_mass_scaler,1,unitless -aircraft:nacelle:avg_diameter,7.94,ft -aircraft:nacelle:avg_length,12.3,ft -aircraft:nacelle:clearance_ratio,0.2,unitless -aircraft:nacelle:core_diameter_ratio,1.25,unitless -aircraft:nacelle:count_factor,2,unitless -aircraft:nacelle:fineness,2,unitless -aircraft:nacelle:form_factor,1.5,unitless -aircraft:nacelle:mass_scaler,1.0,unitless -aircraft:nacelle:mass_specific,3,lbm/ft**2 -aircraft:nacelle:surface_area,329.615,ft**2 -aircraft:nacelle:wetted_area_scaler,1.0,unitless -aircraft:paint:mass_per_unit_area,0.037,lbm/ft**2 -aircraft:propulsion:engine_oil_mass_scaler,1.0,unitless -aircraft:propulsion:misc_mass_scaler,1.0,unitless -aircraft:propulsion:total_num_engines,2,unitless -aircraft:strut:area_ratio,0,unitless -aircraft:strut:chord,0,ft -aircraft:strut:dimensional_location_specified,True,unitless -aircraft:strut:fuselage_interference_factor,0,unitless -aircraft:vertical_tail:area,284.0,ft**2 -aircraft:vertical_tail:aspect_ratio,1.75,unitless -aircraft:vertical_tail:average_chord,16.832,ft -aircraft:vertical_tail:form_factor,1.25,unitless -aircraft:vertical_tail:mass_coefficient,0.289,unitless -aircraft:vertical_tail:mass_scaler,1.0,unitless -aircraft:vertical_tail:moment_ratio,2.362,unitless -aircraft:vertical_tail:num_tails,1,unitless -aircraft:vertical_tail:span,27.996,ft -aircraft:vertical_tail:sweep,35,deg -aircraft:vertical_tail:taper_ratio,0.33,unitless -aircraft:vertical_tail:thickness_to_chord,0.1195,unitless -aircraft:vertical_tail:volume_coefficient,0.145,unitless -aircraft:vertical_tail:wetted_area_scaler,1.0,unitless -aircraft:vertical_tail:wetted_area,581.13,ft**2 -aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless -aircraft:wing:airfoil_technology,1.92669766647637,unitless -aircraft:wing:area,1370.0,ft**2 -aircraft:wing:aspect_ratio,10.13,unitless -aircraft:wing:average_chord,12.615,ft -aircraft:wing:bending_mass_scaler,1.0,unitless -aircraft:wing:center_distance,0.463,unitless -aircraft:wing:choose_fold_location,True,unitless -aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless -aircraft:wing:composite_fraction,0.2,unitless -aircraft:wing:control_surface_area,137,ft**2 -aircraft:wing:control_surface_area_ratio,0.1,unitless -aircraft:wing:flap_chord_ratio,0.3,unitless -aircraft:wing:flap_deflection_landing,40,deg -aircraft:wing:flap_deflection_takeoff,10,deg -aircraft:wing:flap_type,double_slotted,unitless -aircraft:wing:fold_dimensional_location_specified,False,unitless -aircraft:wing:form_factor,1.25,unitless -aircraft:wing:fuselage_interference_factor,1.1,unitless -aircraft:wing:glove_and_bat,134.0,ft**2 -aircraft:wing:has_fold,False,unitless -aircraft:wing:has_strut,False,unitless -aircraft:wing:height,8,ft -aircraft:wing:high_lift_mass_coefficient,1.9,unitless -aircraft:wing:incidence,0,deg -aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless -aircraft:wing:load_distribution_control,2.0,unitless -aircraft:wing:load_fraction,1.0,unitless -aircraft:wing:load_path_sweep_dist,0.,22.,deg -aircraft:wing:loading_above_20,True,unitless -aircraft:wing:loading,128.0,lbf/ft**2 -aircraft:wing:mass_coefficient,102.5,unitless -aircraft:wing:mass_scaler,1.0,unitless -aircraft:wing:max_camber_at_70_semispan,0.0,unitless -aircraft:wing:max_thickness_location,0.4,unitless -aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:misc_mass_scaler,1.0,unitless -aircraft:wing:mounting_type,0,unitless -aircraft:wing:num_integration_stations,50,unitless -aircraft:wing:shear_control_mass_scaler,1.0,unitless -aircraft:wing:span_efficiency_reduction,False,unitless -aircraft:wing:span,117.83,ft -aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless -aircraft:wing:sweep,25.0,deg -aircraft:wing:taper_ratio,0.33,unitless -aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless -aircraft:wing:thickness_to_chord_root,0.15,unitless -aircraft:wing:thickness_to_chord_tip,0.12,unitless -aircraft:wing:thickness_to_chord_unweighted,0.1397,unitless -aircraft:wing:thickness_to_chord,0.13,unitless -aircraft:wing:ultimate_load_factor,3.91650835,unitless -aircraft:wing:var_sweep_mass_penalty,0.0,unitless -aircraft:wing:wetted_area_scaler,1.0,unitless -aircraft:wing:wetted_area,2396.56,ft**2 -aircraft:wing:zero_lift_angle,-1.2,deg -mission:constraints:max_mach,0.785,unitless -mission:design:cruise_altitude,25000,ft -mission:design:gross_mass,175400.0,lbm -mission:design:lift_coefficient_max_flaps_up,1.2596,unitless -mission:design:range,3500,NM -mission:design:thrust_takeoff_per_eng,28928.1,lbf -mission:landing:airport_altitude,0,ft -mission:landing:drag_coefficient_flap_increment,0.0406,unitless -mission:landing:lift_coefficient_flap_increment,1.0293,unitless -mission:landing:lift_coefficient_max,2.8155,unitless -mission:summary:cruise_mach,0.785,unitless -mission:summary:fuel_flow_scaler,1.0,unitless -mission:summary:gross_mass,175400,lbm -mission:takeoff:airport_altitude,0,ft -mission:takeoff:drag_coefficient_flap_increment,0.0085,unitless -mission:takeoff:fuel_simple,577,lbm -mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless -mission:takeoff:lift_coefficient_max,3.0,unitless -mission:takeoff:lift_over_drag,17.354,unitless -mission:takeoff:rolling_friction_coefficient,0.0175,unitless -settings:equations_of_motion,height_energy -settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 68eed3e2b..7fff9058e 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -274,18 +274,18 @@ def bench_test_swap_4_FwFm(self): "num_segments": 6, "order": 3, "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), + "initial_mach": (0.3, "unitless"), "final_mach": (0.79, "unitless"), "mach_bounds": ((0.1, 0.8), "unitless"), "initial_altitude": (35., "ft"), "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((0.0, 36000.0), "ft"), + "altitude_bounds": ((0.0, 35000.0), "ft"), "throttle_enforcement": "path_constraint", "constrain_final": False, "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), + "initial_bounds": ((0.0, 2.0), "min"), "duration_bounds": ((5.0, 50.0), "min"), - "no_descent": True, + "no_descent": False, "add_initial_mass_constraint": False, }, "initial_guesses": {"times": ([0, 40.0], "min")}, @@ -302,7 +302,7 @@ def bench_test_swap_4_FwFm(self): "solve_for_distance": False, "initial_mach": (0.79, "unitless"), "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.78, 0.8), "unitless"), + "mach_bounds": ((0.79, 0.79), "unitless"), "initial_altitude": (35000.0, "ft"), "final_altitude": (35000.0, "ft"), "altitude_bounds": ((35000.0, 35000.0), "ft"), @@ -311,7 +311,7 @@ def bench_test_swap_4_FwFm(self): "constrain_final": False, "fix_duration": False, "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((60.0, 7200.0), "min"), + "duration_bounds": ((60.0, 720.0), "min"), }, "initial_guesses": {"times": ([128, 113], "min")}, }, @@ -328,27 +328,27 @@ def bench_test_swap_4_FwFm(self): "final_mach": (0.3, "unitless"), "mach_bounds": ((0.2, 0.8), "unitless"), "initial_altitude": (35000.0, "ft"), - "final_altitude": (500.0, "ft"), + "final_altitude": (35.0, "ft"), "altitude_bounds": ((0.0, 35000.0), "ft"), "throttle_enforcement": "path_constraint", "fix_initial": False, "constrain_final": True, "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((5.0, 60.0), "min"), - "no_climb": False + "initial_bounds": ((120., 800.), "min"), + "duration_bounds": ((5.0, 35.0), "min"), + "no_climb": True, }, - "initial_guesses": {"times": ([241, 58], "min")}, + "initial_guesses": {"times": ([241, 30], "min")}, }, "post_mission": { "include_landing": True, "constrain_range": True, - "target_range": (3350.0, "nmi"), + "target_range": (3368.0, "nmi"), }, } prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info, max_iter=100) + 'models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, max_iter=50) compare_against_expected_values(prob, self.expected_dict) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 41eb97514..4d173b597 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -341,10 +341,10 @@ def bench_test_swap_1_GwFm(self): "constrain_final": True, "fix_duration": False, "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((5.0, 60.0), "min"), - "no_climb": False + "duration_bounds": ((5.0, 30.0), "min"), + "no_climb": True, }, - "initial_guesses": {"times": ([241, 58], "min")}, + "initial_guesses": {"times": ([241, 30], "min")}, }, "post_mission": { "include_landing": True, @@ -353,8 +353,8 @@ def bench_test_swap_1_GwFm(self): }, } - prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm_simple.csv', phase_info, - max_iter=15) + prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info, + max_iter=50) compare_against_expected_values(prob, self.expected_dict) @@ -362,4 +362,4 @@ def bench_test_swap_1_GwFm(self): if __name__ == '__main__': test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_1_GwFm_simple() + test.bench_test_swap_1_GwFm() From be4f91e58507070c1131479f97337fe70fc8178f Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 18 Jan 2024 18:26:46 -0600 Subject: [PATCH 081/111] Updated tests and docs --- aviary/docs/examples/OAS_subsystem.ipynb | 2 +- .../examples/additional_flight_phases.ipynb | 2 +- ...oupled_aircraft_mission_optimization.ipynb | 2 +- .../docs/examples/more_advanced_example.ipynb | 6 +- .../examples/simple_mission_example.ipynb | 6 +- .../onboarding_ext_subsystem.ipynb | 8 +- .../getting_started/onboarding_level3.ipynb | 375 +++++++++++++++++- ..._same_mission_at_different_UI_levels.ipynb | 318 +++++++++++++-- .../OAS_weight/run_simple_OAS_mission.py | 2 +- .../external_subsystems/battery/run_cruise.py | 2 +- .../simple_weight/run_simple_weight.py | 2 +- aviary/examples/run_aviary_example.py | 2 +- aviary/examples/run_basic_aviary_example.py | 2 +- aviary/interface/test/test_simple_mission.py | 2 +- .../benchmark_tests/test_0_iters.py | 2 +- .../test_FLOPS_based_sizing_N3CC.py | 2 +- 16 files changed, 671 insertions(+), 64 deletions(-) diff --git a/aviary/docs/examples/OAS_subsystem.ipynb b/aviary/docs/examples/OAS_subsystem.ipynb index cff6691c7..af46777e2 100644 --- a/aviary/docs/examples/OAS_subsystem.ipynb +++ b/aviary/docs/examples/OAS_subsystem.ipynb @@ -329,7 +329,7 @@ "if use_OAS:\n", " phase_info['pre_mission']['external_subsystems'] = [wing_weight_builder]\n", "\n", - "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", + "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "mission_method = 'simple'\n", "mass_method = 'FLOPS'\n", "make_plots = False\n", diff --git a/aviary/docs/examples/additional_flight_phases.ipynb b/aviary/docs/examples/additional_flight_phases.ipynb index 7a5cf85a8..ab4ebb2fd 100644 --- a/aviary/docs/examples/additional_flight_phases.ipynb +++ b/aviary/docs/examples/additional_flight_phases.ipynb @@ -223,7 +223,7 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index b39e7217d..6f92f388f 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -148,7 +148,7 @@ "source": [ "import aviary.api as av\n", "\n", - "aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", + "aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "optimizer = \"IPOPT\"\n", "make_plots = True\n", "max_iter = 200\n", diff --git a/aviary/docs/examples/more_advanced_example.ipynb b/aviary/docs/examples/more_advanced_example.ipynb index bd2875bca..865794564 100644 --- a/aviary/docs/examples/more_advanced_example.ipynb +++ b/aviary/docs/examples/more_advanced_example.ipynb @@ -125,7 +125,7 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, @@ -188,7 +188,7 @@ "source": [ "import csv\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", + "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "filename = av.get_path(filename)\n", "\n", "# Read the file\n", @@ -279,7 +279,7 @@ "phase_info['cruise']['user_options']['polynomial_control_order'] = 1\n", "phase_info['descent_1']['user_options']['polynomial_control_order'] = 3\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", " phase_info, optimizer=\"IPOPT\", make_plots=True)" ] }, diff --git a/aviary/docs/examples/simple_mission_example.ipynb b/aviary/docs/examples/simple_mission_example.ipynb index 6c3f17509..71dd7a3fb 100644 --- a/aviary/docs/examples/simple_mission_example.ipynb +++ b/aviary/docs/examples/simple_mission_example.ipynb @@ -21,7 +21,7 @@ "* value: the user-defined value of the variable\n", "* units: the units of the variable\n", "\n", - "Let's take a look at the first few lines of an example aircraft file, `aircraft_for_bench_FwFm_simple.csv`.\n", + "Let's take a look at the first few lines of an example aircraft file, `aircraft_for_bench_FwFm.csv`.\n", "This aircraft is a commercial single-aisle aircraft with two conventional turbofan engines.\n", "Think of it in the same class as a Boeing 737 or Airbus A320.\n", "\n", @@ -40,7 +40,7 @@ "source": [ "import aviary.api as av\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", + "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "filename = av.get_path(filename)\n", "\n", "with open(filename, 'r') as file:\n", @@ -279,7 +279,7 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv',\n", + "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", " phase_info, optimizer=\"SLSQP\", make_plots=True)" ] }, diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index 2b951e8af..c5a9a12b4 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -60,7 +60,7 @@ "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info)\n", + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -119,7 +119,7 @@ "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', av.default_height_energy_phase_info)\n", + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', av.default_height_energy_phase_info)\n", "\n", "# Have checks for clashing user inputs\n", "# Raise warnings or errors depending on how clashing the issues are\n", @@ -231,7 +231,7 @@ "source": [ "prob = av.AviaryProblem()\n", "\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info)" + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info)" ] }, { @@ -622,7 +622,7 @@ "metadata": {}, "outputs": [], "source": [ - "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv'\n", + "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "make_plots = False\n", "max_iter = 0\n", "optimizer = 'SNOPT'\n", diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index eddbbcf53..db2c436ec 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -57,10 +57,370 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "42c6704a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:landing_to_takeoff_mass_ratio\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:nacelle:total_wetted_area\n", + " 'aircraft:nacelle:wetted_area\n", + " 'aircraft:propulsion:total_engine_controls_mass\n", + " 'aircraft:propulsion:total_starter_mass\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- climb ---\n", + " None\n", + " --- cruise ---\n", + " [path] 3.0000e+02 <= altitude_rate_max [ft/min]\n", + " --- descent ---\n", + " None\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:aspect_ratio', promoted using 'aircraft:canard:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:aspect_ratio', promoted using 'aircraft:horizontal_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:aspect_ratio', promoted using 'aircraft:vertical_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb' \n", + " Non-default solvers are required\n", + " implicit duration: False\n", + " solved segments: False\n", + " input initial: True\n", + " Setting `traj.phases.climb.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", + " Explicitly set traj.phases.climb.nonlinear_solver to override.\n", + " Setting `traj.phases.climb.linear_solver = om.DirectSolver(iprint=2)`\n", + " Explicitly set traj.phases.climb.linear_solver to override.\n", + " Set `traj.phases.climb.options[\"auto_solvers\"] = False` to disable this behavior.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "\n", + "List of user-set options:\n", + "\n", + " Name Value used\n", + " file_print_level = 5 yes\n", + " hessian_approximation = limited-memory yes\n", + " linear_solver = mumps yes\n", + " max_iter = 100 yes\n", + " nlp_scaling_method = user-scaling yes\n", + " output_file = reports/problem7/IPOPT.out yes\n", + " print_level = 4 yes\n", + " print_user_options = yes yes\n", + " sb = yes yes\n", + " tol = 0.001 yes\n", + "Total number of variables............................: 82\n", + " variables with only lower bounds: 0\n", + " variables with lower and upper bounds: 82\n", + " variables with only upper bounds: 0\n", + "Total number of equality constraints.................: 79\n", + "Total number of inequality constraints...............: 4\n", + " inequality constraints with only lower bounds: 4\n", + " inequality constraints with lower and upper bounds: 0\n", + " inequality constraints with only upper bounds: 0\n", + "\n", + "\n", + "Number of Iterations....: 25\n", + "\n", + " (scaled) (unscaled)\n", + "Objective...............: 9.4146770609913695e+00 9.4146770609913695e+00\n", + "Dual infeasibility......: 1.0999629934911812e-08 1.0999629934911812e-08\n", + "Constraint violation....: 3.2276147976517677e-08 3.2276147976517677e-08\n", + "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", + "Complementarity.........: 1.2325706634551805e-06 1.2325706634551805e-06\n", + "Overall NLP error.......: 1.2325706634551805e-06 1.2325706634551805e-06\n", + "\n", + "\n", + "Number of objective function evaluations = 28\n", + "Number of objective gradient evaluations = 26\n", + "Number of equality constraint evaluations = 28\n", + "Number of inequality constraint evaluations = 28\n", + "Number of equality constraint Jacobian evaluations = 26\n", + "Number of inequality constraint Jacobian evaluations = 26\n", + "Number of Lagrangian Hessian evaluations = 0\n", + "Total seconds in IPOPT = 13.774\n", + "\n", + "EXIT: Optimal Solution Found.\n", + "\n", + "\n", + "Optimization Problem -- Optimization using pyOpt_sparse\n", + "================================================================================\n", + " Objective Function: _objfunc\n", + "\n", + " Solution: \n", + "--------------------------------------------------------------------------------\n", + " Total Time: 13.7775\n", + " User Objective Time : 9.9599\n", + " User Sensitivity Time : 3.6817\n", + " Interface Time : 0.0666\n", + " Opt Solver Time: 0.0694\n", + " Calls to Objective Function : 28\n", + " Calls to Sens Function : 26\n", + "\n", + "\n", + " Objectives\n", + " Index Name Value\n", + " 0 reg_objective 9.414677E+00\n", + "\n", + " Variables (c - continuous, i - integer, d - discrete)\n", + " Index Name Type Lower Bound Value Upper Bound Status\n", + " 0 mission:design:gross_mass_0 c 7.407407E-01 8.607091E-01 1.481481E+00 \n", + " 1 traj.climb.t_duration_0 c 5.000000E-01 5.000003E-01 2.000000E+00 l\n", + " 2 traj.climb.states:mass_0 c 0.000000E+00 5.241266E+00 1.000000E+17 \n", + " 3 traj.climb.states:mass_1 c 0.000000E+00 5.237291E+00 1.000000E+17 \n", + " 4 traj.climb.states:mass_2 c 0.000000E+00 5.236091E+00 1.000000E+17 \n", + " 5 traj.climb.states:mass_3 c 0.000000E+00 5.230548E+00 1.000000E+17 \n", + " 6 traj.climb.states:mass_4 c 0.000000E+00 5.223489E+00 1.000000E+17 \n", + " 7 traj.climb.states:mass_5 c 0.000000E+00 5.221338E+00 1.000000E+17 \n", + " 8 traj.climb.states:mass_6 c 0.000000E+00 5.215137E+00 1.000000E+17 \n", + " 9 traj.climb.states:mass_7 c 0.000000E+00 5.206956E+00 1.000000E+17 \n", + " 10 traj.climb.states:mass_8 c 0.000000E+00 5.204440E+00 1.000000E+17 \n", + " 11 traj.climb.states:mass_9 c 0.000000E+00 5.198692E+00 1.000000E+17 \n", + " 12 traj.climb.states:mass_10 c 0.000000E+00 5.190826E+00 1.000000E+17 \n", + " 13 traj.climb.states:mass_11 c 0.000000E+00 5.188345E+00 1.000000E+17 \n", + " 14 traj.climb.states:mass_12 c 0.000000E+00 5.183981E+00 1.000000E+17 \n", + " 15 traj.climb.states:mass_13 c 0.000000E+00 5.177987E+00 1.000000E+17 \n", + " 16 traj.climb.states:mass_14 c 0.000000E+00 5.176097E+00 1.000000E+17 \n", + " 17 traj.climb.states:mass_15 c 0.000000E+00 5.174062E+00 1.000000E+17 \n", + " 18 traj.climb.states:mass_16 c 0.000000E+00 5.171248E+00 1.000000E+17 \n", + " 19 traj.climb.states:mass_17 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", + " 20 traj.climb.states:distance_0 c 0.000000E+00 2.764851E-03 1.000000E+15 \n", + " 21 traj.climb.states:distance_1 c 0.000000E+00 5.071419E-03 1.000000E+15 \n", + " 22 traj.climb.states:distance_2 c 0.000000E+00 5.851859E-03 1.000000E+15 \n", + " 23 traj.climb.states:distance_3 c 0.000000E+00 9.998326E-03 1.000000E+15 \n", + " 24 traj.climb.states:distance_4 c 0.000000E+00 1.663641E-02 1.000000E+15 \n", + " 25 traj.climb.states:distance_5 c 0.000000E+00 1.895456E-02 1.000000E+15 \n", + " 26 traj.climb.states:distance_6 c 0.000000E+00 2.644512E-02 1.000000E+15 \n", + " 27 traj.climb.states:distance_7 c 0.000000E+00 3.822814E-02 1.000000E+15 \n", + " 28 traj.climb.states:distance_8 c 0.000000E+00 4.229839E-02 1.000000E+15 \n", + " 29 traj.climb.states:distance_9 c 0.000000E+00 5.222057E-02 1.000000E+15 \n", + " 30 traj.climb.states:distance_10 c 0.000000E+00 6.724973E-02 1.000000E+15 \n", + " 31 traj.climb.states:distance_11 c 0.000000E+00 7.232091E-02 1.000000E+15 \n", + " 32 traj.climb.states:distance_12 c 0.000000E+00 8.163066E-02 1.000000E+15 \n", + " 33 traj.climb.states:distance_13 c 0.000000E+00 9.521093E-02 1.000000E+15 \n", + " 34 traj.climb.states:distance_14 c 0.000000E+00 9.968231E-02 1.000000E+15 \n", + " 35 traj.climb.states:distance_15 c 0.000000E+00 1.045838E-01 1.000000E+15 \n", + " 36 traj.climb.states:distance_16 c 0.000000E+00 1.114998E-01 1.000000E+15 \n", + " 37 traj.climb.states:distance_17 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", + " 38 traj.cruise.t_initial_0 c 7.260000E+02 8.460004E+02 2.904000E+03 \n", + " 39 traj.cruise.t_duration_0 c 5.000000E-01 5.000000E-01 2.000000E+00 l\n", + " 40 traj.cruise.states:mass_0 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", + " 41 traj.cruise.states:mass_1 c 0.000000E+00 5.005025E+00 1.000000E+17 \n", + " 42 traj.cruise.states:mass_2 c 0.000000E+00 4.780360E+00 1.000000E+17 \n", + " 43 traj.cruise.states:mass_3 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", + " 44 traj.cruise.states:distance_0 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", + " 45 traj.cruise.states:distance_1 c 0.000000E+00 1.127228E+00 1.000000E+15 \n", + " 46 traj.cruise.states:distance_2 c 0.000000E+00 2.525655E+00 1.000000E+15 \n", + " 47 traj.cruise.states:distance_3 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", + " 48 traj.descent.t_initial_0 c 1.291140E+04 1.303140E+04 5.164560E+04 \n", + " 49 traj.descent.t_duration_0 c 5.000000E-01 5.000011E-01 2.000000E+00 \n", + " 50 traj.descent.states:mass_0 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", + " 51 traj.descent.states:mass_1 c 0.000000E+00 4.710502E+00 1.000000E+17 \n", + " 52 traj.descent.states:mass_2 c 0.000000E+00 4.711242E+00 1.000000E+17 \n", + " 53 traj.descent.states:mass_3 c 0.000000E+00 4.711494E+00 1.000000E+17 \n", + " 54 traj.descent.states:mass_4 c 0.000000E+00 4.712779E+00 1.000000E+17 \n", + " 55 traj.descent.states:mass_5 c 0.000000E+00 4.714841E+00 1.000000E+17 \n", + " 56 traj.descent.states:mass_6 c 0.000000E+00 4.715567E+00 1.000000E+17 \n", + " 57 traj.descent.states:mass_7 c 0.000000E+00 4.717767E+00 1.000000E+17 \n", + " 58 traj.descent.states:mass_8 c 0.000000E+00 4.721139E+00 1.000000E+17 \n", + " 59 traj.descent.states:mass_9 c 0.000000E+00 4.722228E+00 1.000000E+17 \n", + " 60 traj.descent.states:mass_10 c 0.000000E+00 4.723686E+00 1.000000E+17 \n", + " 61 traj.descent.states:mass_11 c 0.000000E+00 4.725431E+00 1.000000E+17 \n", + " 62 traj.descent.states:mass_12 c 0.000000E+00 4.726157E+00 1.000000E+17 \n", + " 63 traj.descent.states:mass_13 c 0.000000E+00 4.726963E+00 1.000000E+17 \n", + " 64 traj.descent.states:mass_14 c 0.000000E+00 4.728154E+00 1.000000E+17 \n", + " 65 traj.descent.states:mass_15 c 0.000000E+00 4.728551E+00 1.000000E+17 \n", + " 66 traj.descent.states:distance_0 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", + " 67 traj.descent.states:distance_1 c 0.000000E+00 2.976728E+00 1.000000E+15 \n", + " 68 traj.descent.states:distance_2 c 0.000000E+00 2.988146E+00 1.000000E+15 \n", + " 69 traj.descent.states:distance_3 c 0.000000E+00 2.991691E+00 1.000000E+15 \n", + " 70 traj.descent.states:distance_4 c 0.000000E+00 3.007825E+00 1.000000E+15 \n", + " 71 traj.descent.states:distance_5 c 0.000000E+00 3.028841E+00 1.000000E+15 \n", + " 72 traj.descent.states:distance_6 c 0.000000E+00 3.035182E+00 1.000000E+15 \n", + " 73 traj.descent.states:distance_7 c 0.000000E+00 3.051662E+00 1.000000E+15 \n", + " 74 traj.descent.states:distance_8 c 0.000000E+00 3.072458E+00 1.000000E+15 \n", + " 75 traj.descent.states:distance_9 c 0.000000E+00 3.078555E+00 1.000000E+15 \n", + " 76 traj.descent.states:distance_10 c 0.000000E+00 3.089619E+00 1.000000E+15 \n", + " 77 traj.descent.states:distance_11 c 0.000000E+00 3.103383E+00 1.000000E+15 \n", + " 78 traj.descent.states:distance_12 c 0.000000E+00 3.107367E+00 1.000000E+15 \n", + " 79 traj.descent.states:distance_13 c 0.000000E+00 3.111617E+00 1.000000E+15 \n", + " 80 traj.descent.states:distance_14 c 0.000000E+00 3.117100E+00 1.000000E+15 \n", + " 81 traj.descent.states:distance_15 c 0.000000E+00 3.118742E+00 1.000000E+15 \n", + "\n", + " Constraints (i - inequality, e - equality)\n", + " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", + " 0 mass_resid e 0.000000E+00 -3.227615E-08 0.000000E+00 9.00000E+100\n", + " 1 traj.linkages.climb:time_final|cruise:time_initial e 0.000000E+00 1.136868E-13 0.000000E+00 9.00000E+100\n", + " 2 traj.linkages.climb:mass_final|cruise:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 3 traj.linkages.climb:distance_final|cruise:distance_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 4 traj.linkages.cruise:time_final|descent:time_initial e 0.000000E+00 -1.818989E-12 0.000000E+00 9.00000E+100\n", + " 5 traj.linkages.cruise:mass_final|descent:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 6 traj.linkages.cruise:distance_final|descent:distance_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", + " 7 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.025097E-14 0.000000E+00 9.00000E+100\n", + " 8 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.860766E-14 0.000000E+00 9.00000E+100\n", + " 9 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.699134E-14 0.000000E+00 9.00000E+100\n", + " 10 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.485284E-14 0.000000E+00 9.00000E+100\n", + " 11 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.003003E-14 0.000000E+00 9.00000E+100\n", + " 12 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.531926E-14 0.000000E+00 9.00000E+100\n", + " 13 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.113611E-14 0.000000E+00 9.00000E+100\n", + " 14 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.886567E-14 0.000000E+00 9.00000E+100\n", + " 15 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.598810E-14 0.000000E+00 9.00000E+100\n", + " 16 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.408043E-14 0.000000E+00 9.00000E+100\n", + " 17 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.173824E-14 0.000000E+00 9.00000E+100\n", + " 18 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.099713E-14 0.000000E+00 9.00000E+100\n", + " 19 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.608025E-14 0.000000E+00 9.00000E+100\n", + " 20 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.587637E-14 0.000000E+00 9.00000E+100\n", + " 21 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.558807E-14 0.000000E+00 9.00000E+100\n", + " 22 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.279583E-15 0.000000E+00 9.00000E+100\n", + " 23 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.206002E-15 0.000000E+00 9.00000E+100\n", + " 24 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.240740E-15 0.000000E+00 9.00000E+100\n", + " 25 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.162790E-14 0.000000E+00 9.00000E+100\n", + " 26 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.105201E-14 0.000000E+00 9.00000E+100\n", + " 27 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.002517E-14 0.000000E+00 9.00000E+100\n", + " 28 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 2.058287E-14 0.000000E+00 9.00000E+100\n", + " 29 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.782458E-14 0.000000E+00 9.00000E+100\n", + " 30 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.511325E-14 0.000000E+00 9.00000E+100\n", + " 31 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.872588E-14 0.000000E+00 9.00000E+100\n", + " 32 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.655588E-14 0.000000E+00 9.00000E+100\n", + " 33 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.434107E-14 0.000000E+00 9.00000E+100\n", + " 34 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.377297E-14 0.000000E+00 9.00000E+100\n", + " 35 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.265000E-14 0.000000E+00 9.00000E+100\n", + " 36 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.141126E-14 0.000000E+00 9.00000E+100\n", + " 37 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 8.538640E-15 0.000000E+00 9.00000E+100\n", + " 38 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 8.126975E-15 0.000000E+00 9.00000E+100\n", + " 39 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 7.635711E-15 0.000000E+00 9.00000E+100\n", + " 40 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.521029E-15 0.000000E+00 9.00000E+100\n", + " 41 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.453567E-15 0.000000E+00 9.00000E+100\n", + " 42 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.366714E-15 0.000000E+00 9.00000E+100\n", + " 43 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 5.312109E-13 0.000000E+00 9.00000E+100\n", + " 44 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 4.063769E-13 0.000000E+00 9.00000E+100\n", + " 45 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 2.575362E-13 0.000000E+00 9.00000E+100\n", + " 46 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", + " 47 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 3.463299E-18 0.000000E+00 9.00000E+100\n", + " 48 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", + " 49 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.910022E-14 0.000000E+00 9.00000E+100\n", + " 50 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.529124E-14 0.000000E+00 9.00000E+100\n", + " 51 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.342543E-14 0.000000E+00 9.00000E+100\n", + " 52 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 6.585307E-14 0.000000E+00 9.00000E+100\n", + " 53 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.552915E-14 0.000000E+00 9.00000E+100\n", + " 54 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.341976E-14 0.000000E+00 9.00000E+100\n", + " 55 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.791654E-14 0.000000E+00 9.00000E+100\n", + " 56 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.929329E-14 0.000000E+00 9.00000E+100\n", + " 57 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.075605E-14 0.000000E+00 9.00000E+100\n", + " 58 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 2.145444E-14 0.000000E+00 9.00000E+100\n", + " 59 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.435837E-14 0.000000E+00 9.00000E+100\n", + " 60 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 9.991150E-15 0.000000E+00 9.00000E+100\n", + " 61 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.078937E-15 0.000000E+00 9.00000E+100\n", + " 62 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.142482E-15 0.000000E+00 9.00000E+100\n", + " 63 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.257099E-15 0.000000E+00 9.00000E+100\n", + " 64 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.438287E-14 0.000000E+00 9.00000E+100\n", + " 65 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.567239E-14 0.000000E+00 9.00000E+100\n", + " 66 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.757017E-14 0.000000E+00 9.00000E+100\n", + " 67 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.393325E-13 0.000000E+00 9.00000E+100\n", + " 68 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.459218E-13 0.000000E+00 9.00000E+100\n", + " 69 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.566014E-13 0.000000E+00 9.00000E+100\n", + " 70 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.907169E-13 0.000000E+00 9.00000E+100\n", + " 71 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.047396E-13 0.000000E+00 9.00000E+100\n", + " 72 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.289513E-13 0.000000E+00 9.00000E+100\n", + " 73 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.003578E-13 0.000000E+00 9.00000E+100\n", + " 74 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.175539E-13 0.000000E+00 9.00000E+100\n", + " 75 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.479632E-13 0.000000E+00 9.00000E+100\n", + " 76 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.271784E-13 0.000000E+00 9.00000E+100\n", + " 77 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.344334E-13 0.000000E+00 9.00000E+100\n", + " 78 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.461002E-13 0.000000E+00 9.00000E+100\n", + " 79 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.127272E+02 1.000000E+30 9.00000E+100\n", + " 80 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.752630E+02 1.000000E+30 9.00000E+100\n", + " 81 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.643321E+02 1.000000E+30 9.00000E+100\n", + " 82 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.932716E+02 1.000000E+30 9.00000E+100\n", + "\n", + "\n", + " Exit Status\n", + " Inform Description\n", + " 0 Solve Succeeded\n", + "--------------------------------------------------------------------------------\n", + "\n", + "-------------------------------\n", + "times_climb: [846.00038137] (s)\n", + "altitudes_climb: [10668.] (m)\n", + "masses_climb: [51703.54384226] (kg)\n", + "ranges_climb: [113725.11889636] (m)\n", + "velocities_climb: [234.25795132] (m/s)\n", + "thrusts_climb: [71713.80312354] (N)\n", + "times_cruise: [13031.40073487] (s)\n", + "altitudes_cruise: [10668.] (m)\n", + "masses_cruise: [47100.44512976] (kg)\n", + "ranges_cruise: [2968252.0417268] (m)\n", + "velocities_cruise: [234.25795132] (m/s)\n", + "thrusts_cruise: [26338.70498784] (N)\n", + "times_descent: [13908.60273889] (s)\n", + "altitudes_descent: [10.668] (m)\n", + "masses_descent: [47285.51458051] (kg)\n", + "ranges_descent: [3118741.8185247] (m)\n", + "velocities_descent: [102.07377559] (m/s)\n", + "thrusts_descent: [-43173.10618655] (N)\n", + "-------------------------------\n" + ] + } + ], "source": [ "'''\n", "NOTES:\n", @@ -301,8 +661,7 @@ "# link phases #\n", "##########################################\n", "\n", - "traj.link_phases([\"climb\", \"cruise\", \"descent\"], [\"time\", Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple)\n", + "traj.link_phases([\"climb\", \"cruise\", \"descent\"], [\"time\", av.Dynamic.Mission.MASS, av.Dynamic.Mission.DISTANCE], connected=strong_couple)\n", "\n", "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs)\n", "\n", @@ -420,7 +779,7 @@ "prob.set_val('traj.climb.states:mass', climb.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m')\n", "\n", "prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", "prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", @@ -433,7 +792,7 @@ "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " av.Dynamic.Mission.DISTANCe, ys=[distance_i_cruise, distance_f_cruise]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m')\n", "\n", "prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", "prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", @@ -446,7 +805,7 @@ "prob.set_val('traj.descent.states:mass', descent.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " av.Dynamic.Mission.DISTANCe, ys=[distance_i_descent, distance_f_descent]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", "\n", "# Turn off solver printing so that the SNOPT output is readable.\n", "prob.set_solver_print(level=0)\n", @@ -521,7 +880,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "52550a27", "metadata": {}, "outputs": [], diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 4ee71a14f..5baca4d89 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -25,9 +25,88 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_deck.py:198: UserWarning: is a required option for EngineDecks, but has not been specified for EngineDeck . The default value will be used.\n", + " warnings.warn(\n", + "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:touchdown_mass\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fins:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuel:total_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:landing_gear:main_gear_oleo_length\n", + " 'aircraft:landing_gear:nose_gear_oleo_length\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:control_surface_area\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- climb ---\n", + " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " --- cruise ---\n", + " [initial] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " [final] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " --- descent ---\n", + " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, dymos_solution.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "Full total jacobian was computed 3 times, taking 0.589048 seconds.\n", + "Total jacobian shape: (135, 94) \n", + "\n", + "\n", + "Jacobian shape: (135, 94) (13.71% nonzero)\n", + "FWD solves: 22 REV solves: 0\n", + "Total colors vs. total size: 22 vs 94 (76.60% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 0.5890 sec\n", + "Time to compute coloring: 0.0720 sec\n", + "Memory to compute coloring: 0.1992 MB\n", + "Coloring created on: 2024-01-18 18:19:34\n", + "Iteration limit reached (Exit mode 9)\n", + " Current function value: 0.0\n", + " Iterations: 1\n", + " Function evaluations: 1\n", + " Gradient evaluations: 1\n", + "Optimization FAILED.\n", + "Iteration limit reached\n", + "-----------------------------------\n" + ] + } + ], "source": [ "import aviary.api as av\n", "\n", @@ -50,9 +129,96 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:touchdown_mass\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fins:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuel:total_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:landing_gear:main_gear_oleo_length\n", + " 'aircraft:landing_gear:nose_gear_oleo_length\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:control_surface_area\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- climb ---\n", + " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " --- cruise ---\n", + " [initial] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " [final] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + " --- descent ---\n", + " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, level2_example.db, is being overwritten.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model viewer data has already been recorded for Driver.\n", + "Full total jacobian was computed 3 times, taking 0.528602 seconds.\n", + "Total jacobian shape: (135, 94) \n", + "\n", + "\n", + "Jacobian shape: (135, 94) (13.52% nonzero)\n", + "FWD solves: 21 REV solves: 0\n", + "Total colors vs. total size: 21 vs 94 (77.66% improvement)\n", + "\n", + "Sparsity computed using tolerance: 1e-25\n", + "Time to compute sparsity: 0.5286 sec\n", + "Time to compute coloring: 0.0755 sec\n", + "Memory to compute coloring: 0.0000 MB\n", + "Coloring created on: 2024-01-18 18:19:51\n", + "Iteration limit reached (Exit mode 9)\n", + " Current function value: -0.7956010169800001\n", + " Iterations: 1\n", + " Function evaluations: 1\n", + " Gradient evaluations: 1\n", + "Optimization FAILED.\n", + "Iteration limit reached\n", + "-----------------------------------\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import aviary.api as av\n", "\n", @@ -183,9 +349,110 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", + " warnings.warn(\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'climb': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'climb': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'descent': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'descent': lower, upper, ref\n", + " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:aspect_ratio', promoted using 'aircraft:canard:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:aspect_ratio', promoted using 'aircraft:horizontal_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:aspect_ratio', promoted using 'aircraft:vertical_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", + "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "The following variables have been overridden:\n", + " 'aircraft:design:touchdown_mass\n", + " 'aircraft:engine:mass\n", + " 'aircraft:fins:mass\n", + " 'aircraft:fuel:auxiliary_fuel_capacity\n", + " 'aircraft:fuel:fuselage_fuel_capacity\n", + " 'aircraft:fuel:total_capacity\n", + " 'aircraft:fuselage:planform_area\n", + " 'aircraft:fuselage:wetted_area\n", + " 'aircraft:horizontal_tail:wetted_area\n", + " 'aircraft:landing_gear:main_gear_oleo_length\n", + " 'aircraft:landing_gear:nose_gear_oleo_length\n", + " 'aircraft:vertical_tail:wetted_area\n", + " 'aircraft:wing:aspect_ratio\n", + " 'aircraft:wing:control_surface_area\n", + " 'aircraft:wing:wetted_area\n", + "\n", + "--- Constraint Report [traj] ---\n", + " --- climb ---\n", + " None\n", + " --- cruise ---\n", + " [path] 3.0000e+02 <= altitude_rate_max [ft/min]\n", + " --- descent ---\n", + " None\n", + "\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "type object 'Mission' has no attribute 'RANGE'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[6], line 237\u001b[0m\n\u001b[1;32m 231\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\n\u001b[1;32m 232\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.controls:mach\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[1;32m 233\u001b[0m av\u001b[38;5;241m.\u001b[39mDynamic\u001b[38;5;241m.\u001b[39mMission\u001b[38;5;241m.\u001b[39mMACH, ys\u001b[38;5;241m=\u001b[39m[mach_i_climb, mach_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124munitless\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 234\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.states:mass\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[1;32m 235\u001b[0m av\u001b[38;5;241m.\u001b[39mDynamic\u001b[38;5;241m.\u001b[39mMission\u001b[38;5;241m.\u001b[39mMASS, ys\u001b[38;5;241m=\u001b[39m[mass_i_climb, mass_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mkg\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 236\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.states:distance\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[0;32m--> 237\u001b[0m \u001b[43mav\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mDynamic\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mMission\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mRANGE\u001b[49m, ys\u001b[38;5;241m=\u001b[39m[distance_i_climb, distance_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mm\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 239\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.cruise.t_initial\u001b[39m\u001b[38;5;124m'\u001b[39m, t_i_cruise, units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 240\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.cruise.t_duration\u001b[39m\u001b[38;5;124m'\u001b[39m, t_duration_cruise, units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mAttributeError\u001b[0m: type object 'Mission' has no attribute 'RANGE'" + ] + } + ], "source": [ "import dymos as dm\n", "import openmdao.api as om\n", @@ -390,32 +657,6 @@ "prob.model.connect(\"traj.descent.states:mass\",\n", " \"fuel_burn.descent_mass_final\", src_indices=[-1])\n", "\n", - "# TODO: need to add some sort of check that this value is less than the fuel capacity\n", - "# TODO: need to update this with actual FLOPS value, this gives unrealistic\n", - "# TODO: the overall_fuel variable is the burned fuel plus the reserve, but should\n", - "# also include the unused fuel, and the hierarchy variable name should be more clear\n", - "ecomp = om.ExecComp('overall_fuel = fuel_burned + fuel_reserve',\n", - "\n", - "ecomp = om.ExecComp(\n", - " 'mass_resid = operating_empty_mass + overall_fuel + payload_mass '\n", - " '- initial_mass',\n", - " operating_empty_mass={'units': 'lbm'},\n", - " overall_fuel={'units': 'lbm'},\n", - " payload_mass={'units': 'lbm'},\n", - " initial_mass={'units': 'lbm'},\n", - " mass_resid={'units': 'lbm'})\n", - "\n", - "prob.model.add_subsystem(\n", - " 'mass_constraint', ecomp,\n", - " promotes_inputs=[\n", - " ('operating_empty_mass', av.Aircraft.Design.OPERATING_MASS),\n", - " 'overall_fuel',\n", - " ('payload_mass', av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS),\n", - " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", - " promotes_outputs=['mass_resid'])\n", - "\n", - "prob.model.add_constraint('mass_resid', equals=0.0, ref=1.0)\n", - "\n", "##########################\n", "# Add Objective Function #\n", "##########################\n", @@ -449,7 +690,7 @@ "prob.set_val('traj.climb.states:mass', climb.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " av.Dynamic.Mission.RANGE, ys=[distance_i_climb, distance_f_climb]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m')\n", "\n", "prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", "prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", @@ -462,7 +703,7 @@ "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " av.Dynamic.Mission.RANGE, ys=[distance_i_cruise, distance_f_cruise]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m')\n", "\n", "prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", "prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", @@ -475,7 +716,7 @@ "prob.set_val('traj.descent.states:mass', descent.interp(\n", " av.Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " av.Dynamic.Mission.RANGE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", + " av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", "\n", "# Turn off solver printing so that the SNOPT output is readable.\n", "prob.set_solver_print(level=0)\n", @@ -483,6 +724,13 @@ "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9})" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py index 156676327..34bd5d8a6 100644 --- a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py +++ b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py @@ -108,7 +108,7 @@ if use_OAS: phase_info['pre_mission']['external_subsystems'] = [wing_weight_builder] -aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv' +aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' make_plots = False max_iter = 1 # set this to a higher number to fully run the optimization optimizer = 'SLSQP' diff --git a/aviary/examples/external_subsystems/battery/run_cruise.py b/aviary/examples/external_subsystems/battery/run_cruise.py index 44882c487..a0463c89d 100644 --- a/aviary/examples/external_subsystems/battery/run_cruise.py +++ b/aviary/examples/external_subsystems/battery/run_cruise.py @@ -16,7 +16,7 @@ # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) prob.add_pre_mission_systems() diff --git a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py b/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py index f3f2f7d0d..f5b7769e2 100644 --- a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py +++ b/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py @@ -16,7 +16,7 @@ # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) prob.add_pre_mission_systems() diff --git a/aviary/examples/run_aviary_example.py b/aviary/examples/run_aviary_example.py index 875a5f456..c0ded9597 100644 --- a/aviary/examples/run_aviary_example.py +++ b/aviary/examples/run_aviary_example.py @@ -97,7 +97,7 @@ # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info) +prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) # Preprocess inputs diff --git a/aviary/examples/run_basic_aviary_example.py b/aviary/examples/run_basic_aviary_example.py index b53dac620..a1fe4abd7 100644 --- a/aviary/examples/run_basic_aviary_example.py +++ b/aviary/examples/run_basic_aviary_example.py @@ -11,5 +11,5 @@ import aviary.api as av -prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', av.default_height_energy_phase_info, +prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', av.default_height_energy_phase_info, optimizer="SLSQP", make_plots=True) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index d5643c06a..219206590 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -94,7 +94,7 @@ def setUp(self): }, } - self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv' + self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' self.make_plots = False self.max_iter = 100 diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index d8fe2c56e..2d58fb26e 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -47,7 +47,7 @@ class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_simple_zero_iters(self): local_phase_info = deepcopy(simple_phase_info) - self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', + self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm.csv', local_phase_info) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index 95afa681a..e1b144b94 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -274,7 +274,7 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise", "descent"], [ - "time", Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) + "time", Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) From 2674c0c0d514930243bc15230a81495f42921d51 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 18 Jan 2024 18:27:13 -0600 Subject: [PATCH 082/111] Updated tests and docs --- aviary/docs/build_pdf_book.sh | 1 - .../getting_started/onboarding_level3.ipynb | 366 +----------------- ..._same_mission_at_different_UI_levels.ipynb | 286 +------------- 3 files changed, 9 insertions(+), 644 deletions(-) delete mode 100644 aviary/docs/build_pdf_book.sh diff --git a/aviary/docs/build_pdf_book.sh b/aviary/docs/build_pdf_book.sh deleted file mode 100644 index 846f20db7..000000000 --- a/aviary/docs/build_pdf_book.sh +++ /dev/null @@ -1 +0,0 @@ -jupyter-book build . --builder pdflatex \ No newline at end of file diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index db2c436ec..db5d76a26 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -57,370 +57,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "42c6704a", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "The following variables have been overridden:\n", - " 'aircraft:design:landing_to_takeoff_mass_ratio\n", - " 'aircraft:engine:mass\n", - " 'aircraft:fuel:auxiliary_fuel_capacity\n", - " 'aircraft:fuel:fuselage_fuel_capacity\n", - " 'aircraft:fuselage:planform_area\n", - " 'aircraft:fuselage:wetted_area\n", - " 'aircraft:horizontal_tail:wetted_area\n", - " 'aircraft:nacelle:total_wetted_area\n", - " 'aircraft:nacelle:wetted_area\n", - " 'aircraft:propulsion:total_engine_controls_mass\n", - " 'aircraft:propulsion:total_starter_mass\n", - " 'aircraft:vertical_tail:wetted_area\n", - " 'aircraft:wing:aspect_ratio\n", - " 'aircraft:wing:wetted_area\n", - "\n", - "--- Constraint Report [traj] ---\n", - " --- climb ---\n", - " None\n", - " --- cruise ---\n", - " [path] 3.0000e+02 <= altitude_rate_max [ft/min]\n", - " --- descent ---\n", - " None\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:aspect_ratio', promoted using 'aircraft:canard:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:aspect_ratio', promoted using 'aircraft:horizontal_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:aspect_ratio', promoted using 'aircraft:vertical_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/transcriptions/transcription_base.py:497: OpenMDAOWarning:'traj.phases.climb' \n", - " Non-default solvers are required\n", - " implicit duration: False\n", - " solved segments: False\n", - " input initial: True\n", - " Setting `traj.phases.climb.nonlinear_solver = om.NewtonSolver(iprint=0, solve_subsystems=True, maxiter=1000, stall_limit=3)`\n", - " Explicitly set traj.phases.climb.nonlinear_solver to override.\n", - " Setting `traj.phases.climb.linear_solver = om.DirectSolver(iprint=2)`\n", - " Explicitly set traj.phases.climb.linear_solver to override.\n", - " Set `traj.phases.climb.options[\"auto_solvers\"] = False` to disable this behavior.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model viewer data has already been recorded for Driver.\n", - "\n", - "List of user-set options:\n", - "\n", - " Name Value used\n", - " file_print_level = 5 yes\n", - " hessian_approximation = limited-memory yes\n", - " linear_solver = mumps yes\n", - " max_iter = 100 yes\n", - " nlp_scaling_method = user-scaling yes\n", - " output_file = reports/problem7/IPOPT.out yes\n", - " print_level = 4 yes\n", - " print_user_options = yes yes\n", - " sb = yes yes\n", - " tol = 0.001 yes\n", - "Total number of variables............................: 82\n", - " variables with only lower bounds: 0\n", - " variables with lower and upper bounds: 82\n", - " variables with only upper bounds: 0\n", - "Total number of equality constraints.................: 79\n", - "Total number of inequality constraints...............: 4\n", - " inequality constraints with only lower bounds: 4\n", - " inequality constraints with lower and upper bounds: 0\n", - " inequality constraints with only upper bounds: 0\n", - "\n", - "\n", - "Number of Iterations....: 25\n", - "\n", - " (scaled) (unscaled)\n", - "Objective...............: 9.4146770609913695e+00 9.4146770609913695e+00\n", - "Dual infeasibility......: 1.0999629934911812e-08 1.0999629934911812e-08\n", - "Constraint violation....: 3.2276147976517677e-08 3.2276147976517677e-08\n", - "Variable bound violation: 0.0000000000000000e+00 0.0000000000000000e+00\n", - "Complementarity.........: 1.2325706634551805e-06 1.2325706634551805e-06\n", - "Overall NLP error.......: 1.2325706634551805e-06 1.2325706634551805e-06\n", - "\n", - "\n", - "Number of objective function evaluations = 28\n", - "Number of objective gradient evaluations = 26\n", - "Number of equality constraint evaluations = 28\n", - "Number of inequality constraint evaluations = 28\n", - "Number of equality constraint Jacobian evaluations = 26\n", - "Number of inequality constraint Jacobian evaluations = 26\n", - "Number of Lagrangian Hessian evaluations = 0\n", - "Total seconds in IPOPT = 13.774\n", - "\n", - "EXIT: Optimal Solution Found.\n", - "\n", - "\n", - "Optimization Problem -- Optimization using pyOpt_sparse\n", - "================================================================================\n", - " Objective Function: _objfunc\n", - "\n", - " Solution: \n", - "--------------------------------------------------------------------------------\n", - " Total Time: 13.7775\n", - " User Objective Time : 9.9599\n", - " User Sensitivity Time : 3.6817\n", - " Interface Time : 0.0666\n", - " Opt Solver Time: 0.0694\n", - " Calls to Objective Function : 28\n", - " Calls to Sens Function : 26\n", - "\n", - "\n", - " Objectives\n", - " Index Name Value\n", - " 0 reg_objective 9.414677E+00\n", - "\n", - " Variables (c - continuous, i - integer, d - discrete)\n", - " Index Name Type Lower Bound Value Upper Bound Status\n", - " 0 mission:design:gross_mass_0 c 7.407407E-01 8.607091E-01 1.481481E+00 \n", - " 1 traj.climb.t_duration_0 c 5.000000E-01 5.000003E-01 2.000000E+00 l\n", - " 2 traj.climb.states:mass_0 c 0.000000E+00 5.241266E+00 1.000000E+17 \n", - " 3 traj.climb.states:mass_1 c 0.000000E+00 5.237291E+00 1.000000E+17 \n", - " 4 traj.climb.states:mass_2 c 0.000000E+00 5.236091E+00 1.000000E+17 \n", - " 5 traj.climb.states:mass_3 c 0.000000E+00 5.230548E+00 1.000000E+17 \n", - " 6 traj.climb.states:mass_4 c 0.000000E+00 5.223489E+00 1.000000E+17 \n", - " 7 traj.climb.states:mass_5 c 0.000000E+00 5.221338E+00 1.000000E+17 \n", - " 8 traj.climb.states:mass_6 c 0.000000E+00 5.215137E+00 1.000000E+17 \n", - " 9 traj.climb.states:mass_7 c 0.000000E+00 5.206956E+00 1.000000E+17 \n", - " 10 traj.climb.states:mass_8 c 0.000000E+00 5.204440E+00 1.000000E+17 \n", - " 11 traj.climb.states:mass_9 c 0.000000E+00 5.198692E+00 1.000000E+17 \n", - " 12 traj.climb.states:mass_10 c 0.000000E+00 5.190826E+00 1.000000E+17 \n", - " 13 traj.climb.states:mass_11 c 0.000000E+00 5.188345E+00 1.000000E+17 \n", - " 14 traj.climb.states:mass_12 c 0.000000E+00 5.183981E+00 1.000000E+17 \n", - " 15 traj.climb.states:mass_13 c 0.000000E+00 5.177987E+00 1.000000E+17 \n", - " 16 traj.climb.states:mass_14 c 0.000000E+00 5.176097E+00 1.000000E+17 \n", - " 17 traj.climb.states:mass_15 c 0.000000E+00 5.174062E+00 1.000000E+17 \n", - " 18 traj.climb.states:mass_16 c 0.000000E+00 5.171248E+00 1.000000E+17 \n", - " 19 traj.climb.states:mass_17 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", - " 20 traj.climb.states:distance_0 c 0.000000E+00 2.764851E-03 1.000000E+15 \n", - " 21 traj.climb.states:distance_1 c 0.000000E+00 5.071419E-03 1.000000E+15 \n", - " 22 traj.climb.states:distance_2 c 0.000000E+00 5.851859E-03 1.000000E+15 \n", - " 23 traj.climb.states:distance_3 c 0.000000E+00 9.998326E-03 1.000000E+15 \n", - " 24 traj.climb.states:distance_4 c 0.000000E+00 1.663641E-02 1.000000E+15 \n", - " 25 traj.climb.states:distance_5 c 0.000000E+00 1.895456E-02 1.000000E+15 \n", - " 26 traj.climb.states:distance_6 c 0.000000E+00 2.644512E-02 1.000000E+15 \n", - " 27 traj.climb.states:distance_7 c 0.000000E+00 3.822814E-02 1.000000E+15 \n", - " 28 traj.climb.states:distance_8 c 0.000000E+00 4.229839E-02 1.000000E+15 \n", - " 29 traj.climb.states:distance_9 c 0.000000E+00 5.222057E-02 1.000000E+15 \n", - " 30 traj.climb.states:distance_10 c 0.000000E+00 6.724973E-02 1.000000E+15 \n", - " 31 traj.climb.states:distance_11 c 0.000000E+00 7.232091E-02 1.000000E+15 \n", - " 32 traj.climb.states:distance_12 c 0.000000E+00 8.163066E-02 1.000000E+15 \n", - " 33 traj.climb.states:distance_13 c 0.000000E+00 9.521093E-02 1.000000E+15 \n", - " 34 traj.climb.states:distance_14 c 0.000000E+00 9.968231E-02 1.000000E+15 \n", - " 35 traj.climb.states:distance_15 c 0.000000E+00 1.045838E-01 1.000000E+15 \n", - " 36 traj.climb.states:distance_16 c 0.000000E+00 1.114998E-01 1.000000E+15 \n", - " 37 traj.climb.states:distance_17 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", - " 38 traj.cruise.t_initial_0 c 7.260000E+02 8.460004E+02 2.904000E+03 \n", - " 39 traj.cruise.t_duration_0 c 5.000000E-01 5.000000E-01 2.000000E+00 l\n", - " 40 traj.cruise.states:mass_0 c 0.000000E+00 5.170354E+00 1.000000E+17 \n", - " 41 traj.cruise.states:mass_1 c 0.000000E+00 5.005025E+00 1.000000E+17 \n", - " 42 traj.cruise.states:mass_2 c 0.000000E+00 4.780360E+00 1.000000E+17 \n", - " 43 traj.cruise.states:mass_3 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", - " 44 traj.cruise.states:distance_0 c 0.000000E+00 1.137251E-01 1.000000E+15 \n", - " 45 traj.cruise.states:distance_1 c 0.000000E+00 1.127228E+00 1.000000E+15 \n", - " 46 traj.cruise.states:distance_2 c 0.000000E+00 2.525655E+00 1.000000E+15 \n", - " 47 traj.cruise.states:distance_3 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", - " 48 traj.descent.t_initial_0 c 1.291140E+04 1.303140E+04 5.164560E+04 \n", - " 49 traj.descent.t_duration_0 c 5.000000E-01 5.000011E-01 2.000000E+00 \n", - " 50 traj.descent.states:mass_0 c 0.000000E+00 4.710045E+00 1.000000E+17 \n", - " 51 traj.descent.states:mass_1 c 0.000000E+00 4.710502E+00 1.000000E+17 \n", - " 52 traj.descent.states:mass_2 c 0.000000E+00 4.711242E+00 1.000000E+17 \n", - " 53 traj.descent.states:mass_3 c 0.000000E+00 4.711494E+00 1.000000E+17 \n", - " 54 traj.descent.states:mass_4 c 0.000000E+00 4.712779E+00 1.000000E+17 \n", - " 55 traj.descent.states:mass_5 c 0.000000E+00 4.714841E+00 1.000000E+17 \n", - " 56 traj.descent.states:mass_6 c 0.000000E+00 4.715567E+00 1.000000E+17 \n", - " 57 traj.descent.states:mass_7 c 0.000000E+00 4.717767E+00 1.000000E+17 \n", - " 58 traj.descent.states:mass_8 c 0.000000E+00 4.721139E+00 1.000000E+17 \n", - " 59 traj.descent.states:mass_9 c 0.000000E+00 4.722228E+00 1.000000E+17 \n", - " 60 traj.descent.states:mass_10 c 0.000000E+00 4.723686E+00 1.000000E+17 \n", - " 61 traj.descent.states:mass_11 c 0.000000E+00 4.725431E+00 1.000000E+17 \n", - " 62 traj.descent.states:mass_12 c 0.000000E+00 4.726157E+00 1.000000E+17 \n", - " 63 traj.descent.states:mass_13 c 0.000000E+00 4.726963E+00 1.000000E+17 \n", - " 64 traj.descent.states:mass_14 c 0.000000E+00 4.728154E+00 1.000000E+17 \n", - " 65 traj.descent.states:mass_15 c 0.000000E+00 4.728551E+00 1.000000E+17 \n", - " 66 traj.descent.states:distance_0 c 0.000000E+00 2.968252E+00 1.000000E+15 \n", - " 67 traj.descent.states:distance_1 c 0.000000E+00 2.976728E+00 1.000000E+15 \n", - " 68 traj.descent.states:distance_2 c 0.000000E+00 2.988146E+00 1.000000E+15 \n", - " 69 traj.descent.states:distance_3 c 0.000000E+00 2.991691E+00 1.000000E+15 \n", - " 70 traj.descent.states:distance_4 c 0.000000E+00 3.007825E+00 1.000000E+15 \n", - " 71 traj.descent.states:distance_5 c 0.000000E+00 3.028841E+00 1.000000E+15 \n", - " 72 traj.descent.states:distance_6 c 0.000000E+00 3.035182E+00 1.000000E+15 \n", - " 73 traj.descent.states:distance_7 c 0.000000E+00 3.051662E+00 1.000000E+15 \n", - " 74 traj.descent.states:distance_8 c 0.000000E+00 3.072458E+00 1.000000E+15 \n", - " 75 traj.descent.states:distance_9 c 0.000000E+00 3.078555E+00 1.000000E+15 \n", - " 76 traj.descent.states:distance_10 c 0.000000E+00 3.089619E+00 1.000000E+15 \n", - " 77 traj.descent.states:distance_11 c 0.000000E+00 3.103383E+00 1.000000E+15 \n", - " 78 traj.descent.states:distance_12 c 0.000000E+00 3.107367E+00 1.000000E+15 \n", - " 79 traj.descent.states:distance_13 c 0.000000E+00 3.111617E+00 1.000000E+15 \n", - " 80 traj.descent.states:distance_14 c 0.000000E+00 3.117100E+00 1.000000E+15 \n", - " 81 traj.descent.states:distance_15 c 0.000000E+00 3.118742E+00 1.000000E+15 \n", - "\n", - " Constraints (i - inequality, e - equality)\n", - " Index Name Type Lower Value Upper Status Lagrange Multiplier (N/A)\n", - " 0 mass_resid e 0.000000E+00 -3.227615E-08 0.000000E+00 9.00000E+100\n", - " 1 traj.linkages.climb:time_final|cruise:time_initial e 0.000000E+00 1.136868E-13 0.000000E+00 9.00000E+100\n", - " 2 traj.linkages.climb:mass_final|cruise:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", - " 3 traj.linkages.climb:distance_final|cruise:distance_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", - " 4 traj.linkages.cruise:time_final|descent:time_initial e 0.000000E+00 -1.818989E-12 0.000000E+00 9.00000E+100\n", - " 5 traj.linkages.cruise:mass_final|descent:mass_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", - " 6 traj.linkages.cruise:distance_final|descent:distance_initial e 0.000000E+00 0.000000E+00 0.000000E+00 9.00000E+100\n", - " 7 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.025097E-14 0.000000E+00 9.00000E+100\n", - " 8 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.860766E-14 0.000000E+00 9.00000E+100\n", - " 9 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.699134E-14 0.000000E+00 9.00000E+100\n", - " 10 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.485284E-14 0.000000E+00 9.00000E+100\n", - " 11 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.003003E-14 0.000000E+00 9.00000E+100\n", - " 12 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.531926E-14 0.000000E+00 9.00000E+100\n", - " 13 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 3.113611E-14 0.000000E+00 9.00000E+100\n", - " 14 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.886567E-14 0.000000E+00 9.00000E+100\n", - " 15 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.598810E-14 0.000000E+00 9.00000E+100\n", - " 16 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.408043E-14 0.000000E+00 9.00000E+100\n", - " 17 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.173824E-14 0.000000E+00 9.00000E+100\n", - " 18 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 2.099713E-14 0.000000E+00 9.00000E+100\n", - " 19 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.608025E-14 0.000000E+00 9.00000E+100\n", - " 20 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.587637E-14 0.000000E+00 9.00000E+100\n", - " 21 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 1.558807E-14 0.000000E+00 9.00000E+100\n", - " 22 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.279583E-15 0.000000E+00 9.00000E+100\n", - " 23 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.206002E-15 0.000000E+00 9.00000E+100\n", - " 24 traj.climb.collocation_constraint.defects:mass e 0.000000E+00 7.240740E-15 0.000000E+00 9.00000E+100\n", - " 25 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.162790E-14 0.000000E+00 9.00000E+100\n", - " 26 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.105201E-14 0.000000E+00 9.00000E+100\n", - " 27 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.002517E-14 0.000000E+00 9.00000E+100\n", - " 28 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 2.058287E-14 0.000000E+00 9.00000E+100\n", - " 29 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.782458E-14 0.000000E+00 9.00000E+100\n", - " 30 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.511325E-14 0.000000E+00 9.00000E+100\n", - " 31 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.872588E-14 0.000000E+00 9.00000E+100\n", - " 32 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.655588E-14 0.000000E+00 9.00000E+100\n", - " 33 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.434107E-14 0.000000E+00 9.00000E+100\n", - " 34 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.377297E-14 0.000000E+00 9.00000E+100\n", - " 35 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.265000E-14 0.000000E+00 9.00000E+100\n", - " 36 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 1.141126E-14 0.000000E+00 9.00000E+100\n", - " 37 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 8.538640E-15 0.000000E+00 9.00000E+100\n", - " 38 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 8.126975E-15 0.000000E+00 9.00000E+100\n", - " 39 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 7.635711E-15 0.000000E+00 9.00000E+100\n", - " 40 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.521029E-15 0.000000E+00 9.00000E+100\n", - " 41 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.453567E-15 0.000000E+00 9.00000E+100\n", - " 42 traj.climb.collocation_constraint.defects:distance e 0.000000E+00 3.366714E-15 0.000000E+00 9.00000E+100\n", - " 43 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 5.312109E-13 0.000000E+00 9.00000E+100\n", - " 44 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 4.063769E-13 0.000000E+00 9.00000E+100\n", - " 45 traj.cruise.collocation_constraint.defects:mass e 0.000000E+00 2.575362E-13 0.000000E+00 9.00000E+100\n", - " 46 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", - " 47 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 3.463299E-18 0.000000E+00 9.00000E+100\n", - " 48 traj.cruise.collocation_constraint.defects:distance e 0.000000E+00 -6.926598E-18 0.000000E+00 9.00000E+100\n", - " 49 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.910022E-14 0.000000E+00 9.00000E+100\n", - " 50 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.529124E-14 0.000000E+00 9.00000E+100\n", - " 51 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.342543E-14 0.000000E+00 9.00000E+100\n", - " 52 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 6.585307E-14 0.000000E+00 9.00000E+100\n", - " 53 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.552915E-14 0.000000E+00 9.00000E+100\n", - " 54 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.341976E-14 0.000000E+00 9.00000E+100\n", - " 55 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.791654E-14 0.000000E+00 9.00000E+100\n", - " 56 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.929329E-14 0.000000E+00 9.00000E+100\n", - " 57 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 3.075605E-14 0.000000E+00 9.00000E+100\n", - " 58 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 2.145444E-14 0.000000E+00 9.00000E+100\n", - " 59 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 1.435837E-14 0.000000E+00 9.00000E+100\n", - " 60 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 9.991150E-15 0.000000E+00 9.00000E+100\n", - " 61 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.078937E-15 0.000000E+00 9.00000E+100\n", - " 62 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 5.142482E-15 0.000000E+00 9.00000E+100\n", - " 63 traj.descent.collocation_constraint.defects:mass e 0.000000E+00 4.257099E-15 0.000000E+00 9.00000E+100\n", - " 64 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.438287E-14 0.000000E+00 9.00000E+100\n", - " 65 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.567239E-14 0.000000E+00 9.00000E+100\n", - " 66 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 6.757017E-14 0.000000E+00 9.00000E+100\n", - " 67 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.393325E-13 0.000000E+00 9.00000E+100\n", - " 68 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.459218E-13 0.000000E+00 9.00000E+100\n", - " 69 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.566014E-13 0.000000E+00 9.00000E+100\n", - " 70 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.907169E-13 0.000000E+00 9.00000E+100\n", - " 71 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.047396E-13 0.000000E+00 9.00000E+100\n", - " 72 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.289513E-13 0.000000E+00 9.00000E+100\n", - " 73 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.003578E-13 0.000000E+00 9.00000E+100\n", - " 74 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.175539E-13 0.000000E+00 9.00000E+100\n", - " 75 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 2.479632E-13 0.000000E+00 9.00000E+100\n", - " 76 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.271784E-13 0.000000E+00 9.00000E+100\n", - " 77 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.344334E-13 0.000000E+00 9.00000E+100\n", - " 78 traj.descent.collocation_constraint.defects:distance e 0.000000E+00 1.461002E-13 0.000000E+00 9.00000E+100\n", - " 79 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.127272E+02 1.000000E+30 9.00000E+100\n", - " 80 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 7.752630E+02 1.000000E+30 9.00000E+100\n", - " 81 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.643321E+02 1.000000E+30 9.00000E+100\n", - " 82 traj.phases.cruise->path_constraint->altitude_rate_max i 3.000000E+02 8.932716E+02 1.000000E+30 9.00000E+100\n", - "\n", - "\n", - " Exit Status\n", - " Inform Description\n", - " 0 Solve Succeeded\n", - "--------------------------------------------------------------------------------\n", - "\n", - "-------------------------------\n", - "times_climb: [846.00038137] (s)\n", - "altitudes_climb: [10668.] (m)\n", - "masses_climb: [51703.54384226] (kg)\n", - "ranges_climb: [113725.11889636] (m)\n", - "velocities_climb: [234.25795132] (m/s)\n", - "thrusts_climb: [71713.80312354] (N)\n", - "times_cruise: [13031.40073487] (s)\n", - "altitudes_cruise: [10668.] (m)\n", - "masses_cruise: [47100.44512976] (kg)\n", - "ranges_cruise: [2968252.0417268] (m)\n", - "velocities_cruise: [234.25795132] (m/s)\n", - "thrusts_cruise: [26338.70498784] (N)\n", - "times_descent: [13908.60273889] (s)\n", - "altitudes_descent: [10.668] (m)\n", - "masses_descent: [47285.51458051] (kg)\n", - "ranges_descent: [3118741.8185247] (m)\n", - "velocities_descent: [102.07377559] (m/s)\n", - "thrusts_descent: [-43173.10618655] (N)\n", - "-------------------------------\n" - ] - } - ], + "outputs": [], "source": [ "'''\n", "NOTES:\n", @@ -880,7 +520,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "52550a27", "metadata": {}, "outputs": [], diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 5baca4d89..9ed57fff1 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -25,88 +25,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_deck.py:198: UserWarning: is a required option for EngineDecks, but has not been specified for EngineDeck . The default value will be used.\n", - " warnings.warn(\n", - "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", - " warnings.warn(\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "The following variables have been overridden:\n", - " 'aircraft:design:touchdown_mass\n", - " 'aircraft:engine:mass\n", - " 'aircraft:fins:mass\n", - " 'aircraft:fuel:auxiliary_fuel_capacity\n", - " 'aircraft:fuel:fuselage_fuel_capacity\n", - " 'aircraft:fuel:total_capacity\n", - " 'aircraft:fuselage:planform_area\n", - " 'aircraft:fuselage:wetted_area\n", - " 'aircraft:horizontal_tail:wetted_area\n", - " 'aircraft:landing_gear:main_gear_oleo_length\n", - " 'aircraft:landing_gear:nose_gear_oleo_length\n", - " 'aircraft:vertical_tail:wetted_area\n", - " 'aircraft:wing:aspect_ratio\n", - " 'aircraft:wing:control_surface_area\n", - " 'aircraft:wing:wetted_area\n", - "\n", - "--- Constraint Report [traj] ---\n", - " --- climb ---\n", - " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " --- cruise ---\n", - " [initial] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " [final] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " --- descent ---\n", - " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, dymos_solution.db, is being overwritten.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model viewer data has already been recorded for Driver.\n", - "Full total jacobian was computed 3 times, taking 0.589048 seconds.\n", - "Total jacobian shape: (135, 94) \n", - "\n", - "\n", - "Jacobian shape: (135, 94) (13.71% nonzero)\n", - "FWD solves: 22 REV solves: 0\n", - "Total colors vs. total size: 22 vs 94 (76.60% improvement)\n", - "\n", - "Sparsity computed using tolerance: 1e-25\n", - "Time to compute sparsity: 0.5890 sec\n", - "Time to compute coloring: 0.0720 sec\n", - "Memory to compute coloring: 0.1992 MB\n", - "Coloring created on: 2024-01-18 18:19:34\n", - "Iteration limit reached (Exit mode 9)\n", - " Current function value: 0.0\n", - " Iterations: 1\n", - " Function evaluations: 1\n", - " Gradient evaluations: 1\n", - "Optimization FAILED.\n", - "Iteration limit reached\n", - "-----------------------------------\n" - ] - } - ], + "outputs": [], "source": [ "import aviary.api as av\n", "\n", @@ -129,96 +50,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", - " warnings.warn(\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "The following variables have been overridden:\n", - " 'aircraft:design:touchdown_mass\n", - " 'aircraft:engine:mass\n", - " 'aircraft:fins:mass\n", - " 'aircraft:fuel:auxiliary_fuel_capacity\n", - " 'aircraft:fuel:fuselage_fuel_capacity\n", - " 'aircraft:fuel:total_capacity\n", - " 'aircraft:fuselage:planform_area\n", - " 'aircraft:fuselage:wetted_area\n", - " 'aircraft:horizontal_tail:wetted_area\n", - " 'aircraft:landing_gear:main_gear_oleo_length\n", - " 'aircraft:landing_gear:nose_gear_oleo_length\n", - " 'aircraft:vertical_tail:wetted_area\n", - " 'aircraft:wing:aspect_ratio\n", - " 'aircraft:wing:control_surface_area\n", - " 'aircraft:wing:wetted_area\n", - "\n", - "--- Constraint Report [traj] ---\n", - " --- climb ---\n", - " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " --- cruise ---\n", - " [initial] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " [final] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - " --- descent ---\n", - " [path] 0.0000e+00 <= throttle <= 1.0000e+00 [unitless]\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py:227: UserWarning:The existing case recorder file, level2_example.db, is being overwritten.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Model viewer data has already been recorded for Driver.\n", - "Full total jacobian was computed 3 times, taking 0.528602 seconds.\n", - "Total jacobian shape: (135, 94) \n", - "\n", - "\n", - "Jacobian shape: (135, 94) (13.52% nonzero)\n", - "FWD solves: 21 REV solves: 0\n", - "Total colors vs. total size: 21 vs 94 (77.66% improvement)\n", - "\n", - "Sparsity computed using tolerance: 1e-25\n", - "Time to compute sparsity: 0.5286 sec\n", - "Time to compute coloring: 0.0755 sec\n", - "Memory to compute coloring: 0.0000 MB\n", - "Coloring created on: 2024-01-18 18:19:51\n", - "Iteration limit reached (Exit mode 9)\n", - " Current function value: -0.7956010169800001\n", - " Iterations: 1\n", - " Function evaluations: 1\n", - " Gradient evaluations: 1\n", - "Optimization FAILED.\n", - "Iteration limit reached\n", - "-----------------------------------\n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import aviary.api as av\n", "\n", @@ -349,110 +183,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/mnt/c/Users/John/Dropbox/git/om-aviary/aviary/subsystems/propulsion/engine_model.py:131: UserWarning: The value of aircraft:engine:wing_locations passed to EngineModel is type . Only the first entry in this iterable will be used.\n", - " warnings.warn(\n", - "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'climb': lower, upper, ref\n", - " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", - "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'climb': lower, upper, ref\n", - " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", - "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'mach' in phase 'descent': lower, upper, ref\n", - " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", - "/mnt/c/Users/John/Dropbox/git/Dymos/dymos/phase/phase.py:2225: RuntimeWarning: Invalid options for non-optimal control 'altitude' in phase 'descent': lower, upper, ref\n", - " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.canard' : input variable 'aircraft:canard:wetted_area_scaler', promoted using 'aircraft:canard:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:area', promoted using 'aircraft:canard:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:aspect_ratio', promoted using 'aircraft:canard:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:canard:thickness_to_chord', promoted using 'aircraft:canard:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:aspect_ratio', promoted using 'aircraft:horizontal_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:aspect_ratio', promoted using 'aircraft:vertical_tail:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:taper_ratio', promoted using 'aircraft:wing:taper_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.characteristic_lengths' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:avg_diameter', promoted using 'aircraft:fuselage:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:length', promoted using 'aircraft:fuselage:length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:fuselage:wetted_area_scaler', promoted using 'aircraft:fuselage:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:thickness_to_chord', promoted using 'aircraft:horizontal_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:vertical_tail:thickness_to_chord', promoted using 'aircraft:vertical_tail:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:aspect_ratio', promoted using 'aircraft:wing:aspect_ratio', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:glove_and_bat', promoted using 'aircraft:wing:glove_and_bat', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.fuselage' : input variable 'aircraft:wing:thickness_to_chord', promoted using 'aircraft:wing:thickness_to_chord', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_diameter', promoted using 'aircraft:nacelle:avg_diameter', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:avg_length', promoted using 'aircraft:nacelle:avg_length', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.nacelles' : input variable 'aircraft:nacelle:wetted_area_scaler', promoted using 'aircraft:nacelle:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:area', promoted using 'aircraft:horizontal_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:vertical_tail_fraction', promoted using 'aircraft:horizontal_tail:vertical_tail_fraction', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:horizontal_tail:wetted_area_scaler', promoted using 'aircraft:horizontal_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:area', promoted using 'aircraft:vertical_tail:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.tail' : input variable 'aircraft:vertical_tail:wetted_area_scaler', promoted using 'aircraft:vertical_tail:wetted_area_scaler', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:area', promoted using 'aircraft:wing:area', was already promoted using 'aircraft*'.\n", - "/mnt/c/Users/John/Dropbox/git/OpenMDAO/openmdao/core/system.py:2431: PromotionWarning:'pre_mission.core_geometry.wing' : input variable 'aircraft:wing:wetted_area_scaler', promoted using 'aircraft:wing:wetted_area_scaler', was already promoted using 'aircraft*'.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "The following variables have been overridden:\n", - " 'aircraft:design:touchdown_mass\n", - " 'aircraft:engine:mass\n", - " 'aircraft:fins:mass\n", - " 'aircraft:fuel:auxiliary_fuel_capacity\n", - " 'aircraft:fuel:fuselage_fuel_capacity\n", - " 'aircraft:fuel:total_capacity\n", - " 'aircraft:fuselage:planform_area\n", - " 'aircraft:fuselage:wetted_area\n", - " 'aircraft:horizontal_tail:wetted_area\n", - " 'aircraft:landing_gear:main_gear_oleo_length\n", - " 'aircraft:landing_gear:nose_gear_oleo_length\n", - " 'aircraft:vertical_tail:wetted_area\n", - " 'aircraft:wing:aspect_ratio\n", - " 'aircraft:wing:control_surface_area\n", - " 'aircraft:wing:wetted_area\n", - "\n", - "--- Constraint Report [traj] ---\n", - " --- climb ---\n", - " None\n", - " --- cruise ---\n", - " [path] 3.0000e+02 <= altitude_rate_max [ft/min]\n", - " --- descent ---\n", - " None\n", - "\n" - ] - }, - { - "ename": "AttributeError", - "evalue": "type object 'Mission' has no attribute 'RANGE'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[6], line 237\u001b[0m\n\u001b[1;32m 231\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\n\u001b[1;32m 232\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.controls:mach\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[1;32m 233\u001b[0m av\u001b[38;5;241m.\u001b[39mDynamic\u001b[38;5;241m.\u001b[39mMission\u001b[38;5;241m.\u001b[39mMACH, ys\u001b[38;5;241m=\u001b[39m[mach_i_climb, mach_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124munitless\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 234\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.states:mass\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[1;32m 235\u001b[0m av\u001b[38;5;241m.\u001b[39mDynamic\u001b[38;5;241m.\u001b[39mMission\u001b[38;5;241m.\u001b[39mMASS, ys\u001b[38;5;241m=\u001b[39m[mass_i_climb, mass_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mkg\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 236\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.climb.states:distance\u001b[39m\u001b[38;5;124m'\u001b[39m, climb\u001b[38;5;241m.\u001b[39minterp(\n\u001b[0;32m--> 237\u001b[0m \u001b[43mav\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mDynamic\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mMission\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mRANGE\u001b[49m, ys\u001b[38;5;241m=\u001b[39m[distance_i_climb, distance_f_climb]), units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mm\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 239\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.cruise.t_initial\u001b[39m\u001b[38;5;124m'\u001b[39m, t_i_cruise, units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 240\u001b[0m prob\u001b[38;5;241m.\u001b[39mset_val(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtraj.cruise.t_duration\u001b[39m\u001b[38;5;124m'\u001b[39m, t_duration_cruise, units\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", - "\u001b[0;31mAttributeError\u001b[0m: type object 'Mission' has no attribute 'RANGE'" - ] - } - ], + "outputs": [], "source": [ "import dymos as dm\n", "import openmdao.api as om\n", @@ -724,13 +457,6 @@ "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9})" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { From 6c0c33740232eecbce49ed0e3533ddb0b9b5a6b0 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Thu, 18 Jan 2024 18:42:01 -0600 Subject: [PATCH 083/111] Feedback based on PR --- aviary/interface/methods_for_level2.py | 4 +-- .../interface/test/test_check_phase_info.py | 18 +++++++----- aviary/mission/flops_based/ode/mission_EOM.py | 2 +- aviary/mission/flops_based/ode/mission_ODE.py | 7 +++-- .../flops_based/ode/required_thrust.py | 29 ++++++++++--------- .../flops_based/ode/simple_mission_EOM.py | 2 +- .../flops_based/ode/simple_mission_ODE.py | 4 +-- .../benchmark_tests/test_0_iters.py | 6 ++-- aviary/variable_info/enums.py | 3 +- 9 files changed, 39 insertions(+), 36 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 1e40b3ba9..eec2e2f97 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -691,7 +691,7 @@ def _add_groundroll_eq_constraint(self, phase): promotes_inputs=["t_init_gear", "t_init_flaps"], ) - def _get_simple_phase(self, phase_name, phase_idx): + def _get_height_energy_phase(self, phase_name, phase_idx): base_phase_options = self.phase_info[phase_name] fix_duration = base_phase_options['user_options']['fix_duration'] @@ -1053,7 +1053,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): elif self.mission_method is HEIGHT_ENERGY: for phase_idx, phase_name in enumerate(phases): phase = traj.add_phase( - phase_name, self._get_simple_phase(phase_name, phase_idx)) + phase_name, self._get_height_energy_phase(phase_name, phase_idx)) add_subsystem_timeseries_outputs(phase, phase_name) # loop through phase_info and external subsystems diff --git a/aviary/interface/test/test_check_phase_info.py b/aviary/interface/test/test_check_phase_info.py index 56774258a..9e18ca521 100644 --- a/aviary/interface/test/test_check_phase_info.py +++ b/aviary/interface/test/test_check_phase_info.py @@ -2,8 +2,8 @@ import copy from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_flops -from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_gasp +from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_height_energy +from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_two_dof from aviary.variable_info.enums import EquationsOfMotion HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY @@ -13,34 +13,36 @@ class TestCheckInputs(unittest.TestCase): def test_correct_input_height_energy(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_flops, mission_method=HEIGHT_ENERGY)) + self.assertTrue(check_phase_info( + phase_info_height_energy, mission_method=HEIGHT_ENERGY)) def test_incorrect_tuple(self): # Let's replace a tuple with a float in the 'climb' phase - incorrect_tuple_phase_info = copy.deepcopy(phase_info_flops) + incorrect_tuple_phase_info = copy.deepcopy(phase_info_height_energy) incorrect_tuple_phase_info['climb']['user_options']['initial_altitude'] = 10.668e3 with self.assertRaises(ValueError): check_phase_info(incorrect_tuple_phase_info, mission_method=HEIGHT_ENERGY) def test_incorrect_unit(self): # Let's replace a valid unit with an invalid one in the 'climb' phase - incorrect_unit_phase_info = copy.deepcopy(phase_info_flops) + incorrect_unit_phase_info = copy.deepcopy(phase_info_height_energy) incorrect_unit_phase_info['climb']['user_options']['initial_altitude'] = ( 10.668e3, 'invalid_unit') with self.assertRaisesRegex(ValueError, "Key initial_altitude in phase climb has an invalid unit invalid_unit."): check_phase_info(incorrect_unit_phase_info, mission_method=HEIGHT_ENERGY) - def test_correct_input_gasp(self): + def test_correct_input_two_dof(self): # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_gasp, + self.assertTrue(check_phase_info(phase_info_two_dof, mission_method=TWO_DEGREES_OF_FREEDOM)) def test_incorrect_mission_method(self): # Let's pass an incorrect mission_method name incorrect_mission_method = 'INVALID_METHOD' with self.assertRaises(ValueError): - check_phase_info(phase_info_flops, mission_method=incorrect_mission_method) + check_phase_info(phase_info_height_energy, + mission_method=incorrect_mission_method) if __name__ == '__main__': diff --git a/aviary/mission/flops_based/ode/mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py index b726d17b6..55bc58889 100644 --- a/aviary/mission/flops_based/ode/mission_EOM.py +++ b/aviary/mission/flops_based/ode/mission_EOM.py @@ -19,7 +19,7 @@ def setup(self): subsys=RequiredThrust(num_nodes=nn), promotes_inputs=[Dynamic.Mission.DRAG, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS], - promotes_outputs=['T_required']) + promotes_outputs=['thrust_required']) self.add_subsystem(name='groundspeed', subsys=RangeRate(num_nodes=nn), diff --git a/aviary/mission/flops_based/ode/mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py index 689df00fc..2a6dcccd4 100644 --- a/aviary/mission/flops_based/ode/mission_ODE.py +++ b/aviary/mission/flops_based/ode/mission_ODE.py @@ -40,7 +40,8 @@ def initialize(self): 'use_actual_takeoff_mass', default=False, desc='flag to use actual takeoff mass in the climb phase, otherwise assume 100 kg fuel burn') self.options.declare( - 'throttle_enforcement', default='path', + 'throttle_enforcement', default='path_constraint', + values=['path_constraint', 'boundary_constraint', 'bounded'], desc='flag to enforce throttle constraints on the path or at the segment boundaries or using solver bounds' ) @@ -149,7 +150,7 @@ def setup(self): Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, Dynamic.Mission.ALTITUDE_RATE_MAX, Dynamic.Mission.DISTANCE_RATE, - 'T_required', + 'thrust_required', ]) # add a balance comp to compute throttle based on the altitude rate @@ -157,7 +158,7 @@ def setup(self): subsys=om.BalanceComp(name=Dynamic.Mission.THROTTLE, units="unitless", val=np.ones(nn), - lhs_name='T_required', + lhs_name='thrust_required', rhs_name=Dynamic.Mission.THRUST_TOTAL, eq_units="lbf", normalize=False, diff --git a/aviary/mission/flops_based/ode/required_thrust.py b/aviary/mission/flops_based/ode/required_thrust.py index 25903ac6d..af3c5ed62 100644 --- a/aviary/mission/flops_based/ode/required_thrust.py +++ b/aviary/mission/flops_based/ode/required_thrust.py @@ -7,7 +7,7 @@ class RequiredThrust(om.ExplicitComponent): """ Computes the required thrust using the equation: - T_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass + thrust_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass """ def initialize(self): @@ -26,17 +26,18 @@ def setup(self): nn), units='m/s**2', desc='rate of change of velocity') self.add_input(Dynamic.Mission.MASS, val=np.zeros( nn), units='kg', desc='mass of the aircraft') - self.add_output('T_required', val=np.zeros( + self.add_output('thrust_required', val=np.zeros( nn), units='N', desc='required thrust') ar = np.arange(nn) - self.declare_partials('T_required', Dynamic.Mission.DRAG, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Mission.DRAG, rows=ar, cols=ar) self.declare_partials( - 'T_required', Dynamic.Mission.ALTITUDE_RATE, rows=ar, cols=ar) - self.declare_partials('T_required', Dynamic.Mission.VELOCITY, rows=ar, cols=ar) + 'thrust_required', Dynamic.Mission.ALTITUDE_RATE, rows=ar, cols=ar) self.declare_partials( - 'T_required', Dynamic.Mission.VELOCITY_RATE, rows=ar, cols=ar) - self.declare_partials('T_required', Dynamic.Mission.MASS, rows=ar, cols=ar) + 'thrust_required', Dynamic.Mission.VELOCITY, rows=ar, cols=ar) + self.declare_partials( + 'thrust_required', Dynamic.Mission.VELOCITY_RATE, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Mission.MASS, rows=ar, cols=ar) def compute(self, inputs, outputs): drag = inputs[Dynamic.Mission.DRAG] @@ -45,9 +46,9 @@ def compute(self, inputs, outputs): velocity_rate = inputs[Dynamic.Mission.VELOCITY_RATE] mass = inputs[Dynamic.Mission.MASS] - T_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass + thrust_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass - outputs['T_required'] = T_required + outputs['thrust_required'] = thrust_required def compute_partials(self, inputs, partials): altitude_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] @@ -55,10 +56,10 @@ def compute_partials(self, inputs, partials): velocity_rate = inputs[Dynamic.Mission.VELOCITY_RATE] mass = inputs[Dynamic.Mission.MASS] - partials['T_required', Dynamic.Mission.DRAG] = 1.0 - partials['T_required', Dynamic.Mission.ALTITUDE_RATE] = gravity/velocity * mass - partials['T_required', Dynamic.Mission.VELOCITY] = - \ + partials['thrust_required', Dynamic.Mission.DRAG] = 1.0 + partials['thrust_required', Dynamic.Mission.ALTITUDE_RATE] = gravity/velocity * mass + partials['thrust_required', Dynamic.Mission.VELOCITY] = - \ altitude_rate*gravity/velocity**2 * mass - partials['T_required', Dynamic.Mission.VELOCITY_RATE] = mass - partials['T_required', Dynamic.Mission.MASS] = altitude_rate * \ + partials['thrust_required', Dynamic.Mission.VELOCITY_RATE] = mass + partials['thrust_required', Dynamic.Mission.MASS] = altitude_rate * \ gravity/velocity + velocity_rate diff --git a/aviary/mission/flops_based/ode/simple_mission_EOM.py b/aviary/mission/flops_based/ode/simple_mission_EOM.py index b726d17b6..55bc58889 100644 --- a/aviary/mission/flops_based/ode/simple_mission_EOM.py +++ b/aviary/mission/flops_based/ode/simple_mission_EOM.py @@ -19,7 +19,7 @@ def setup(self): subsys=RequiredThrust(num_nodes=nn), promotes_inputs=[Dynamic.Mission.DRAG, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS], - promotes_outputs=['T_required']) + promotes_outputs=['thrust_required']) self.add_subsystem(name='groundspeed', subsys=RangeRate(num_nodes=nn), diff --git a/aviary/mission/flops_based/ode/simple_mission_ODE.py b/aviary/mission/flops_based/ode/simple_mission_ODE.py index 0a34ad7ee..beb8016c9 100644 --- a/aviary/mission/flops_based/ode/simple_mission_ODE.py +++ b/aviary/mission/flops_based/ode/simple_mission_ODE.py @@ -149,7 +149,7 @@ def setup(self): Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, Dynamic.Mission.ALTITUDE_RATE_MAX, Dynamic.Mission.DISTANCE_RATE, - 'T_required', + 'thrust_required', ]) # add a balance comp to compute throttle based on the altitude rate @@ -157,7 +157,7 @@ def setup(self): subsys=om.BalanceComp(name=Dynamic.Mission.THROTTLE, units="unitless", val=np.ones(nn), - lhs_name='T_required', + lhs_name='thrust_required', rhs_name=Dynamic.Mission.THRUST_TOTAL, eq_units="lbf", normalize=False, diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 2d58fb26e..c60146b11 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -5,7 +5,7 @@ from aviary.interface.methods_for_level2 import AviaryProblem from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as simple_phase_info +from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info from aviary.variable_info.enums import EquationsOfMotion @@ -45,8 +45,8 @@ def test_gasp_zero_iters(self): class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") - def test_simple_zero_iters(self): - local_phase_info = deepcopy(simple_phase_info) + def test_height_energy_zero_iters(self): + local_phase_info = deepcopy(height_energy_phase_info) self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm.csv', local_phase_info) diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 17e8f102c..7978e4da3 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -57,9 +57,8 @@ class EquationsOfMotion(Enum): """ Available equations of motion for use during mission analysis """ - TWO_DEGREES_OF_FREEDOM = '2DOF' - # TODO these are a little out of place atm HEIGHT_ENERGY = 'height_energy' + TWO_DEGREES_OF_FREEDOM = '2DOF' SOLVED = 'solved' From d83a3fbe31de71e572e43eca76c512bf0eb56f6e Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Fri, 19 Jan 2024 08:35:41 -0500 Subject: [PATCH 084/111] statics XDSM upd to pass spec, climb and descent XDSM upd for clarity --- aviary/xdsm/climb_xdsm.py | 14 +++++++++++++- aviary/xdsm/descent1_xdsm.py | 11 +++++++++++ aviary/xdsm/descent2_xdsm.py | 11 +++++++++++ aviary/xdsm/statics_xdsm.py | 16 ++++++++++++---- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/aviary/xdsm/climb_xdsm.py b/aviary/xdsm/climb_xdsm.py index 764ad79ca..cd775b221 100644 --- a/aviary/xdsm/climb_xdsm.py +++ b/aviary/xdsm/climb_xdsm.py @@ -19,6 +19,8 @@ x.add_system("eom", GROUP, [r"\textbf{ClimbEOM}"]) x.add_system("balance_lift", IFUNC, ["BalanceLift"]) x.add_system("constraints", FUNC, [r"\textbf{Constraints}"]) +x.add_system('specific_energy', FUNC, ["specific_energy"]) +x.add_system('alt_rate', FUNC, ["alt_rate"]) # create inputs x.add_input("speeds", [Dynamic.Mission.MACH]) @@ -49,8 +51,10 @@ Aircraft.Engine.SCALE_FACTOR, ]) x.add_input("eom", [Dynamic.Mission.MASS]) +x.add_input("specific_energy", [Dynamic.Mission.MASS]) +x.add_input("alt_rate", ["TAS_rate"]) -# make connections +# make connections6 x.connect("atmos", "fc", ["rho", Dynamic.Mission.SPEED_OF_SOUND]) # x.connect("atmos", "prop", [Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE]) x.connect("atmos", "constraints", ["rho"]) @@ -71,6 +75,12 @@ x.connect("eom", "balance_lift", ["required_lift"]) x.connect("balance_lift", "constraints", ["alpha"]) x.connect("balance_lift", "aero", ["alpha"]) +x.connect("fc", "specific_energy", ["TAS"]) +x.connect("aero", "specific_energy", [Dynamic.Mission.DRAG]) +x.connect("prop", "specific_energy", [Dynamic.Mission.THRUST_MAX_TOTAL]) +x.connect("specific_energy", "alt_rate", [Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS]) +x.connect("fc", "alt_rate", ["TAS"]) + # create outputs x.add_output("eom", [ @@ -86,5 +96,7 @@ "CL_max", ], side="right") +x.add_output("alt_rate", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") + x.write("climb_xdsm") x.write_sys_specs("climb_specs") diff --git a/aviary/xdsm/descent1_xdsm.py b/aviary/xdsm/descent1_xdsm.py index 74e3b0f02..a405f9b93 100644 --- a/aviary/xdsm/descent1_xdsm.py +++ b/aviary/xdsm/descent1_xdsm.py @@ -19,6 +19,8 @@ x.add_system("balance_lift", FUNC, ["BalanceLift"]) x.add_system("aero", IGROUP, ["CruiseAero", "(alpha~in)"]) x.add_system("pitch", FUNC, ["Constraints"]) +x.add_system('specific_energy', FUNC, ["specific_energy"]) +x.add_system('alt_rate', FUNC, ["alt_rate"]) # create inputs # x.add_input("fc", [Dynamic.Mission.MACH]) @@ -37,6 +39,8 @@ Aircraft.Wing.AREA, Aircraft.Wing.INCIDENCE, ]) +x.add_input("specific_energy", [Dynamic.Mission.MASS]) +x.add_input("alt_rate", ["TAS_rate"]) # make connections x.connect("atmos", "fc", ["rho", Dynamic.Mission.SPEED_OF_SOUND]) @@ -62,6 +66,11 @@ x.connect("aero", "eom", [Dynamic.Mission.DRAG]) x.connect("aero", "pitch", ["CL_max"]) x.connect("aero", "balance_lift", [Dynamic.Mission.LIFT]) +x.connect("fc", "specific_energy", ["TAS"]) +x.connect("aero", "specific_energy", [Dynamic.Mission.DRAG]) +x.connect("prop", "specific_energy", [Dynamic.Mission.THRUST_MAX_TOTAL]) +x.connect("specific_energy", "alt_rate", [Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS]) +x.connect("fc", "alt_rate", ["TAS"]) # create outputs x.add_output("eom", [ @@ -70,5 +79,7 @@ "required_lift" ], side="right") +x.add_output("alt_rate", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") + x.write("descent1_xdsm") x.write_sys_specs("descent1_specs") diff --git a/aviary/xdsm/descent2_xdsm.py b/aviary/xdsm/descent2_xdsm.py index 20ba3f889..f23e9cd45 100644 --- a/aviary/xdsm/descent2_xdsm.py +++ b/aviary/xdsm/descent2_xdsm.py @@ -13,6 +13,8 @@ x.add_system("balance_lift", FUNC, ["BalanceLift"]) x.add_system("aero", IGROUP, ["CruiseAero", "(alpha~in)"]) x.add_system("pitch", FUNC, ["Constraints"]) +x.add_system('specific_energy', FUNC, ["specific_energy"]) +x.add_system('alt_rate', FUNC, ["alt_rate"]) # create inputs # x.add_input("fc", ["EAS"]) @@ -29,6 +31,8 @@ Aircraft.Wing.AREA, Aircraft.Wing.INCIDENCE, ]) +x.add_input("specific_energy", [Dynamic.Mission.MASS]) +x.add_input("alt_rate", ["TAS_rate"]) # make connections x.add_input("fc", ["EAS"]) @@ -50,6 +54,11 @@ x.connect("aero", "eom", [Dynamic.Mission.DRAG]) x.connect("aero", "pitch", ["CL_max"]) x.connect("aero", "balance_lift", [Dynamic.Mission.LIFT]) +x.connect("fc", "specific_energy", ["TAS"]) +x.connect("aero", "specific_energy", [Dynamic.Mission.DRAG]) +x.connect("prop", "specific_energy", [Dynamic.Mission.THRUST_MAX_TOTAL]) +x.connect("specific_energy", "alt_rate", [Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS]) +x.connect("fc", "alt_rate", ["TAS"]) # create outputs x.add_output("eom", [ @@ -58,5 +67,7 @@ "required_lift" ], side="right") +x.add_output("alt_rate", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") + x.write("descent2_xdsm") x.write_sys_specs("descent2_specs") diff --git a/aviary/xdsm/statics_xdsm.py b/aviary/xdsm/statics_xdsm.py index 2d5c5eed5..69920ccfe 100644 --- a/aviary/xdsm/statics_xdsm.py +++ b/aviary/xdsm/statics_xdsm.py @@ -343,6 +343,10 @@ # Create outputs x.add_output("landing", [Mission.Landing.GROUND_DISTANCE], side="right") +x.add_output("climb1", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") +x.add_output("climb2", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") +x.add_output("descent2", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") +x.add_output("descent1", [Dynamic.Mission.ALTITUDE_RATE_MAX], side="right") # Create phase continuities x.connect("dymos", "groundroll", [Dynamic.Mission.MASS, "TAS", "t_curr"]) @@ -351,10 +355,13 @@ x.connect("dymos", "ascent", [Dynamic.Mission.MASS, Dynamic.Mission.ALTITUDE, "TAS", Dynamic.Mission.FLIGHT_PATH_ANGLE, "t_curr", "alpha"]) x.connect("dymos", "accelerate", [Dynamic.Mission.ALTITUDE, "TAS", Dynamic.Mission.MASS]) -x.connect("dymos", "climb1", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) -x.connect("dymos", "climb2", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) +x.connect("dymos", "climb1", [Dynamic.Mission.ALTITUDE, + Dynamic.Mission.MASS, "TAS_rate"]) +x.connect("dymos", "climb2", [Dynamic.Mission.ALTITUDE, + Dynamic.Mission.MASS, "TAS_rate"]) x.connect("dymos", "poly", ["time_cp", "h_cp"]) -x.connect("dymos", "descent2", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) +x.connect("dymos", "descent2", [Dynamic.Mission.ALTITUDE, + Dynamic.Mission.MASS, "TAS_rate"]) x.connect("dymos", "landing", [Dynamic.Mission.MASS]) x.connect("taxi", "groundroll", [Dynamic.Mission.MASS]) x.connect("dymos", @@ -365,7 +372,8 @@ "cruise_time_initial", "cruise_distance_initial"], ) -x.connect("dymos", "descent1", [Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS]) +x.connect("dymos", "descent1", [Dynamic.Mission.ALTITUDE, + Dynamic.Mission.MASS, "TAS_rate"]) x.connect("dymos", "fuelburn", [Mission.Landing.TOUCHDOWN_MASS]) x.connect("dymos", Dynamic.Mission.DISTANCE, [Mission.Summary.RANGE]) x.connect("cruise", "dymos", ["cruise_time_final", "cruise_distance_final"]) From 19048cf69a27aef9dae088d64edf42f33ee7758d Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 19 Jan 2024 10:56:50 -0500 Subject: [PATCH 085/111] merge fix --- aviary/utils/process_input_decks.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 41f52680e..4f7ea1161 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -153,7 +153,6 @@ def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): GASP_defaults.set_val('mass_defect', val=10000, units='lbm') GASP_defaults.set_val('problem_type', val=ProblemType.SIZING) GASP_defaults.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - GASP_defaults.set_val(Aircraft.Design.RESERVES, val=4998) # overwrite GASP_defaults with values from aircraft_values, then replace # aircraft_values with this merged set From e6f5efcc316476d60ff0a9b187fe23cec7671960 Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 19 Jan 2024 11:43:00 -0500 Subject: [PATCH 086/111] removed dupe import and fixed up the dashboard test to use the correct reports subdirectory --- aviary/interface/test/test_simple_mission.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aviary/interface/test/test_simple_mission.py b/aviary/interface/test/test_simple_mission.py index f9559b691..bbf17e394 100644 --- a/aviary/interface/test/test_simple_mission.py +++ b/aviary/interface/test/test_simple_mission.py @@ -6,7 +6,6 @@ from aviary.interface.methods_for_level1 import run_aviary from aviary.subsystems.test.test_dummy_subsystem import ArrayGuessSubsystemBuilder -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs @use_tempdirs @@ -131,7 +130,7 @@ def test_mission_basic_and_dashboard(self): self.assertIsNotNone(prob) self.assertFalse(prob.failed) - cmd = f'aviary dashboard --problem_recorder dymos_solution.db --driver_recorder driver_test.db test_simple_mission' + cmd = f'aviary dashboard --problem_recorder dymos_solution.db --driver_recorder driver_test.db {prob.driver._problem()._name}' # this only tests that a given command line tool returns a 0 return code. It doesn't # check the expected output at all. The underlying functions that implement the # commands should be tested seperately. From d0dd94be65cdfc49a5cc9fb1beedb65c6c1d00ea Mon Sep 17 00:00:00 2001 From: Herb Schilling Date: Fri, 19 Jan 2024 12:14:46 -0500 Subject: [PATCH 087/111] removed tmate from workflow --- .github/workflows/test_workflow.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 436b1947c..3edbe2f3e 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -213,10 +213,6 @@ jobs: python run_all.py cd ../.. - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - - - name: Run tests if: matrix.MAKE_DOCS == 0 shell: bash -l {0} From db5f28e1b61605ba4be6a74b9d39fd0117d0deb1 Mon Sep 17 00:00:00 2001 From: swryan Date: Fri, 19 Jan 2024 12:29:40 -0500 Subject: [PATCH 088/111] use only conda-forge for depndencies --- .github/workflows/test_workflow.yml | 3 ++- .github/workflows/test_workflow_no_dev_install.yml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 3edbe2f3e..b95cfb4a0 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -106,6 +106,7 @@ jobs: with: auto-update-conda: true python-version: ${{ matrix.PY }} + channels: conda-forge - name: Install dependencies shell: bash -l {0} @@ -232,7 +233,7 @@ jobs: echo "Build the docs" echo "=============================================================" bash build_book.sh - + - name: Display doc build reports continue-on-error: True if: matrix.MAKE_DOCS diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index 74c498830..7fc2bf431 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -54,6 +54,7 @@ jobs: with: auto-update-conda: true python-version: ${{ matrix.PY }} + channels: conda-forge - name: Checkout Aviary uses: actions/checkout@v2 From 18320937f5b2d6248aad0a7f80efac801c1431f5 Mon Sep 17 00:00:00 2001 From: swryan Date: Fri, 19 Jan 2024 12:32:09 -0500 Subject: [PATCH 089/111] enable workflow_dispatch to run tests workflows --- .github/workflows/test_workflow.yml | 3 +++ .github/workflows/test_workflow_no_dev_install.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index b95cfb4a0..95980162e 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -11,6 +11,9 @@ on: merge_group: branches: [ main ] + # Allow running the workflow manually from the Actions tab + workflow_dispatch: + jobs: pre_commit: diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index 7fc2bf431..7e0ca5d54 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -11,6 +11,9 @@ on: merge_group: branches: [ main ] + # Allow running the workflow manually from the Actions tab + workflow_dispatch: + jobs: test_ubuntu_no_dev_install: From 810dc0740a2e58789794aa449e90e0d0a67f5a78 Mon Sep 17 00:00:00 2001 From: swryan Date: Fri, 19 Jan 2024 12:41:40 -0500 Subject: [PATCH 090/111] remove owner condition from workflows --- .github/workflows/test_workflow.yml | 2 -- .github/workflows/test_workflow_no_dev_install.yml | 1 - 2 files changed, 3 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 95980162e..ff240cea6 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -17,7 +17,6 @@ on: jobs: pre_commit: - if: github.repository_owner == 'OpenMDAO' # run pre-commit checks runs-on: ubuntu-latest @@ -29,7 +28,6 @@ jobs: - uses: pre-commit/action@v3.0.0 test_ubuntu: - if: github.repository_owner == 'OpenMDAO' runs-on: ubuntu-latest timeout-minutes: 90 diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index 7e0ca5d54..b963e3666 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -17,7 +17,6 @@ on: jobs: test_ubuntu_no_dev_install: - if: github.repository_owner == 'OpenMDAO' runs-on: ubuntu-latest timeout-minutes: 90 From fc1e4c25327f28ceadbe0f3e2b1bac664994c2d7 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 19 Jan 2024 11:48:34 -0600 Subject: [PATCH 091/111] PR feedback changes --- .../default_phase_info/height_energy.py | 56 ++++++++++++- .../interface/default_phase_info/two_dof.py | 4 +- aviary/interface/methods_for_level2.py | 16 ++-- aviary/interface/test/test_phase_info.py | 50 ++++++++++-- .../test/test_solved_aero_group.py | 78 +------------------ .../test/test_custom_engine_model.py | 3 +- .../benchmark_tests/test_0_iters.py | 4 +- .../benchmark_tests/test_bench_FwFm.py | 2 +- 8 files changed, 116 insertions(+), 97 deletions(-) diff --git a/aviary/interface/default_phase_info/height_energy.py b/aviary/interface/default_phase_info/height_energy.py index 4aceafb61..e42c67172 100644 --- a/aviary/interface/default_phase_info/height_energy.py +++ b/aviary/interface/default_phase_info/height_energy.py @@ -3,6 +3,7 @@ from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Dynamic, Mission from aviary.variable_info.enums import LegacyCode FLOPS = LegacyCode.FLOPS @@ -23,7 +24,6 @@ "user_options": { "optimize_mach": False, "optimize_altitude": False, - "polynomial_control_order": 1, "num_segments": 5, "order": 3, "solve_for_distance": False, @@ -48,7 +48,6 @@ "user_options": { "optimize_mach": False, "optimize_altitude": False, - "polynomial_control_order": 1, "num_segments": 5, "order": 3, "solve_for_distance": False, @@ -72,7 +71,6 @@ "user_options": { "optimize_mach": False, "optimize_altitude": False, - "polynomial_control_order": 1, "num_segments": 5, "order": 3, "solve_for_distance": False, @@ -94,6 +92,56 @@ "post_mission": { "include_landing": False, "constrain_range": True, - "target_range": (1906, "nmi"), + "target_range": (1906., "nmi"), }, } + + +def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): + """ + Modify the values in the phase_info dictionary to accommodate different values + for the following mission design inputs: cruise altitude, cruise Mach number, + cruise range, design gross mass. + + Parameters + ---------- + phase_info : dict + Dictionary of phase settings for a mission profile + aviary_inputs : + Object containing values and units for all aviary inputs and options + + Returns + ------- + dict + Modified phase_info that has been changed to match the new mission + parameters + """ + + alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + mach_cruise = aviary_inputs.get_val(Mission.Summary.CRUISE_MACH) + + # Range + old_range_cruise, range_units = post_mission_info['target_range'] + range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units=range_units) + print(old_range_cruise, range_cruise) + if range_cruise != old_range_cruise: + new_val = post_mission_info['target_range'][0] * range_cruise / old_range_cruise + post_mission_info['target_range'] = (new_val, range_units) + + # Altitude + old_alt_cruise = 32000. + if alt_cruise != old_alt_cruise: + phase_info['climb']['user_options']['final_altitude'] = (alt_cruise, 'ft') + phase_info['cruise']['user_options']['initial_altitude'] = (alt_cruise, 'ft') + phase_info['cruise']['user_options']['final_altitude'] = (alt_cruise, 'ft') + phase_info['descent']['user_options']['initial_altitude'] = (alt_cruise, 'ft') + + # Mach + old_mach_cruise = 0.72 + if mach_cruise != old_mach_cruise: + phase_info['climb']['user_options']['final_mach'] = (mach_cruise, "unitless") + phase_info['cruise']['user_options']['initial_mach'] = (mach_cruise, "unitless") + phase_info['cruise']['user_options']['final_mach'] = (mach_cruise, "unitless") + phase_info['descent']['user_options']['initial_mach'] = (mach_cruise, "unitless") + + return phase_info, post_mission_info diff --git a/aviary/interface/default_phase_info/two_dof.py b/aviary/interface/default_phase_info/two_dof.py index a34a5098d..c1733d16b 100644 --- a/aviary/interface/default_phase_info/two_dof.py +++ b/aviary/interface/default_phase_info/two_dof.py @@ -306,7 +306,7 @@ } -def phase_info_parameterization(phase_info, aviary_inputs): +def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): """ Modify the values in the phase_info dictionary to accomodate different values for the following mission design inputs: cruise altitude, cruise mach number, @@ -383,4 +383,4 @@ def phase_info_parameterization(phase_info, aviary_inputs): phase_info['cruise']['initial_guesses']['mach'] = (mach_cruise, 'unitless') - return phase_info + return phase_info, post_mission_info diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index eec2e2f97..701927249 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -951,8 +951,9 @@ def add_phases(self, phase_info_parameterization=None): traj: The Dymos Trajectory object containing the added mission phases. """ if phase_info_parameterization is not None: - self.phase_info = phase_info_parameterization(self.phase_info, - self.aviary_inputs) + self.phase_info, self.post_mission_info = phase_info_parameterization(self.phase_info, + self.post_mission_info, + self.aviary_inputs) phase_info = self.phase_info @@ -2385,7 +2386,8 @@ def _add_flops_landing_systems(self): 'traj.climb.initial_states:distance') # Create an ExecComp to compute the difference in mach - mach_diff_comp = om.ExecComp('mach_difference = final_mach - initial_mach') + mach_diff_comp = om.ExecComp( + 'mach_resid_for_connecting_takeoff = final_mach - initial_mach') self.model.add_subsystem('mach_diff_comp', mach_diff_comp) # Connect the inputs to the mach difference component @@ -2394,11 +2396,12 @@ def _add_flops_landing_systems(self): 'mach_diff_comp.initial_mach', src_indices=[0]) # Add constraint for mach difference - self.model.add_constraint('mach_diff_comp.mach_difference', equals=0.0) + self.model.add_constraint( + 'mach_diff_comp.mach_resid_for_connecting_takeoff', equals=0.0) # Similar steps for altitude difference alt_diff_comp = om.ExecComp( - 'altitude_difference = final_altitude - initial_altitude', units='ft') + 'altitude_resid_for_connecting_takeoff = final_altitude - initial_altitude', units='ft') self.model.add_subsystem('alt_diff_comp', alt_diff_comp) self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, @@ -2406,7 +2409,8 @@ def _add_flops_landing_systems(self): self.model.connect('traj.climb.control_values:altitude', 'alt_diff_comp.initial_altitude', src_indices=[0]) - self.model.add_constraint('alt_diff_comp.altitude_difference', equals=0.0) + self.model.add_constraint( + 'alt_diff_comp.altitude_resid_for_connecting_takeoff', equals=0.0) self.model.connect('traj.descent.states:mass', Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index 6fab50d7a..c8d8cc62c 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -7,13 +7,14 @@ from openmdao.utils.assert_utils import assert_near_equal -from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp -from aviary.interface.default_phase_info.two_dof import phase_info_parameterization as phase_info_parameterization_gasp +from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_two_dof +from aviary.interface.default_phase_info.two_dof import phase_info_parameterization as phase_info_parameterization_two_dof +from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_height_energy +from aviary.interface.default_phase_info.height_energy import phase_info_parameterization as phase_info_parameterization_height_energy from aviary.interface.methods_for_level2 import AviaryProblem from aviary.mission.flops_based.phases.phase_builder_base import \ PhaseBuilderBase as PhaseBuilder, phase_info_to_builder -# must keep this import to register the phase from aviary.variable_info.variables import Aircraft, Mission @@ -85,8 +86,8 @@ def test_default_phase_height_energy(self): class TestParameterizePhaseInfo(unittest.TestCase): - def test_phase_info_parameterization_gasp(self): - phase_info = deepcopy(ph_in_gasp) + def test_phase_info_parameterization_two_dof(self): + phase_info = deepcopy(ph_in_two_dof) prob = AviaryProblem() @@ -102,7 +103,7 @@ def test_phase_info_parameterization_gasp(self): prob.aviary_inputs.set_val(Mission.Design.MACH, 0.6, 'unitless') prob.add_pre_mission_systems() - prob.add_phases(phase_info_parameterization=phase_info_parameterization_gasp) + prob.add_phases(phase_info_parameterization=phase_info_parameterization_two_dof) prob.add_post_mission_systems() prob.link_phases() @@ -121,7 +122,44 @@ def test_phase_info_parameterization_gasp(self): assert_near_equal(prob.get_val("traj.cruise.rhs.mach")[0], 0.6) + def test_phase_info_parameterization_height_energy(self): + phase_info = deepcopy(ph_in_height_energy) + + prob = AviaryProblem() + + csv_path = "models/test_aircraft/aircraft_for_bench_FwFm.csv" + + prob.load_inputs(csv_path, phase_info) + prob.check_and_preprocess_inputs() + + # We can set some crazy vals, since we aren't going to optimize. + prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000., 'km') + prob.aviary_inputs.set_val(Mission.Design.CRUISE_ALTITUDE, 31000., units='ft') + prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 195000., 'lbm') + prob.aviary_inputs.set_val(Mission.Summary.CRUISE_MACH, 0.6, 'unitless') + + prob.add_pre_mission_systems() + prob.add_phases( + phase_info_parameterization=phase_info_parameterization_height_energy) + prob.add_post_mission_systems() + + prob.link_phases() + + prob.setup() + prob.set_initial_guesses() + + prob.run_model() + + range_resid = prob.get_val(Mission.Constraints.RANGE_RESIDUAL, units='km')[-1] + assert_near_equal(range_resid, 5000.0 - 1.e-3) + assert_near_equal(prob.get_val("traj.cruise.timeseries.polynomial_controls:altitude", units='ft')[0], + 31000.0) + assert_near_equal(prob.get_val("traj.cruise.timeseries.polynomial_controls:mach")[0], + 0.6) + # To run the tests if __name__ == '__main__': unittest.main() + # test = TestPhaseInfo() + # test.test_default_phase_height_energy() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py index d84d9860b..dd07de05f 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py @@ -187,80 +187,6 @@ def test_solved_aero_pass_polar_unique_abscissa(self): assert_near_equal(CL_pass, CL_base, 1e-6) assert_near_equal(CD_pass, CD_base, 1e-6) - def test_solved_aero_pass_polar_unique_abscissa(self): - # Solved Aero with shortened lists of table abscissa. - local_phase_info = deepcopy(phase_info) - - prob = AviaryProblem() - - csv_path = "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv" - - prob.load_inputs(csv_path, local_phase_info) - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_model() - - CL_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - # Lift and Drag polars passed from external component in static. - - ph_in = deepcopy(phase_info) - - alt = np.array([0., 3000., 6000., 9000., 12000., 15000., 18000., 21000., - 24000., 27000., 30000., 33000., 36000., 38000., 42000.]) - mach = np.array([0., 0.2, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8, 0.85, 0.9]) - alpha = np.array([-2., 0., 2., 4., 6., 8., 10.]) - - polar_builder = FakeDragPolarBuilder(name="aero", altitude=alt, mach=mach, - alpha=alpha) - aero_data = NamedValues() - aero_data.set_val('altitude', alt, 'ft') - aero_data.set_val('mach', mach, 'unitless') - aero_data.set_val('angle_of_attack', alpha, 'deg') - - subsystem_options = {'method': 'solved_alpha', - 'aero_data': aero_data, - 'training_data': True} - ph_in['pre_mission']['external_subsystems'] = [polar_builder] - - ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} - - prob = AviaryProblem() - - prob.load_inputs(csv_path, ph_in) - - prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, - np.zeros_like(CL), units='unitless') - prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, - np.zeros_like(CD), units='unitless') - - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_model() - - CL_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - assert_near_equal(CL_pass, CL_base, 1e-6) - assert_near_equal(CD_pass, CD_base, 1e-6) - class FakeCalcDragPolar(om.ExplicitComponent): """ @@ -349,4 +275,6 @@ def build_pre_mission(self, aviary_inputs): if __name__ == "__main__": - unittest.main() + # unittest.main() + test = TestSolvedAero() + test.test_solved_aero_pass_polar_unique_abscissa() diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index b079f01fb..2222168a5 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -167,8 +167,7 @@ def test_custom_engine(self): prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info, engine_builder=SimpleTestEngine()) - -# Preprocess inputs + # Preprocess inputs prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index c60146b11..31761bd19 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -63,4 +63,6 @@ def test_zero_iters_solved(self): if __name__ == "__main__": - unittest.main() + # unittest.main() + test = SolvedProblemTestCase() + test.test_zero_iters_solved() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 7fff9058e..bd73cb077 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -343,7 +343,7 @@ def bench_test_swap_4_FwFm(self): "post_mission": { "include_landing": True, "constrain_range": True, - "target_range": (3368.0, "nmi"), + "target_range": (3375.0, "nmi"), }, } From 7f9dc5b63dc6af6a6056c77dfa1e2f0c3d6bc3f1 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Fri, 19 Jan 2024 11:58:51 -0600 Subject: [PATCH 092/111] Fixed doc build --- aviary/mission/flops_based/ode/mission_ODE.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/mission/flops_based/ode/mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py index 2a6dcccd4..60cfba24e 100644 --- a/aviary/mission/flops_based/ode/mission_ODE.py +++ b/aviary/mission/flops_based/ode/mission_ODE.py @@ -41,7 +41,7 @@ def initialize(self): desc='flag to use actual takeoff mass in the climb phase, otherwise assume 100 kg fuel burn') self.options.declare( 'throttle_enforcement', default='path_constraint', - values=['path_constraint', 'boundary_constraint', 'bounded'], + values=['path_constraint', 'boundary_constraint', 'bounded', None], desc='flag to enforce throttle constraints on the path or at the segment boundaries or using solver bounds' ) From 470ecc66b6e04d87d7fd3aa245e1e487cba7e888 Mon Sep 17 00:00:00 2001 From: crecine <51181861+crecine@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:03:44 -0800 Subject: [PATCH 093/111] updated simple to HE --- aviary/validation_cases/benchmark_tests/test_0_iters.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 6121652f6..4654feea7 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -7,7 +7,6 @@ from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info from aviary.interface.default_phase_info.solved import phase_info as solved_phase_info -from aviary.interface.default_phase_info.simple import phase_info as simple_phase_info from aviary.models.N3CC.N3CC_data import inputs from aviary.variable_info.variables import Settings from aviary.variable_info.enums import EquationsOfMotion @@ -49,7 +48,7 @@ class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_zero_iters_height_energy(self): - local_phase_info = deepcopy(simple_phase_info) + local_phase_info = deepcopy(height_energy_phase_info) inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) self.build_and_run_problem(inputs, local_phase_info) From be458616eb24e940beed6503f49f0d8dfcec5a0a Mon Sep 17 00:00:00 2001 From: crecine <51181861+crecine@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:54:13 -0800 Subject: [PATCH 094/111] Removed unused setting --- aviary/validation_cases/benchmark_tests/test_0_iters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 4654feea7..baa403fad 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -49,7 +49,6 @@ class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_zero_iters_height_energy(self): local_phase_info = deepcopy(height_energy_phase_info) - inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.SIMPLE) self.build_and_run_problem(inputs, local_phase_info) From b7bd2700a9ea3754a789d79428cf010d723e49f9 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 09:45:56 -0800 Subject: [PATCH 095/111] Declared states so that nox doesn't have to be blocked --- aviary/examples/level2_shooting_traj.py | 1 - .../default_phase_info/two_dof_fiti.py | 10 ---- .../ode/time_integration_base_classes.py | 52 +++++++++++++--- .../phases/time_integration_phases.py | 60 ++++++++++++++----- .../phases/time_integration_traj.py | 4 ++ 5 files changed, 91 insertions(+), 36 deletions(-) diff --git a/aviary/examples/level2_shooting_traj.py b/aviary/examples/level2_shooting_traj.py index 0bbd323b5..5c66e0bbe 100644 --- a/aviary/examples/level2_shooting_traj.py +++ b/aviary/examples/level2_shooting_traj.py @@ -74,7 +74,6 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, analysis_scheme=An ode_args=prob.ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine.nox', 'nox'], ), ) descent1_vals = { diff --git a/aviary/interface/default_phase_info/two_dof_fiti.py b/aviary/interface/default_phase_info/two_dof_fiti.py index 577bfc20c..def0c1fdc 100644 --- a/aviary/interface/default_phase_info/two_dof_fiti.py +++ b/aviary/interface/default_phase_info/two_dof_fiti.py @@ -17,7 +17,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) groundroll_vals = { @@ -29,7 +28,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) rotation_vals = {} @@ -38,7 +36,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) ascent_vals = { @@ -53,7 +50,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) accel_vals = {} @@ -64,7 +60,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) climb1_vals = { @@ -79,7 +74,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) climb2_vals = { @@ -94,7 +88,6 @@ def create_2dof_based_ascent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) climb3_vals = { @@ -150,7 +143,6 @@ def create_2dof_based_descent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) descent1_vals = { @@ -166,7 +158,6 @@ def create_2dof_based_descent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) descent2_vals = { @@ -182,7 +173,6 @@ def create_2dof_based_descent_phases( ode_args=ode_args, simupy_args=dict( DEBUG=False, - blocked_state_names=['engine_deck.nox', 'nox'], ), ) descent3_vals = { diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index d612c1618..e9b09033d 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -8,7 +8,18 @@ from aviary.mission.gasp_based.ode.params import ParamPort +def add_SGM_required_inputs(group: om.Group, inputs_to_add: dict): + blank_execcomp = om.ExecComp() + for input, details in inputs_to_add.items(): + blank_execcomp.add_input(input, **details) + group.add_subsystem('SGM_required_inputs', + blank_execcomp, + promotes_inputs=list(inputs_to_add.keys()), + ) + # Subproblem used as a basis for forward in time integration phases. + + class SimuPyProblem(SimulationMixin): def __init__( self, @@ -61,6 +72,10 @@ def __init__( self.time_independent = time_independent if control_names is None: control_names = [] + if alternate_state_names is None: + alternate_state_names = {} + if alternate_state_rate_names is None: + alternate_state_rate_names = {} self.control_names = control_names if control_units is not None: self.control_units = control_units @@ -97,7 +112,7 @@ def __init__( for name in blocked_state_names: if name in state_names: state_names.remove(name) - if alternate_state_names is not None: + if alternate_state_names: for key, val in alternate_state_names.items(): state_key = key.replace(rate_suffix, "") if state_key in state_names: # Used to rename an existing state @@ -107,7 +122,7 @@ def __init__( if state_rate_names is None: state_rate_names = [state_name + rate_suffix for state_name in state_names] - if alternate_state_names is not None: + if alternate_state_rate_names: state_rate_names = [name if name not in alternate_state_rate_names.keys( ) else alternate_state_rate_names[name] for name in state_rate_names] @@ -169,7 +184,7 @@ def __init__( for output_name in output_names ] - if include_state_outputs: + if include_state_outputs or output_names == []: # prevent empty outputs output_names = state_names + output_names self.output_units = self.state_units + self.output_units @@ -189,6 +204,8 @@ def __init__( if DEBUG: om.n2(prob, outfile="n2_simupy_problem.html", show_browser=False) + with open('input_list_simupy.txt', 'w') as outfile: + prob.model.list_inputs(out_stream=outfile,) print(state_names) print(self.state_units) print(state_rate_names) @@ -360,8 +377,10 @@ def initialize(self): def setup_params( self, ODEs, + promote_all_auto_ivc=False, traj_final_state_output=None, traj_promote_final_output=None, + traj_promote_initial_input=None, traj_initial_state_input=None, traj_event_trigger_input=None, ): @@ -381,13 +400,29 @@ def setup_params( traj_final_state_output = [] if traj_promote_final_output is None: traj_promote_final_output = [] + if traj_promote_initial_input is None: + traj_promote_initial_input = {} if traj_initial_state_input is None: traj_initial_state_input = [] if traj_event_trigger_input is None: traj_event_trigger_input = [] - for name, kwargs in self.options["param_dict"].items(): + if promote_all_auto_ivc: + for ode in ODEs: + ode: SimuPyProblem + ode.auto_ivc_vars = ode.prob.model.list_inputs( + is_indep_var=True, units=True, out_stream=None) + for abs_name, data in ode.auto_ivc_vars: + prom_name = data.pop('prom_name') + if '.' in prom_name: + continue + traj_promote_initial_input[prom_name] = data + + self.traj_promote_initial_input = { + **self.options["param_dict"], **traj_promote_initial_input} + for name, kwargs in self.traj_promote_initial_input.items(): self.add_input(name, **kwargs) + final_suffix = "_final" self.traj_final_state_output = { final_state_output: { @@ -463,17 +498,16 @@ def setup_params( self.declare_partials(["*"], ["*"],) def compute_params(self, inputs): - # parameter pass-through setup - for param_input in self.options["param_dict"].keys(): + for input in self.traj_promote_initial_input.keys(): for ode in self.ODEs: try: - ode.set_val(param_input, inputs[param_input]) + ode.set_val(input, inputs[input]) except KeyError: if self.DEBUG: print( - "*** ParamPort input not found:", + "*** Input not found:", ode, - param_input + input ) pass diff --git a/aviary/mission/gasp_based/phases/time_integration_phases.py b/aviary/mission/gasp_based/phases/time_integration_phases.py index 1d4a784c7..7b5865192 100644 --- a/aviary/mission/gasp_based/phases/time_integration_phases.py +++ b/aviary/mission/gasp_based/phases/time_integration_phases.py @@ -9,8 +9,7 @@ from aviary.mission.gasp_based.phases.landing_group import LandingSegment from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE from aviary.mission.gasp_based.ode.rotation_ode import RotationODE -from aviary.mission.gasp_based.ode.time_integration_base_classes import ( - SGMTrajBase, SimuPyProblem) +from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import AlphaModes, AnalysisScheme, SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -37,8 +36,13 @@ def __init__( super().__init__( GroundrollODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), output_names=["normal_force"], - alternate_state_names={Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS, - 'TAS': 'TAS'}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + 'TAS' + ], + # state_units=['lbm','nmi','ft','ft/s'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, @@ -73,8 +77,12 @@ def __init__( super().__init__( RotationODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), output_names=["normal_force", "alpha"], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, @@ -127,8 +135,12 @@ def __init__( "normal_force", "alpha", ], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, control_names=control_names, @@ -366,8 +378,12 @@ def __init__( super().__init__( ode, output_names=["EAS", "mach", "alpha"], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, @@ -432,8 +448,12 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, @@ -496,8 +516,12 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, @@ -571,8 +595,12 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - alternate_state_names={ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: Dynamic.Mission.MASS}, + state_names=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], + # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, diff --git a/aviary/mission/gasp_based/phases/time_integration_traj.py b/aviary/mission/gasp_based/phases/time_integration_traj.py index cc136d943..d566635d3 100644 --- a/aviary/mission/gasp_based/phases/time_integration_traj.py +++ b/aviary/mission/gasp_based/phases/time_integration_traj.py @@ -29,8 +29,10 @@ class FlexibleTraj(TimeIntegrationTrajBase): def initialize(self): super().initialize() self.options.declare('Phases', default=None) + self.options.declare('promote_all_auto_ivc', default=False) self.options.declare('traj_final_state_output', default=None) self.options.declare('traj_promote_final_output', default=None) + self.options.declare('traj_promote_initial_input', default=None) self.options.declare('traj_initial_state_input', default=None) self.options.declare('traj_event_trigger_input', default=None) @@ -44,9 +46,11 @@ def setup(self): self.setup_params( ODEs=ODEs, + promote_all_auto_ivc=self.options['promote_all_auto_ivc'], traj_final_state_output=self.options['traj_final_state_output'], traj_promote_final_output=self.options['traj_promote_final_output'], + traj_promote_initial_input=self.options['traj_promote_initial_input'], traj_initial_state_input=self.options['traj_initial_state_input'], traj_event_trigger_input=self.options['traj_event_trigger_input'], ) From 70d4a9874aa9d0d5c3e2e5d8309289140df6e1e3 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 09:49:30 -0800 Subject: [PATCH 096/111] fixed extra lines added by precommit --- aviary/mission/gasp_based/ode/time_integration_base_classes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index e9b09033d..a6b675643 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -17,9 +17,8 @@ def add_SGM_required_inputs(group: om.Group, inputs_to_add: dict): promotes_inputs=list(inputs_to_add.keys()), ) -# Subproblem used as a basis for forward in time integration phases. - +# Subproblem used as a basis for forward in time integration phases. class SimuPyProblem(SimulationMixin): def __init__( self, From fee4f8a18a4ae29d91c71bf80b93a7aaa8db7e14 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 09:56:45 -0800 Subject: [PATCH 097/111] grabbed two more instances --- aviary/examples/level2_shooting_traj.py | 2 -- aviary/interface/methods_for_level2.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/aviary/examples/level2_shooting_traj.py b/aviary/examples/level2_shooting_traj.py index 5c66e0bbe..b02eba8ee 100644 --- a/aviary/examples/level2_shooting_traj.py +++ b/aviary/examples/level2_shooting_traj.py @@ -58,8 +58,6 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, analysis_scheme=An alpha_mode=AlphaModes.REQUIRED_LIFT, simupy_args=dict( DEBUG=True, - blocked_state_names=['engine.nox', 'nox', - 'TAS', Dynamic.Mission.FLIGHT_PATH_ANGLE], ), ) cruise_vals = { diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 028f05b27..19e65fe53 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -1001,8 +1001,6 @@ def add_phases(self, phase_info_parameterization=None): alpha_mode=AlphaModes.REQUIRED_LIFT, simupy_args=dict( DEBUG=True, - blocked_state_names=['engine.nox', 'nox', - 'TAS', Dynamic.Mission.FLIGHT_PATH_ANGLE], ), ) cruise_vals = { From 47a560c3b2acf7b86d03b389fb786ea047cffcdc Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 10:02:25 -0800 Subject: [PATCH 098/111] Added test for level 1 with SGM --- aviary/interface/test/test_cmd_entry_points.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aviary/interface/test/test_cmd_entry_points.py b/aviary/interface/test/test_cmd_entry_points.py index 41da59bd7..1ae378f7e 100644 --- a/aviary/interface/test/test_cmd_entry_points.py +++ b/aviary/interface/test/test_cmd_entry_points.py @@ -28,6 +28,12 @@ def bench_test_IPOPT_cmd(self): cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' self.run_and_test_cmd(cmd) + @require_pyoptsparse(optimizer="IPOPT") + def bench_test_IPOPT_cmd(self): + cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv' \ + ' --optimizer IPOPT --max_iter 1 --shooting' + self.run_and_test_cmd(cmd) + def test_diff_configuration_conversion(self): filepath = pkg_resources.resource_filename('aviary', 'models/test_aircraft/converter_configuration_test_data_GwGm.dat') From b29273a420bb29f5de4b9c77d4ba57e437f2ba68 Mon Sep 17 00:00:00 2001 From: Gregory Wrenn Date: Mon, 22 Jan 2024 13:05:30 -0500 Subject: [PATCH 099/111] [no ci] Restore passenger count to 180. --- aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py | 2 +- .../models/large_single_aisle_1/large_single_aisle_1_GwGm.csv | 2 +- .../models/large_single_aisle_1/large_single_aisle_1_GwGm.dat | 2 +- aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv | 2 +- aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py index 0809183c3..113fc4748 100644 --- a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py +++ b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py @@ -13,7 +13,7 @@ V3_bug_fixed_options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.NUM_PASSENGERS, val=169, units='unitless') + Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') V3_bug_fixed_options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') V3_bug_fixed_options.set_val( Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index 603362b3e..5226249f0 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -6,7 +6,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,169,unitless +aircraft:crew_and_payload:num_passengers,180,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat index 633061c3c..f23fff285 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat @@ -18,7 +18,7 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck HCK=4.5, ! mean fuselage cabin diameter minus mean fuselage nose diameter in feet (2.47) HTG=8., ! wing height about ground during ground run in feet (3.0) HWING=0.0, ! wing location on fuselage =0, low wing; =1 high wing - PAX=169., ! number of passenger seats excluding crew + PAX=180., ! number of passenger seats excluding crew PS=29.0, ! seat pitch in inches RELR=0.4524, ! cg of fuselage and contents, fraction fuselage(.4) if LCWING <> 0 SAB=6., ! seats abreast in fuselage diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index b94349906..85217169b 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -5,7 +5,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,169,unitless +aircraft:crew_and_payload:num_passengers,180,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv index ba578e05d..720764ca5 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_solved.csv @@ -5,7 +5,7 @@ aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:num_passengers,169,unitless +aircraft:crew_and_payload:num_passengers,180,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless From 9d90a746466a1a30464d219fd2ae4933c11e6b81 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 22 Jan 2024 15:29:36 -0600 Subject: [PATCH 100/111] Updated GwGm truth values and added workflow for benchmarks --- .github/workflows/test_workflow.yml | 29 +++++++++++++++++-- .../benchmark_tests/test_bench_GwGm.py | 8 ++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index ff240cea6..7410a715d 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -46,6 +46,7 @@ jobs: OPENMDAO: '3.27' DYMOS: '1.8.0' MAKE_DOCS: 0 + RUN_BENCHES: 0 # development versions of openmdao/dymos - NAME: dev @@ -57,6 +58,7 @@ jobs: OPENMDAO: 'dev' DYMOS: 'dev' MAKE_DOCS: 0 + RUN_BENCHES: 0 # latest versions of openmdao/dymos - NAME: latest @@ -68,6 +70,7 @@ jobs: OPENMDAO: 'latest' DYMOS: 'latest' MAKE_DOCS: 0 + RUN_BENCHES: 0 # latest versions of openmdao/dymos for docs only - NAME: latest_docs @@ -79,6 +82,19 @@ jobs: OPENMDAO: 'latest' DYMOS: 'latest' MAKE_DOCS: 1 + RUN_BENCHES: 0 + + # latest versions of openmdao/dymos for benches only + - NAME: latest_benches + PY: 3 + NUMPY: 1 + SCIPY: 1 + PYOPTSPARSE: 'v2.9.1' + SNOPT: '7.7' + OPENMDAO: 'latest' + DYMOS: 'latest' + MAKE_DOCS: 0 + RUN_BENCHES: 1 steps: - name: Display run details @@ -205,7 +221,7 @@ jobs: retention-days: 5 - name: Generate specs - if: matrix.MAKE_DOCS == 0 + if: matrix.MAKE_DOCS == 0 && matrix.RUN_BENCHES == 0 shell: bash -l {0} run: | echo "=============================================================" @@ -216,7 +232,7 @@ jobs: cd ../.. - name: Run tests - if: matrix.MAKE_DOCS == 0 + if: matrix.MAKE_DOCS == 0 && matrix.RUN_BENCHES == 0 shell: bash -l {0} run: | echo "=============================================================" @@ -224,6 +240,15 @@ jobs: echo "=============================================================" testflo . -n 1 --show_skipped --coverage --coverpkg aviary + - name: Run benchmarks + if: matrix.RUN_BENCHES + shell: bash -l {0} + run: | + echo "=============================================================" + echo "Run Benchmarks" + echo "=============================================================" + testflo . --testmatch=bench_test* + - name: Build docs if: matrix.MAKE_DOCS shell: bash -l {0} diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index d87013d8d..7dda04ad4 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -23,16 +23,16 @@ def bench_test_swap_2_GwGm(self): # There are no truth values for these. assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), - 174039., tolerance=rtol) + 181654., tolerance=rtol) assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), - 95509, tolerance=rtol) + 101555., tolerance=rtol) assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), - 42529., tolerance=rtol) + 44098., tolerance=rtol) assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), - 2634.8, tolerance=rtol) + 2637.86, tolerance=rtol) assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], 3675.0, tolerance=rtol) From 5593aaf67600f184e6e1b6c7b8574e157061b367 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 22 Jan 2024 15:52:00 -0600 Subject: [PATCH 101/111] Updated benches to pass CI --- .../mission/gasp_based/phases/benchmark/test_bench_accel.py | 2 ++ .../benchmark_tests/test_FLOPS_based_sizing_N3CC.py | 5 ++++- aviary/validation_cases/benchmark_tests/test_bench_FwFm.py | 4 +++- aviary/validation_cases/benchmark_tests/test_bench_FwGm.py | 5 ++--- aviary/validation_cases/benchmark_tests/test_bench_GwFm.py | 4 +++- aviary/validation_cases/benchmark_tests/test_bench_GwGm.py | 5 ++--- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/aviary/mission/gasp_based/phases/benchmark/test_bench_accel.py b/aviary/mission/gasp_based/phases/benchmark/test_bench_accel.py index ac1f1294e..6d53ac5d4 100644 --- a/aviary/mission/gasp_based/phases/benchmark/test_bench_accel.py +++ b/aviary/mission/gasp_based/phases/benchmark/test_bench_accel.py @@ -1,10 +1,12 @@ import unittest from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse from aviary.mission.gasp_based.phases.run_phases.run_accel import run_accel +@require_pyoptsparse(optimizer="SNOPT") class AccelPhaseTestCase(unittest.TestCase): def bench_test_accel(self): diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index e1b144b94..d1f982f5d 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -13,6 +13,7 @@ import scipy.constants as _units from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs +from openmdao.utils.testing_utils import require_pyoptsparse from aviary.mission.flops_based.phases.build_landing import Landing from aviary.mission.flops_based.phases.build_takeoff import Takeoff @@ -274,7 +275,7 @@ def run_trajectory(sim=True): promotes_outputs=['mission:*']) traj.link_phases(["climb", "cruise", "descent"], [ - "time", Dynamic.Mission.ALTITUDE, Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) + "time", Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) traj = setup_trajectory_params(prob.model, traj, aviary_inputs) @@ -437,6 +438,8 @@ def run_trajectory(sim=True): @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): + + @require_pyoptsparse(optimizer="SNOPT") def bench_test_sizing_N3CC(self): prob = run_trajectory(sim=False) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index bd73cb077..365291916 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -2,6 +2,7 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs +from openmdao.utils.testing_utils import require_pyoptsparse from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ @@ -260,6 +261,7 @@ def setUp(self): self.expected_dict = expected_dict + @require_pyoptsparse(optimizer="IPOPT") def bench_test_swap_4_FwFm(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, @@ -348,7 +350,7 @@ def bench_test_swap_4_FwFm(self): } prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, max_iter=50) + 'models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, max_iter=50, optimizer='IPOPT') compare_against_expected_values(prob, self.expected_dict) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index 29dacddbf..21c076e17 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -1,5 +1,4 @@ from copy import deepcopy -import os import unittest from openmdao.utils.assert_utils import assert_near_equal @@ -13,11 +12,11 @@ @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer="IPOPT") def bench_test_swap_3_FwGm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwGm.csv', - local_phase_info) + local_phase_info, optimizer='IPOPT') rtol = 1e-2 diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 4d173b597..129d71978 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -9,6 +9,7 @@ import numpy as np from openmdao.utils.testing_utils import use_tempdirs +from openmdao.utils.testing_utils import require_pyoptsparse from aviary.interface.methods_for_level1 import run_aviary from aviary.validation_cases.benchmark_utils import \ @@ -266,6 +267,7 @@ def setUp(self): self.expected_dict = expected_dict + @require_pyoptsparse(optimizer="IPOPT") def bench_test_swap_1_GwFm(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, @@ -354,7 +356,7 @@ def bench_test_swap_1_GwFm(self): } prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info, - max_iter=50) + max_iter=50, optimizer='IPOPT') compare_against_expected_values(prob, self.expected_dict) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 7dda04ad4..b6e6b7eb5 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -1,5 +1,4 @@ from copy import deepcopy -import os import unittest from openmdao.utils.assert_utils import assert_near_equal @@ -13,11 +12,11 @@ @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer="IPOPT") def bench_test_swap_2_GwGm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwGm.csv', - local_phase_info) + local_phase_info, optimizer='IPOPT') rtol = 0.01 From 388445bb7cea88182989e1e9e773940984e2eb81 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Mon, 22 Jan 2024 16:35:21 -0600 Subject: [PATCH 102/111] Updated bench values --- aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv | 4 ++-- aviary/utils/preprocessors.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 120717a9e..a3bcfe007 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -21,8 +21,8 @@ aircraft:crew_and_payload:num_flight_attendants,3,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,0,unitless aircraft:crew_and_payload:num_non_flight_crew,3,unitless -aircraft:crew_and_payload:num_passengers,169,unitless -aircraft:crew_and_payload:num_tourist_class,158,unitless +aircraft:crew_and_payload:num_passengers,180,unitless +aircraft:crew_and_payload:num_tourist_class,169,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless aircraft:crew_and_payload:wing_cargo,0.0,lbm diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index c2cce0604..57cd37f84 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -58,7 +58,7 @@ def preprocess_crewpayload(aviary_options: AviaryValues): # only perform check if at least one passenger class is entered if passenger_check > 0 and passenger_count != passenger_check: raise om.AnalysisError( - "ERROR: In preprocesssors.py: passenger_count does not equal the sum of firt class + business class + tourist class passengers.") + f"ERROR: In preprocesssors.py: passenger_count ({passenger_count}) does not equal the sum of first class + business class + tourist class passengers (total of {passenger_check}).") if Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS not in aviary_options: flight_attendants_count = 0 # assume no passengers From 7b79cbd2bee05feca10376d1bb1db6266a237037 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 16:39:55 -0800 Subject: [PATCH 103/111] Combined lists of names and lists of units into dicts of name:units --- .../gasp_based/idle_descent_estimation.py | 7 +- .../ode/time_integration_base_classes.py | 357 +++++++++--------- .../phases/time_integration_phases.py | 30 +- .../phases/time_integration_traj.py | 4 +- 4 files changed, 196 insertions(+), 202 deletions(-) diff --git a/aviary/mission/gasp_based/idle_descent_estimation.py b/aviary/mission/gasp_based/idle_descent_estimation.py index 0371183fa..50fb3759d 100644 --- a/aviary/mission/gasp_based/idle_descent_estimation.py +++ b/aviary/mission/gasp_based/idle_descent_estimation.py @@ -34,8 +34,11 @@ def descent_range_and_fuel( traj = FlexibleTraj( Phases=phases, - traj_final_state_output=[Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE], + traj_final_state_output=[ + Dynamic.Mission.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Mission.ALTITUDE, + ], traj_initial_state_input=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index a6b675643..5ad167b01 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -25,19 +25,14 @@ def __init__( ode, time_independent=False, t_name="t_curr", - state_names=None, + states=None, alternate_state_names=None, blocked_state_names=None, - state_units=None, - state_rate_names=None, + state_rates=None, alternate_state_rate_names=None, - state_rate_units=None, - parameter_names=None, - parameter_units=None, - output_names=None, - output_units=None, - control_names=None, - control_units=None, + parameters=None, + outputs=None, + controls=None, include_state_outputs=False, rate_suffix="_rate", DEBUG=False, @@ -46,9 +41,21 @@ def __init__( ): """ + states: a dictionary of the form {state_name:{'units':unit, 'rate':state_rate_name}} + alternate_state_names: a dictionary of the form {state_to_replace:'new_state_name'} + blocked_state_names: a list of the form [state_name_to_block] + state_rates: a dictionary of the form {state_rate_name:unit} + alternate_state_rate_names: a dictionary of the form {state_rate_to_replace:'new_state_rate_name'} + parameters: a dictionary of the form {parameter_name:unit} + outputs: a dictionary of the form {output_name:unit} + controls: a dictionary of the form {control_name:unit} include_state_outputs : automatically add the state to the input works well for auto-parsed naming, does not check for duplication before adding + states, state_rates, parameters, outputs, and controls can also be input as a list of keys for the dictionary """ + + default_args = dict(prom_name=True, val=False, out_stream=None, units=True) + self.DEBUG = DEBUG self.max_allowable_time = max_allowable_time self.adjoint_int_opts = adjoint_int_opts @@ -69,146 +76,144 @@ def __init__( prob.final_setup() self.time_independent = time_independent - if control_names is None: - control_names = [] + if type(states) is list: + states = {state: {'units': None, 'rate': state+rate_suffix} + for state in states} + if type(parameters) is list: + parameters = {parameter: None for parameter in parameters} + if type(outputs) is list: + outputs = {output: None for output in outputs} + if controls is None: + controls = {} + elif type(controls) is list: + controls = {control: None for control in controls} if alternate_state_names is None: alternate_state_names = {} if alternate_state_rate_names is None: alternate_state_rate_names = {} - self.control_names = control_names - if control_units is not None: - self.control_units = control_units - else: - self.control_units = [ - om_dict["units"] - for om_name, om_dict in prob.model.list_inputs( - includes=control_names, - out_stream=False, - val=False, - units=True, - ) - ] + + data = prob.model.list_inputs(includes=controls.keys(), **default_args) + control_data = {val.pop('prom_name'): val for key, val in data} + for control_name, control_units in controls.items(): + if control_units is None: + controls[control_name] = control_data[control_name]["units"] + self.controls = controls if ( - state_names is None - or parameter_names is None - or output_names is None # or + states is None + or parameters is None + or outputs is None # or # event_names is None ): - data = prob.model.list_outputs(prom_name=True, val=False, out_stream=None) - outputs = [val['prom_name'] for key, val in data] - data = prob.model.list_inputs(prom_name=True, val=False, out_stream=None) - inputs = [val['prom_name'] for key, val in data] - - if state_names is None: - state_names = [ - output.replace(rate_suffix, "") - for output in outputs + data = prob.model.list_outputs(**default_args) + model_outputs = [val['prom_name'] for key, val in data] + data = prob.model.list_inputs(**default_args) + model_inputs = [val['prom_name'] for key, val in data] + + if states is None: + states = { + output.replace(rate_suffix, ""): {'units': None, 'rate': output} + for output in model_outputs if output.endswith(rate_suffix) or output in alternate_state_names.keys() - ] + } + if blocked_state_names is not None: for name in blocked_state_names: - if name in state_names: - state_names.remove(name) + if name in states.keys(): + states.pop(name) if alternate_state_names: - for key, val in alternate_state_names.items(): - state_key = key.replace(rate_suffix, "") - if state_key in state_names: # Used to rename an existing state - state_names[state_names.index(state_key)] = val + for state_key, val in alternate_state_names.items(): + if state_key in states.keys(): # Used to rename an existing state + # modified_states = {} + # for name, state_data in states.items(): + # key = name if name not in alternate_state_names else alternate_state_names[name] + # modified_states[key] = state_data + # states = modified_states + states[val] = states.pop(state_key) else: # Used to add a new state - state_names.append(val) + states[val]: {'units': None, 'rate': val+rate_suffix} - if state_rate_names is None: - state_rate_names = [state_name + rate_suffix for state_name in state_names] + if state_rates is None: + state_rates = { + state_name + rate_suffix: None + for state_name in states.keys()} if alternate_state_rate_names: - state_rate_names = [name if name not in alternate_state_rate_names.keys( - ) else alternate_state_rate_names[name] for name in state_rate_names] - - if state_rate_units is not None: - self.state_rate_units = state_rate_units - else: - self.state_rate_units = [ - om_dict["units"] - for om_name, om_dict in prob.model.list_outputs( - includes=state_rate_names, - out_stream=False, - val=False, - units=True, - ) - ] - - if state_units is not None: - self.state_units = state_units - else: - self.state_units = [ - units.simplify_unit("s*" + rate_unit) - for rate_unit in self.state_rate_units - ] + for rate_name, val in alternate_state_rate_names.items(): + if rate_name in state_rates.keys(): + # state_rates[val] = state_rates.pop(rate_name) + modified_rates = {} + for name, rate_data in state_rates.items(): + key = name if name not in alternate_state_rate_names else alternate_state_rate_names[ + name] + modified_rates[key] = rate_data + state_rates = modified_rates + + state_name = rate_name.replace(rate_suffix, "") + if state_name in states.keys(): + states[state_name]['rate'] = val + + data = prob.model.list_outputs(includes=state_rates.keys(), **default_args) + rate_data = {val.pop('prom_name'): val for key, val in data} + for rate_name, rate_units in state_rates.items(): + if rate_units is None: + state_rates[rate_name] = rate_data[rate_name]["units"] + + for state_name, state_data in states.items(): + if state_data['units'] is None: + rate_unit = rate_data[state_data['rate']]["units"] + states[state_name]['units'] = units.simplify_unit("s*" + rate_unit) + + if parameters is None: + parameters = { + inp: None + for inp in set(model_inputs) + if inp not in list(states.keys()) + list(controls.keys()) + [t_name] + } - if parameter_names is None: - parameter_names = [ - inp - for inp in set(inputs) - if inp not in state_names + control_names + [t_name] - ] - if parameter_units is not None: - self.parameter_units = parameter_units - else: - self.parameter_units = [ - om_dict["units"] - for om_name, om_dict in prob.model.list_inputs( - includes=parameter_names, - out_stream=False, - val=False, - units=True, - ) - ] + data = prob.model.list_inputs(includes=parameters.keys(), **default_args) + parameter_data = {val.pop('prom_name'): val for key, val in data} + for parameter_name, parameter_units in parameters.items(): + if parameter_units is None: + parameters[parameter_name] = parameter_data[parameter_name]["units"] - if output_names is None: - output_names = [ - outp + if outputs is None: + outputs = { + outp: None for outp in outputs - if outp not in state_rate_names # + event_names - ] + if outp not in state_rates # + event_names + } - if output_units is not None: - self.output_units = output_units - else: - self.output_units = [ - next(iter(prob.model.get_io_metadata( + for output_name, output_units in outputs.items(): + if output_units is None: + outputs[output_name] = next(iter(prob.model.get_io_metadata( includes=[output_name], metadata_keys=["units"] ).values()))["units"] - for output_name in output_names - ] - if include_state_outputs or output_names == []: # prevent empty outputs - output_names = state_names + output_names - self.output_units = self.state_units + self.output_units + if include_state_outputs or outputs == {}: # prevent empty outputs + outputs = states + outputs self.t_name = t_name - self.state_names = state_names + self.states = states - self.state_rate_names = state_rate_names - self.parameter_names = parameter_names - self.output_names = output_names + self.state_rates = state_rates + self.parameters = parameters + self.outputs = outputs - self.dim_state = len(state_names) - self.dim_output = len(output_names) - self.dim_input = len(control_names) - self.dim_parameters = len(parameter_names) + self.dim_state = len(states) + self.dim_output = len(outputs) + self.dim_input = len(controls) + self.dim_parameters = len(parameters) # TODO: add defensive checks to make sure dimensions match in both setup and # calls - if DEBUG: + if DEBUG or True: om.n2(prob, outfile="n2_simupy_problem.html", show_browser=False) with open('input_list_simupy.txt', 'w') as outfile: prob.model.list_inputs(out_stream=outfile,) - print(state_names) - print(self.state_units) - print(state_rate_names) - print(self.state_rate_units) + print(states) + print(state_rates) @property def time(self): @@ -224,8 +229,8 @@ def time(self, value): def state(self): return np.array( [ - self.prob.get_val(state_name, units=unit)[0] - for state_name, unit in zip(self.state_names, self.state_units) + self.prob.get_val(state_name, units=state_data['units'])[0] + for state_name, state_data in self.states.items() ] ) @@ -233,15 +238,17 @@ def state(self): def state(self, value): if np.all(self.state == value): return - for state_name, elem_val, unit in zip( - self.state_names, value, self.state_units + for state_name, elem_val in zip( + self.states.keys(), value ): - self.prob.set_val(state_name, elem_val, units=unit) + self.prob.set_val(state_name, elem_val, + units=self.states[state_name]['units']) def compute_along_traj(self, ts, xs): self.prob.set_val(self.t_name, ts) - for state_name, elem_val, unit in zip(self.state_names, xs.T, self.state_units): - self.prob.set_val(state_name, elem_val, units=unit) + for state_name, elem_val in zip(self.states.keys(), xs.T): + self.prob.set_val(state_name, elem_val, + units=self.states[state_name]['units']) self.prob.run_model() @@ -250,7 +257,7 @@ def control(self): return np.array( [ self.prob.get_val(control_name, units=unit)[0] - for control_name, unit in zip(self.control_names, self.control_units) + for control_name, unit in self.controls.items() ] ) @@ -260,19 +267,17 @@ def control(self, value): value = np.array([]) if (self.control.size == value.size) and np.all(self.control == value): return - for control_name, elem_val, unit in zip( - self.control_names, value, self.control_units + for control_name, elem_val in zip( + self.controls, value ): - self.prob.set_val(control_name, elem_val, units=unit) + self.prob.set_val(control_name, elem_val, units=self.controls[control_name]) @property def parameter(self): return np.array( [ self.prob.get_val(parameter_name, units=unit)[0] - for parameter_name, unit in zip( - self.parameter_names, self.parameter_units - ) + for parameter_name, unit in self.parameters.items() ] ) @@ -280,8 +285,8 @@ def parameter(self): def parameter(self, value): if np.all(self.parameter == value): return - for parameter_name, elem_val, unit in zip( - self.parameter_names, value, self.parameter_units + for parameter_name, elem_val in zip( + self.paramaters, value ): self.prob.set_val(parameter_name, elem_val) @@ -290,9 +295,7 @@ def state_rate(self): return np.array( [ self.prob.get_val(state_rate_name, units=unit)[0] - for state_rate_name, unit in zip( - self.state_rate_names, self.state_rate_units - ) + for state_rate_name, unit in self.state_rates.items() ] ) @@ -301,7 +304,7 @@ def output(self): return np.array( [ self.prob.get_val(output_name, units=unit)[0] - for output_name, unit in zip(self.output_names, self.output_units) + for output_name, unit in self.outputs.items() ] ) @@ -431,9 +434,7 @@ def setup_params( ), **self.add_output( final_state_output+final_suffix, - units=ODEs[-1].state_units[ - ODEs[-1].state_names.index(final_state_output) - ], + units=ODEs[-1].states[final_state_output]['units'], ) } for final_state_output in traj_final_state_output @@ -446,9 +447,7 @@ def setup_params( ), **self.add_output( promoted_final_output+final_suffix, - units=ODEs[-1].output_units[ - ODEs[-1].output_names.index(promoted_final_output) - ], + units=ODEs[-1].outputs[promoted_final_output], ), } for promoted_final_output in traj_promote_final_output @@ -463,9 +462,7 @@ def setup_params( **dict(name=initial_state_input+initial_suffix), **self.add_input( initial_state_input+initial_suffix, - units=ODEs[0].state_units[ - ODEs[0].state_names.index(initial_state_input) - ], + units=ODEs[0].states[initial_state_input]['units'], ) } for initial_state_input in traj_initial_state_input @@ -486,9 +483,7 @@ def setup_params( event_trigger_input[1], trigger_suffix ]), - units=event_trigger_input[0].state_units[ - event_trigger_input[0].state_names.index(event_trigger_input[1]) - ], + units=event_trigger_input[0].states[event_trigger_input[1]]['units'], ) } for event_trigger_input in traj_event_trigger_input @@ -523,7 +518,7 @@ def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None): inputs[state_name+"_initial"].squeeze() if state_name in self.traj_initial_state_input else 0. - for state_name in first_problem.state_names + for state_name in first_problem.states.keys() ]).squeeze() while True: @@ -566,10 +561,8 @@ def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None): current_problem.output_equation_function(t, x) state = np.array( [ - current_problem.prob.get_val(state_name, units=unit) - for state_name, unit in zip( - next_problem.state_names, next_problem.state_units - ) + current_problem.prob.get_val(state_name, units=state_data['units']) + for state_name, state_data in next_problem.states.items() ] ).squeeze() sim_problems.append(next_problem) @@ -588,7 +581,7 @@ def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None): outputs[output_name] = sim_results[-1].x[ -1, - sim_problems[-1].state_names.index(state_name) + list(sim_problems[-1].states.keys()).index(state_name) ] for output in self.traj_promote_final_output: @@ -597,7 +590,7 @@ def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None): outputs[promoted_name] = sim_results[-1].y[ -1, - sim_problems[-1].output_names.index(output_name) + list(sim_problems[-1].outputs.keys()).index(output_name) ] self.last_inputs = np.array(list(inputs.values())) @@ -645,13 +638,13 @@ def compute_partials(self, inputs, J): param_deriv = np.zeros(len(param_dict)) if output in self.traj_final_state_output: - costate[next_prob.state_names.index(output)] = 1. + costate[list(next_prob.states.keys()).index(output)] = 1. else: # in self.traj_promote_final_output next_prob.state_equation_function(next_res.t[-1], next_res.x[-1, :]) costate[:] = next_prob.compute_totals( output, - next_prob.state_names, + next_prob.states.keys(), return_format='array' ).squeeze() @@ -692,12 +685,12 @@ def compute_partials(self, inputs, J): num_active_event_channels += 1 dg_dx = np.zeros((1, prob.dim_state)) - if channel_name in prob.state_names: - dg_dx[0, prob.state_names.index(channel_name)] = 1. + if channel_name in prob.states.keys(): + dg_dx[0, list(prob.states.keys()).index(channel_name)] = 1. else: dg_dx[0, :] = prob.compute_totals( [channel_name], - prob.state_names, + prob.states.keys(), return_format='array' ) @@ -733,17 +726,17 @@ def compute_partials(self, inputs, J): # here and co-state assume number of states is only decreasing # forward in time - for state_name in next_prob.state_names: - state_idx = next_prob.state_names.index(state_name) + for state_name in next_prob.states.keys(): + state_idx = list(next_prob.states.keys()).index(state_name) - if state_name in prob.state_names: + if state_name in prob.states.keys(): f_plus[ state_idx - ] = plus_rate[prob.state_names.index(state_name)] + ] = plus_rate[list(prob.states.keys()).index(state_name)] # state_update[ - # next_prob.state_names.index(state_name) - # ] = x[prob.state_names.index(state_name)] + # list(next_prob.states.keys()).index(state_name) + # ] = x[list(prob.states.keys()).index(state_name)] # TODO: make sure index multiplying next_pronb costate # lines up -- since costate is pre-filled to next_prob's @@ -751,14 +744,14 @@ def compute_partials(self, inputs, J): # column should map to dh_dx[state_idx, state_idx] = 1. - elif state_name in prob.output_names: + elif state_name in prob.outputs.keys(): state_update[ state_idx - ] = res.y[-1, prob.output_names.index(state_name)] + ] = res.y[-1, list(prob.outputs.keys()).index(state_name)] dh_j_dx = prob.compute_totals( [state_name], - prob.state_names, + prob.states.keys(), return_format='array').squeeze() dh_dparam[state_idx, :] = prob.compute_totals( @@ -767,15 +760,15 @@ def compute_partials(self, inputs, J): return_format='array' ).squeeze() - for state_name_2 in prob.state_names: + for state_name_2 in prob.states.keys(): # I'm actually computing dh_dx.T # dh_dx rows are new state, columns are old state # now, dh_dx.T rows are old state, columns are new # so I think this is right dh_dx[ - next_prob.state_names.index(state_name_2), + list(next_prob.states.keys()).index(state_name_2), state_idx, - ] = dh_j_dx[prob.state_names.index(state_name_2)] + ] = dh_j_dx[list(prob.states.keys()).index(state_name_2)] else: state_update[ @@ -787,12 +780,12 @@ def compute_partials(self, inputs, J): dh_dxs.append(dh_dx) dh_dparams.append(dh_dparam) - df_dx_data[idx, :, :] = prob.compute_totals(prob.state_rate_names, - prob.state_names, + df_dx_data[idx, :, :] = prob.compute_totals(prob.state_rates.keys(), + prob.states.keys(), return_format='array').T if param_dict: df_dparam_data[idx, ...] = prob.compute_totals( - prob.state_rate_names, + prob.state_rates.keys(), list(param_dict.keys()), return_format='array' ) @@ -903,7 +896,7 @@ def compute_partials(self, inputs, J): # lamda_dot_plus = lamda_dot if self.DEBUG: if np.any(state_disc): - print("update is non-zero!", prob, prob.state_names, + print("update is non-zero!", prob, prob.states.keys(), state_disc, costate, lamda_dot) print( "inner product becomes...", @@ -912,7 +905,7 @@ def compute_partials(self, inputs, J): state_disc[None, :] @ dh_dx.T @ lamda_dot_plus[:, None] ) - print("dh_dx for", prob, prob.state_names, "\n", dh_dx) + print("dh_dx for", prob, prob.states.keys(), "\n", dh_dx) print("costate", costate) costate_update_terms = [ dh_dx.T @ costate[:, None], @@ -1009,17 +1002,17 @@ def co_state_rate(t, costate, *args): # TODO: do co-states need unit changes? probably not... for state_name in prob.state_names: - costate[next_prob.state_names.index(state_name)] = co_res.x[-1, - prob.state_names.index(state_name)] + costate[list(next_prob.states.keys()).index( + state_name)] = co_res.x[-1, list(prob.states.keys()).index(state_name)] lamda_dot_plus[ - next_prob.state_names.index(state_name) - ] = lamda_dot_plus_rate[prob.state_names.index(state_name)] + list(next_prob.states.keys()).index(state_name) + ] = lamda_dot_plus_rate[list(prob.states.keys()).index(state_name)] for state_to_deriv, metadata in self.traj_initial_state_input.items(): param_name = metadata["name"] J[output_name, param_name] = costate_reses[output][-1].x[ -1, - prob.state_names.index(state_to_deriv) + list(prob.states.keys()).index(state_to_deriv) ] for param_deriv_val, param_deriv_name in zip(param_deriv, param_dict): J[output_name, param_deriv_name] = param_deriv_val diff --git a/aviary/mission/gasp_based/phases/time_integration_phases.py b/aviary/mission/gasp_based/phases/time_integration_phases.py index 7b5865192..fa6d3f62a 100644 --- a/aviary/mission/gasp_based/phases/time_integration_phases.py +++ b/aviary/mission/gasp_based/phases/time_integration_phases.py @@ -35,8 +35,8 @@ def __init__( super().__init__( GroundrollODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), - output_names=["normal_force"], - state_names=[ + outputs=["normal_force"], + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -76,8 +76,8 @@ def __init__( ): super().__init__( RotationODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), - output_names=["normal_force", "alpha"], - state_names=[ + outputs=["normal_force", "alpha"], + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -129,13 +129,13 @@ def __init__( super().__init__( AscentODE(analysis_scheme=AnalysisScheme.SHOOTING, alpha_mode=alpha_mode, **ode_args), - output_names=[ + outputs=[ "load_factor", "fuselage_pitch", "normal_force", "alpha", ], - state_names=[ + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -258,7 +258,7 @@ def set_val(self, *args, **kwargs): ode.set_val(*args, **kwargs) def compute_alpha(self, ode, t, x): - return ode.output_equation_function(t, x)[ode.output_names.index("alpha")] + return ode.output_equation_function(t, x)[list(ode.outputs.keys()).index("alpha")] def get_alpha(self, t, x): a_key = (t,) + tuple(x) @@ -377,8 +377,8 @@ def __init__( ode = AccelODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args) super().__init__( ode, - output_names=["EAS", "mach", "alpha"], - state_names=[ + outputs=["EAS", "mach", "alpha"], + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -436,7 +436,7 @@ def __init__( self.alt_trigger_units = alt_trigger_units super().__init__( ode, - output_names=[ + outputs=[ "alpha", Dynamic.Mission.FLIGHT_PATH_ANGLE, "required_lift", @@ -448,7 +448,7 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - state_names=[ + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -507,7 +507,7 @@ def __init__( super().__init__( ode, - output_names=[ + outputs=[ "alpha", # ? "lift", "EAS", @@ -516,7 +516,7 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - state_names=[ + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, @@ -585,7 +585,7 @@ def __init__( self.alt_trigger_units = alt_trigger_units super().__init__( ode, - output_names=[ + outputs=[ "alpha", "required_lift", "lift", @@ -595,7 +595,7 @@ def __init__( "drag", Dynamic.Mission.ALTITUDE_RATE, ], - state_names=[ + states=[ Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE, Dynamic.Mission.ALTITUDE, diff --git a/aviary/mission/gasp_based/phases/time_integration_traj.py b/aviary/mission/gasp_based/phases/time_integration_traj.py index d566635d3..5e1884012 100644 --- a/aviary/mission/gasp_based/phases/time_integration_traj.py +++ b/aviary/mission/gasp_based/phases/time_integration_traj.py @@ -103,9 +103,7 @@ def compute(self, inputs, outputs): print('t_final', t_final) print('x_final', x_final) - print('states', self.ODEs[-1].state_names) - print('units', self.ODEs[-1].state_units) - + print(self.ODEs[-1].states) # class SGMTraj1(TimeIntegrationTrajBase): # ''' From 01844796a71578fea00a6118d64929757243b21d Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Mon, 22 Jan 2024 17:07:51 -0800 Subject: [PATCH 104/111] moved all rate information into the states --- .../ode/time_integration_base_classes.py | 63 ++++++------------- .../phases/time_integration_phases.py | 14 ++--- 2 files changed, 27 insertions(+), 50 deletions(-) diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index 5ad167b01..54208b01d 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -28,7 +28,6 @@ def __init__( states=None, alternate_state_names=None, blocked_state_names=None, - state_rates=None, alternate_state_rate_names=None, parameters=None, outputs=None, @@ -41,17 +40,16 @@ def __init__( ): """ - states: a dictionary of the form {state_name:{'units':unit, 'rate':state_rate_name}} - alternate_state_names: a dictionary of the form {state_to_replace:'new_state_name'} + states: a dictionary of the form {state_name:{'units':unit, 'rate':state_rate_name, 'rate_units':state_rate_units}} + alternate_state_names: a dictionary of the form {state_to_replace:new_state_name} blocked_state_names: a list of the form [state_name_to_block] - state_rates: a dictionary of the form {state_rate_name:unit} - alternate_state_rate_names: a dictionary of the form {state_rate_to_replace:'new_state_rate_name'} + alternate_state_rate_names: a dictionary of the form {state_to_modify:new_state_rate_name} parameters: a dictionary of the form {parameter_name:unit} outputs: a dictionary of the form {output_name:unit} controls: a dictionary of the form {control_name:unit} include_state_outputs : automatically add the state to the input works well for auto-parsed naming, does not check for duplication before adding - states, state_rates, parameters, outputs, and controls can also be input as a list of keys for the dictionary + states, parameters, outputs, and controls can also be input as a list of keys for the dictionary """ default_args = dict(prom_name=True, val=False, out_stream=None, units=True) @@ -77,7 +75,7 @@ def __init__( self.time_independent = time_independent if type(states) is list: - states = {state: {'units': None, 'rate': state+rate_suffix} + states = {state: {'units': None, 'rate': state+rate_suffix, 'rate_units': None} for state in states} if type(parameters) is list: parameters = {parameter: None for parameter in parameters} @@ -125,41 +123,21 @@ def __init__( if alternate_state_names: for state_key, val in alternate_state_names.items(): if state_key in states.keys(): # Used to rename an existing state - # modified_states = {} - # for name, state_data in states.items(): - # key = name if name not in alternate_state_names else alternate_state_names[name] - # modified_states[key] = state_data - # states = modified_states states[val] = states.pop(state_key) else: # Used to add a new state states[val]: {'units': None, 'rate': val+rate_suffix} - if state_rates is None: - state_rates = { - state_name + rate_suffix: None - for state_name in states.keys()} - if alternate_state_rate_names: - for rate_name, val in alternate_state_rate_names.items(): - if rate_name in state_rates.keys(): - # state_rates[val] = state_rates.pop(rate_name) - modified_rates = {} - for name, rate_data in state_rates.items(): - key = name if name not in alternate_state_rate_names else alternate_state_rate_names[ - name] - modified_rates[key] = rate_data - state_rates = modified_rates - - state_name = rate_name.replace(rate_suffix, "") - if state_name in states.keys(): - states[state_name]['rate'] = val - - data = prob.model.list_outputs(includes=state_rates.keys(), **default_args) - rate_data = {val.pop('prom_name'): val for key, val in data} - for rate_name, rate_units in state_rates.items(): - if rate_units is None: - state_rates[rate_name] = rate_data[rate_name]["units"] + if alternate_state_rate_names: + for state_name, val in alternate_state_rate_names.items(): + if state_name in states.keys(): + states[state_name]['rate'] = val + state_rate_names = [val['rate'] for _, val in states.items()] + data = prob.model.list_outputs(includes=state_rate_names, **default_args) + rate_data = {val.pop('prom_name'): val for key, val in data} for state_name, state_data in states.items(): + if state_data['rate_units'] is None: + state_data['rate_units'] = rate_data[state_data['rate']]["units"] if state_data['units'] is None: rate_unit = rate_data[state_data['rate']]["units"] states[state_name]['units'] = units.simplify_unit("s*" + rate_unit) @@ -181,7 +159,7 @@ def __init__( outputs = { outp: None for outp in outputs - if outp not in state_rates # + event_names + if outp not in state_rate_names # + event_names } for output_name, output_units in outputs.items(): @@ -197,7 +175,6 @@ def __init__( self.t_name = t_name self.states = states - self.state_rates = state_rates self.parameters = parameters self.outputs = outputs @@ -213,7 +190,6 @@ def __init__( with open('input_list_simupy.txt', 'w') as outfile: prob.model.list_inputs(out_stream=outfile,) print(states) - print(state_rates) @property def time(self): @@ -294,8 +270,8 @@ def parameter(self, value): def state_rate(self): return np.array( [ - self.prob.get_val(state_rate_name, units=unit)[0] - for state_rate_name, unit in self.state_rates.items() + self.prob.get_val(state_data['rate'], units=state_data['rate_units'])[0] + for _, state_data in self.states.items() ] ) @@ -780,12 +756,13 @@ def compute_partials(self, inputs, J): dh_dxs.append(dh_dx) dh_dparams.append(dh_dparam) - df_dx_data[idx, :, :] = prob.compute_totals(prob.state_rates.keys(), + state_rate_names = [val['rate'] for _, val in prob.states.items()] + df_dx_data[idx, :, :] = prob.compute_totals(state_rate_names, prob.states.keys(), return_format='array').T if param_dict: df_dparam_data[idx, ...] = prob.compute_totals( - prob.state_rates.keys(), + state_rate_names, list(param_dict.keys()), return_format='array' ) diff --git a/aviary/mission/gasp_based/phases/time_integration_phases.py b/aviary/mission/gasp_based/phases/time_integration_phases.py index fa6d3f62a..b0b53c5ca 100644 --- a/aviary/mission/gasp_based/phases/time_integration_phases.py +++ b/aviary/mission/gasp_based/phases/time_integration_phases.py @@ -44,7 +44,7 @@ def __init__( ], # state_units=['lbm','nmi','ft','ft/s'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) @@ -84,7 +84,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) @@ -142,7 +142,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, control_names=control_names, **simupy_args, ) @@ -385,7 +385,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) self.phase_name = phase_name @@ -455,7 +455,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) self.phase_name = phase_name @@ -523,7 +523,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) @@ -602,7 +602,7 @@ def __init__( ], # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ - Dynamic.Mission.MASS_RATE: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, + Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, **simupy_args, ) From 984cdf4c1a6ffcfea8a30c0d22dd751df4ae28c1 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Tue, 23 Jan 2024 08:57:17 -0800 Subject: [PATCH 105/111] Renamed variable for clarity --- .../gasp_based/ode/time_integration_base_classes.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py index 54208b01d..b3a8d0e17 100644 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ b/aviary/mission/gasp_based/ode/time_integration_base_classes.py @@ -52,7 +52,8 @@ def __init__( states, parameters, outputs, and controls can also be input as a list of keys for the dictionary """ - default_args = dict(prom_name=True, val=False, out_stream=None, units=True) + default_om_list_args = dict(prom_name=True, val=False, + out_stream=None, units=True) self.DEBUG = DEBUG self.max_allowable_time = max_allowable_time @@ -90,7 +91,7 @@ def __init__( if alternate_state_rate_names is None: alternate_state_rate_names = {} - data = prob.model.list_inputs(includes=controls.keys(), **default_args) + data = prob.model.list_inputs(includes=controls.keys(), **default_om_list_args) control_data = {val.pop('prom_name'): val for key, val in data} for control_name, control_units in controls.items(): if control_units is None: @@ -103,9 +104,9 @@ def __init__( or outputs is None # or # event_names is None ): - data = prob.model.list_outputs(**default_args) + data = prob.model.list_outputs(**default_om_list_args) model_outputs = [val['prom_name'] for key, val in data] - data = prob.model.list_inputs(**default_args) + data = prob.model.list_inputs(**default_om_list_args) model_inputs = [val['prom_name'] for key, val in data] if states is None: @@ -133,7 +134,7 @@ def __init__( states[state_name]['rate'] = val state_rate_names = [val['rate'] for _, val in states.items()] - data = prob.model.list_outputs(includes=state_rate_names, **default_args) + data = prob.model.list_outputs(includes=state_rate_names, **default_om_list_args) rate_data = {val.pop('prom_name'): val for key, val in data} for state_name, state_data in states.items(): if state_data['rate_units'] is None: @@ -149,7 +150,7 @@ def __init__( if inp not in list(states.keys()) + list(controls.keys()) + [t_name] } - data = prob.model.list_inputs(includes=parameters.keys(), **default_args) + data = prob.model.list_inputs(includes=parameters.keys(), **default_om_list_args) parameter_data = {val.pop('prom_name'): val for key, val in data} for parameter_name, parameter_units in parameters.items(): if parameter_units is None: From ffe4114acda28bf108293ee3a0af3adb6027bb1a Mon Sep 17 00:00:00 2001 From: Eliot Aretskin-Hariton Date: Tue, 23 Jan 2024 12:06:47 -0500 Subject: [PATCH 106/111] Update aviary/xdsm/climb_xdsm.py Co-authored-by: crecine <51181861+crecine@users.noreply.github.com> --- aviary/xdsm/climb_xdsm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/xdsm/climb_xdsm.py b/aviary/xdsm/climb_xdsm.py index cd775b221..4bf95c1ab 100644 --- a/aviary/xdsm/climb_xdsm.py +++ b/aviary/xdsm/climb_xdsm.py @@ -54,7 +54,7 @@ x.add_input("specific_energy", [Dynamic.Mission.MASS]) x.add_input("alt_rate", ["TAS_rate"]) -# make connections6 +# make connections x.connect("atmos", "fc", ["rho", Dynamic.Mission.SPEED_OF_SOUND]) # x.connect("atmos", "prop", [Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE]) x.connect("atmos", "constraints", ["rho"]) From e0bd272f09c608b5e866364e38104e4fa79e8436 Mon Sep 17 00:00:00 2001 From: Carl Recine Date: Tue, 23 Jan 2024 09:27:00 -0800 Subject: [PATCH 107/111] adding deepcopy to prevent intermittent testflo failure --- aviary/validation_cases/benchmark_tests/test_0_iters.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index baa403fad..023c7e92a 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -49,7 +49,8 @@ class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_zero_iters_height_energy(self): local_phase_info = deepcopy(height_energy_phase_info) - self.build_and_run_problem(inputs, local_phase_info) + local_inputs = deepcopy(inputs) + self.build_and_run_problem(local_inputs, local_phase_info) @use_tempdirs From 60bd15010ae3f293247e19f8fcc176b859056b43 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Tue, 23 Jan 2024 15:20:55 -0600 Subject: [PATCH 108/111] Began to tease apart initial guessing for GASP missions --- aviary/interface/methods_for_level2.py | 6 +- aviary/utils/process_input_decks.py | 66 ++++++++----------- .../benchmark_tests/test_0_iters.py | 3 +- .../benchmark_tests/test_bench_FwFm.py | 2 +- .../benchmark_tests/test_bench_GwGm.py | 10 +-- 5 files changed, 39 insertions(+), 48 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 028f05b27..d9a972284 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -39,7 +39,7 @@ from aviary.subsystems.premission import CorePreMission from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution from aviary.utils.functions import set_aviary_initial_values, Null, create_opts2vals, add_opts2vals, promote_aircraft_and_mission_vars -from aviary.utils.process_input_decks import create_vehicle, update_GASP_options +from aviary.utils.process_input_decks import create_vehicle, update_GASP_options, initial_guessing from aviary.utils.preprocessors import preprocess_crewpayload from aviary.interface.utils.check_phase_info import check_phase_info from aviary.utils.aviary_values import AviaryValues @@ -170,8 +170,8 @@ def load_inputs(self, aviary_inputs, phase_info=None, engine_builder=None): self.mass_method = mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) if mission_method is TWO_DEGREES_OF_FREEDOM or mass_method is GASP: - aviary_inputs, initial_guesses = update_GASP_options(aviary_inputs, - initial_guesses) + aviary_inputs = update_GASP_options(aviary_inputs) + initial_guesses = initial_guessing(aviary_inputs, initial_guesses) self.aviary_inputs = aviary_inputs self.initial_guesses = initial_guesses diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 4f7ea1161..ce8257965 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -52,13 +52,23 @@ def create_vehicle(vehicle_deck=''): aircraft_values = get_option_defaults(engine=False) # TODO temporary, needed until debug_mode retired in favor of new verbosity flag + # TODO remove all hardcoded GASP values here, find appropriate place for them aircraft_values.set_val('debug_mode', val=False) + aircraft_values.set_val('INGASP.JENGSZ', val=4) + aircraft_values.set_val('test_mode', val=False) + aircraft_values.set_val('use_surrogates', val=True) + aircraft_values.set_val('mass_defect', val=10000, units='lbm') + aircraft_values.set_val('problem_type', val=ProblemType.SIZING) + aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) + aircraft_values.set_val( + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, val=4998, units='lbm') if isinstance(vehicle_deck, AviaryValues): aircraft_values.update(vehicle_deck) + initial_guesses = {} else: vehicle_deck = get_path(vehicle_deck) - parse_inputs(vehicle_deck, aircraft_values) + aircraft_values, initial_guesses = parse_inputs(vehicle_deck, aircraft_values) return aircraft_values, initial_guesses @@ -77,6 +87,18 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues(), meta_data=_MetaD ------- tuple: Updated aircraft values and initial guesses. """ + initial_guesses = { + # initial_guesses is a dictionary that contains values used to initialize the trajectory + 'actual_takeoff_mass': 0, + 'rotation_mass': .99, + 'operating_empty_mass': 0, + 'fuel_burn_per_passenger_mile': 0.1, + 'cruise_mass_final': 0, + 'flight_duration': 0, + 'time_to_climb': 0, + 'climb_range': 0, + 'reserves': 0 + } guess_names = list(initial_guesses.keys()) with open(vehicle_deck, newline='') as f_in: @@ -132,7 +154,7 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues(), meta_data=_MetaD # e.g. aero preprocessor, mass preprocessor, 2DOF preprocessor, etc. -def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): +def update_GASP_options(aircraft_values: AviaryValues()): """ Updates options based on the current values in aircraft_values. This function also handles special cases and prints debug information if the debug mode is active. @@ -140,25 +162,11 @@ def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): Parameters ---------- aircraft_values (AviaryValues): An instance of AviaryValues containing current aircraft values. - initial_guesses (dict): A dictionary of initial guesses for various parameters. Returns ------- tuple: Updated aircraft values and initial guesses. """ - GASP_defaults = AviaryValues() - GASP_defaults.set_val('INGASP.JENGSZ', val=4) - GASP_defaults.set_val('test_mode', val=False) - GASP_defaults.set_val('use_surrogates', val=True) - GASP_defaults.set_val('mass_defect', val=10000, units='lbm') - GASP_defaults.set_val('problem_type', val=ProblemType.SIZING) - GASP_defaults.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - - # overwrite GASP_defaults with values from aircraft_values, then replace - # aircraft_values with this merged set - GASP_defaults.update(aircraft_values) - aircraft_values = GASP_defaults - # update the options that depend on variables update_dependent_options(aircraft_values, dependent_options) @@ -181,18 +189,13 @@ def update_GASP_options(aircraft_values: AviaryValues(), initial_guesses): aircraft_values.set_val( Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=False) - initial_guessing(aircraft_values) - if aircraft_values.get_val('debug_mode'): print('\nOptions') for key in get_keys(aircraft_values): val, units = aircraft_values.get_item(key) - print(key, val) - print('\nInitial Guesses') - for key, value in initial_guesses.items(): - print(key, value) + print(key, val, units) - return aircraft_values, initial_guesses + return aircraft_values def update_dependent_options(aircraft_values: AviaryValues(), dependent_options): @@ -227,7 +230,7 @@ def update_dependent_options(aircraft_values: AviaryValues(), dependent_options) return aircraft_values -def initial_guessing(aircraft_values: AviaryValues()): +def initial_guessing(aircraft_values: AviaryValues(), initial_guesses): """ Sets initial guesses for various aircraft parameters based on the current problem type, aircraft values, and other factors. It calculates and sets values like takeoff mass, cruise mass, flight duration, etc. @@ -336,7 +339,7 @@ def initial_guessing(aircraft_values: AviaryValues()): initial_guesses['climb_range'] = initial_guesses['time_to_climb'] / \ (60 * 60) * (avg_speed_guess * np.cos(gamma_guess)) - return aircraft_values, initial_guesses + return initial_guesses dependent_options = [ @@ -378,16 +381,3 @@ def initial_guessing(aircraft_values: AviaryValues()): [Aircraft.VerticalTail.VOLUME_COEFFICIENT, { 'val': 0, 'relation': '==', 'target': Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, 'result': True, 'alternate': False}], ] - -initial_guesses = { - # initial_guesses is a dictionary that contains values used to initialize the trajectory - 'actual_takeoff_mass': 0, - 'rotation_mass': .99, - 'operating_empty_mass': 0, - 'fuel_burn_per_passenger_mile': 0.1, - 'cruise_mass_final': 0, - 'flight_duration': 0, - 'time_to_climb': 0, - 'climb_range': 0, - 'reserves': 0 -} diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index baa403fad..023c7e92a 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -49,7 +49,8 @@ class HEZeroItersTestCase(BaseProblemPhaseTestCase): @require_pyoptsparse(optimizer="IPOPT") def test_zero_iters_height_energy(self): local_phase_info = deepcopy(height_energy_phase_info) - self.build_and_run_problem(inputs, local_phase_info) + local_inputs = deepcopy(inputs) + self.build_and_run_problem(local_inputs, local_phase_info) @use_tempdirs diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 365291916..124635e5c 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -262,7 +262,7 @@ def setUp(self): self.expected_dict = expected_dict @require_pyoptsparse(optimizer="IPOPT") - def bench_test_swap_4_FwFm(self): + def test_bench_FwFm(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, "climb": { diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index b6e6b7eb5..33ccb75a3 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -13,7 +13,7 @@ class ProblemPhaseTestCase(unittest.TestCase): @require_pyoptsparse(optimizer="IPOPT") - def bench_test_swap_2_GwGm(self): + def test_bench_GwGm(self): local_phase_info = deepcopy(phase_info) prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwGm.csv', local_phase_info, optimizer='IPOPT') @@ -22,16 +22,16 @@ def bench_test_swap_2_GwGm(self): # There are no truth values for these. assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), - 181654., tolerance=rtol) + 174039., tolerance=rtol) assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), - 101555., tolerance=rtol) + 95509, tolerance=rtol) assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), - 44098., tolerance=rtol) + 42529., tolerance=rtol) assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), - 2637.86, tolerance=rtol) + 2634.8, tolerance=rtol) assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], 3675.0, tolerance=rtol) From 679225d301b1d6a29e440b7af91ac56bcac5a2a7 Mon Sep 17 00:00:00 2001 From: johnjasa Date: Tue, 23 Jan 2024 16:15:27 -0600 Subject: [PATCH 109/111] Bench fix --- aviary/interface/methods_for_level2.py | 1 - aviary/mission/gasp_based/phases/time_integration_phases.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 9dd6ca174..d11cc6d43 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -980,7 +980,6 @@ def add_phases(self, phase_info_parameterization=None): descent_phases = create_2dof_based_descent_phases( self.ode_args, - cruise_alt=self.cruise_alt, cruise_mach=self.cruise_mach) descent_estimation = descent_range_and_fuel( diff --git a/aviary/mission/gasp_based/phases/time_integration_phases.py b/aviary/mission/gasp_based/phases/time_integration_phases.py index b0b53c5ca..a972070cd 100644 --- a/aviary/mission/gasp_based/phases/time_integration_phases.py +++ b/aviary/mission/gasp_based/phases/time_integration_phases.py @@ -125,7 +125,7 @@ def __init__( ode_args={}, simupy_args={}, ): - control_names = None + controls = None super().__init__( AscentODE(analysis_scheme=AnalysisScheme.SHOOTING, alpha_mode=alpha_mode, **ode_args), @@ -143,7 +143,7 @@ def __init__( # state_units=['lbm','nmi','ft'], alternate_state_rate_names={ Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - control_names=control_names, + controls=controls, **simupy_args, ) From bfd4c9e62e4169abf5754749e762c357f28a315b Mon Sep 17 00:00:00 2001 From: johnjasa Date: Tue, 23 Jan 2024 16:37:05 -0600 Subject: [PATCH 110/111] updating bench --- .../mission/gasp_based/ode/flight_path_ode.py | 7 +++--- .../benchmark_tests/test_bench_FwFm.py | 17 +++++++++---- .../benchmark_tests/test_bench_FwGm.py | 24 +++++++++++++++++++ .../benchmark_tests/test_bench_GwFm.py | 15 +++++++++--- .../benchmark_tests/test_bench_GwGm.py | 24 +++++++++++++++++++ 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/aviary/mission/gasp_based/ode/flight_path_ode.py b/aviary/mission/gasp_based/ode/flight_path_ode.py index 1e757b0d7..1ec3fab63 100644 --- a/aviary/mission/gasp_based/ode/flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/flight_path_ode.py @@ -8,9 +8,6 @@ from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.flight_path_eom import FlightPathEOM from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import (CruiseAero, - LowSpeedAero) -from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate @@ -285,7 +282,9 @@ def setup(self): 'alpha_comp', 'prop_group', 'eoms', - 'mass_trigger' + 'mass_trigger', + 'SPECIFIC_ENERGY_RATE_EXCESS', + 'ALTITUDE_RATE_MAX', ] + debug_comp) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 124635e5c..26a9c672d 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -261,8 +261,6 @@ def setUp(self): self.expected_dict = expected_dict - @require_pyoptsparse(optimizer="IPOPT") - def test_bench_FwFm(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, "climb": { @@ -349,8 +347,19 @@ def test_bench_FwFm(self): }, } + self.phase_info = phase_info + + @require_pyoptsparse(optimizer="IPOPT") + def test_bench_FwFm(self): + prob = run_aviary( + 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, max_iter=50, optimizer='IPOPT') + + compare_against_expected_values(prob, self.expected_dict) + + @require_pyoptsparse(optimizer="SNOPT") + def test_bench_FwFm_SNOPT(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, max_iter=50, optimizer='IPOPT') + 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, max_iter=50, optimizer='SNOPT') compare_against_expected_values(prob, self.expected_dict) @@ -358,4 +367,4 @@ def test_bench_FwFm(self): if __name__ == '__main__': test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_4_FwFm() + test.test_bench_FwFm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index 437e0eee7..6119cf699 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -36,6 +36,30 @@ def bench_test_swap_3_FwGm(self): assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], 3675.0, tolerance=rtol) + @require_pyoptsparse(optimizer="SNOPT") + def bench_test_swap_3_FwGm_SNOPT(self): + local_phase_info = deepcopy(phase_info) + prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwGm.csv', + local_phase_info, optimizer='SNOPT') + + rtol = 1e-2 + + # There are no truth values for these. + assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), + 186418., tolerance=rtol) + + assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), + 104530., tolerance=rtol) + + assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), + 44032., tolerance=rtol) + + assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), + 2528., tolerance=rtol) + + assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], + 3675.0, tolerance=rtol) + if __name__ == "__main__": # unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 129d71978..ae9dd722c 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -267,8 +267,6 @@ def setUp(self): self.expected_dict = expected_dict - @require_pyoptsparse(optimizer="IPOPT") - def bench_test_swap_1_GwFm(self): phase_info = { "pre_mission": {"include_takeoff": True, "optimize_mass": True}, "climb": { @@ -355,11 +353,22 @@ def bench_test_swap_1_GwFm(self): }, } - prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info, + self.phase_info = phase_info + + @require_pyoptsparse(optimizer="IPOPT") + def bench_test_swap_1_GwFm(self): + prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', self.phase_info, max_iter=50, optimizer='IPOPT') compare_against_expected_values(prob, self.expected_dict) + @require_pyoptsparse(optimizer="SNOPT") + def bench_test_swap_1_GwFm_SNOPT(self): + prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwFm.csv', self.phase_info, + max_iter=50, optimizer='SNOPT') + + compare_against_expected_values(prob, self.expected_dict) + if __name__ == '__main__': test = ProblemPhaseTestCase() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 33ccb75a3..6547dd59b 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -36,6 +36,30 @@ def test_bench_GwGm(self): assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], 3675.0, tolerance=rtol) + @require_pyoptsparse(optimizer="SNOPT") + def test_bench_GwGm_SNOPT(self): + local_phase_info = deepcopy(phase_info) + prob = run_aviary('models/test_aircraft/aircraft_for_bench_GwGm.csv', + local_phase_info, optimizer='SNOPT') + + rtol = 0.01 + + # There are no truth values for these. + assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), + 174039., tolerance=rtol) + + assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), + 95509, tolerance=rtol) + + assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), + 42529., tolerance=rtol) + + assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), + 2634.8, tolerance=rtol) + + assert_near_equal(prob.get_val("traj.desc2.timeseries.states:distance")[-1], + 3675.0, tolerance=rtol) + if __name__ == '__main__': # unittest.main() From 4e5121b5478e1f256cb641c2b3b3cd01a284bbbd Mon Sep 17 00:00:00 2001 From: johnjasa Date: Wed, 24 Jan 2024 11:04:45 -0600 Subject: [PATCH 111/111] PR feedback --- aviary/utils/process_input_decks.py | 7 +++++-- aviary/validation_cases/benchmark_tests/test_bench_FwGm.py | 2 +- aviary/validation_cases/benchmark_tests/test_bench_GwFm.py | 2 +- aviary/validation_cases/benchmark_tests/test_bench_GwGm.py | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index ce8257965..0250a2a2f 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -60,8 +60,6 @@ def create_vehicle(vehicle_deck=''): aircraft_values.set_val('mass_defect', val=10000, units='lbm') aircraft_values.set_val('problem_type', val=ProblemType.SIZING) aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) - aircraft_values.set_val( - Aircraft.Design.RESERVE_FUEL_ADDITIONAL, val=4998, units='lbm') if isinstance(vehicle_deck, AviaryValues): aircraft_values.update(vehicle_deck) @@ -339,6 +337,11 @@ def initial_guessing(aircraft_values: AviaryValues(), initial_guesses): initial_guesses['climb_range'] = initial_guesses['time_to_climb'] / \ (60 * 60) * (avg_speed_guess * np.cos(gamma_guess)) + if aircraft_values.get_val('debug_mode'): + print('\nInitial Guesses') + for key, value in initial_guesses.items(): + print(key, value) + return initial_guesses diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index 6119cf699..c8c9dae3c 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -64,4 +64,4 @@ def bench_test_swap_3_FwGm_SNOPT(self): if __name__ == "__main__": # unittest.main() test = ProblemPhaseTestCase() - test.bench_test_swap_3_FwGm() + test.bench_test_swap_3_FwGm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index ae9dd722c..7270f242e 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -373,4 +373,4 @@ def bench_test_swap_1_GwFm_SNOPT(self): if __name__ == '__main__': test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_1_GwFm() + test.bench_test_swap_1_GwFm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 6547dd59b..5a194e8c7 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -64,4 +64,4 @@ def test_bench_GwGm_SNOPT(self): if __name__ == '__main__': # unittest.main() test = ProblemPhaseTestCase() - test.bench_test_swap_2_GwGm() + test.test_bench_GwGm_SNOPT()