From a5248695f9f39072a19bb0d883dc7721a822a14a Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 20 Dec 2024 11:39:55 -0500 Subject: [PATCH 01/30] Updated printout control using verbosity Renamed input_filename argument to input_data --- aviary/interface/methods_for_level1.py | 39 +++++++--- aviary/interface/methods_for_level2.py | 103 +++++++++++++++++++------ aviary/utils/process_input_decks.py | 16 ++-- 3 files changed, 115 insertions(+), 43 deletions(-) diff --git a/aviary/interface/methods_for_level1.py b/aviary/interface/methods_for_level1.py index 363f58e6c..632495a1f 100644 --- a/aviary/interface/methods_for_level1.py +++ b/aviary/interface/methods_for_level1.py @@ -11,11 +11,21 @@ from aviary.utils.functions import get_path -def run_aviary(aircraft_filename, phase_info, optimizer=None, - analysis_scheme=AnalysisScheme.COLLOCATION, objective_type=None, - record_filename='problem_history.db', restart_filename=None, max_iter=50, - run_driver=True, make_plots=True, phase_info_parameterization=None, - optimization_history_filename=None, verbosity=Verbosity.BRIEF): +def run_aviary( + aircraft_data, + phase_info, + optimizer=None, + analysis_scheme=AnalysisScheme.COLLOCATION, + objective_type=None, + record_filename='problem_history.db', + restart_filename=None, + max_iter=50, + run_driver=True, + make_plots=True, + phase_info_parameterization=None, + optimization_history_filename=None, + verbosity=None, +): """ Run the Aviary optimization problem for a specified aircraft configuration and mission. @@ -26,8 +36,9 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, Parameters ---------- - aircraft_filename : str - Filename from which to load the aircraft and options data. + aircraft_data: str, Path, AviaryValues + Filename from which to load the aircraft and options data, either as a string or + Path object, or an AviaryValues object containing that information. phase_info : dict Information about the phases of the mission. optimizer : str @@ -52,8 +63,9 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, optimization_history_filename : str or Path The name of the database file where the driver iterations are to be recorded. The default is None. - verbosity : Verbosity or int + verbosity : Verbosity or int, optional Sets level of information outputted to the terminal during model execution. + If provided, overwrites verbosity specified in aircraft_filename. Returns ------- @@ -66,15 +78,18 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, It raises warnings or errors if there are clashing user inputs. Users can modify or add methods to alter the Aviary problem's behavior. """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) + # If loading from a file, use filename as problem name. Else, use OpenMDAO default + if isinstance(aircraft_data, (str, Path)): + name = Path(aircraft_data).stem + else: + name = None # Build problem - prob = AviaryProblem(analysis_scheme, name=Path(aircraft_filename).stem) + prob = AviaryProblem(analysis_scheme, name=name, verbosity=verbosity) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(aircraft_filename, phase_info, verbosity=verbosity) + prob.load_inputs(aircraft_data, phase_info, verbosity=verbosity) # Preprocess inputs prob.check_and_preprocess_inputs() diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index d7a4f21df..1d48f339a 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -236,7 +236,9 @@ class AviaryProblem(om.Problem): additional methods to help users create and solve Aviary problems. """ - def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): + def __init__( + self, analysis_scheme=AnalysisScheme.COLLOCATION, verbosity=None, **kwargs + ): # Modify OpenMDAO's default_reports for this session. new_reports = ['subsystems', 'mission', 'timeseries_csv', 'run_status'] for report in new_reports: @@ -246,6 +248,7 @@ def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): super().__init__(**kwargs) self.timestamp = datetime.now() + self.verbosity = verbosity self.model = AviaryGroup() self.pre_mission = PreMissionGroup() @@ -260,7 +263,14 @@ def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): self.regular_phases = [] self.reserve_phases = [] - def load_inputs(self, aviary_inputs, phase_info=None, engine_builders=None, meta_data=BaseMetaData, verbosity=Verbosity.BRIEF): + def load_inputs( + self, + aircraft_data, + phase_info=None, + engine_builders=None, + meta_data=BaseMetaData, + verbosity=None, + ): """ This method loads the aviary_values inputs and options that the user specifies. They could specify files to load and values to @@ -271,13 +281,22 @@ def load_inputs(self, aviary_inputs, phase_info=None, engine_builders=None, meta This method is not strictly necessary; a user could also supply an AviaryValues object and/or phase_info dict of their own. """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) + # We haven't read the input file yet, so by default self.verbosity is None + if self.verbosity is None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity + ## LOAD INPUT FILE ### # Create AviaryValues object from file (or process existing AviaryValues object # with default values from metadata) and generate initial guesses aviary_inputs, initialization_guesses = create_vehicle( - aviary_inputs, meta_data=meta_data, verbosity=verbosity) + aircraft_data, meta_data=meta_data, verbosity=verbosity + ) + + # Now that the input file has been read, we have the desired verbosity for this + # run stored in aviary_inputs. Save this to self. # pull which methods will be used for subsystems and mission self.mission_method = mission_method = aviary_inputs.get_val( @@ -1633,7 +1652,9 @@ def connect_with_common_params(self, source, target): for source, target in connect_map.items(): connect_with_common_params(self, source, target) - def add_driver(self, optimizer=None, use_coloring=None, max_iter=50, verbosity=Verbosity.BRIEF): + def add_driver( + self, optimizer=None, use_coloring=None, max_iter=50, verbosity=None + ): """ Add an optimization driver to the Aviary problem. @@ -1662,12 +1683,16 @@ def add_driver(self, optimizer=None, use_coloring=None, max_iter=50, verbosity=V ------- None """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) + # override verbosity for this function call if user desired + if verbosity is None: + verbsity = self.verbosity + else: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) # Set defaults for optimizer and use_coloring based on analysis scheme if optimizer is None: - optimizer = 'IPOPT' if self.analysis_scheme is AnalysisScheme.SHOOTING else 'SNOPT' + optimizer = 'IPOPT' # if self.analysis_scheme is AnalysisScheme.SHOOTING else 'SNOPT' if use_coloring is None: use_coloring = False if self.analysis_scheme is AnalysisScheme.SHOOTING else True @@ -1679,59 +1704,78 @@ def add_driver(self, optimizer=None, use_coloring=None, max_iter=50, verbosity=V driver.options["optimizer"] = optimizer if use_coloring: - driver.declare_coloring() + # define coloring options by verbosity + if verbosity <= Verbosity.VERBOSE: # if QUIET, BRIEF + driver.declare_coloring(show_summary=False) + elif verbosity == Verbosity.DEBUG: + driver.declare_coloring(show_summary=True, show_sparsity=True) + else: # if VERBOSE + driver.declare_coloring(show_summary=True) if driver.options["optimizer"] == "SNOPT": + # Print Options # if verbosity == Verbosity.QUIET: isumm, iprint = 0, 0 elif verbosity == Verbosity.BRIEF: isumm, iprint = 6, 0 elif verbosity > Verbosity.BRIEF: isumm, iprint = 6, 9 + driver.opt_settings["iSumm"] = isumm + driver.opt_settings["iPrint"] = iprint + # Optimizer Settings # driver.opt_settings["Major iterations limit"] = max_iter driver.opt_settings["Major optimality tolerance"] = 1e-4 driver.opt_settings["Major feasibility tolerance"] = 1e-7 - driver.opt_settings["iSumm"] = isumm - driver.opt_settings["iPrint"] = iprint + elif driver.options["optimizer"] == "IPOPT": + # Print Options # if verbosity == Verbosity.QUIET: - print_level = 3 # minimum to get exit status + # print_level = 3 # minimum to get exit status + print_level = 0 driver.opt_settings['print_user_options'] = 'no' elif verbosity == Verbosity.BRIEF: - print_level = 5 + # print_level = 5 + print_level = 3 driver.opt_settings['print_user_options'] = 'no' driver.opt_settings['print_frequency_iter'] = 10 elif verbosity == Verbosity.VERBOSE: print_level = 5 else: # DEBUG print_level = 7 + driver.opt_settings['print_level'] = print_level + # Optimizer Settings # driver.opt_settings['tol'] = 1.0E-6 driver.opt_settings['mu_init'] = 1e-5 driver.opt_settings['max_iter'] = max_iter - driver.opt_settings['print_level'] = print_level # for faster convergence driver.opt_settings['nlp_scaling_method'] = 'gradient-based' driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas' driver.opt_settings['mu_strategy'] = 'monotone' + elif driver.options["optimizer"] == "SLSQP": + # Print Options # if verbosity == Verbosity.QUIET: disp = False else: disp = True + driver.options["disp"] = disp + # Optimizer Settings # driver.options["tol"] = 1e-9 driver.options["maxiter"] = max_iter - driver.options["disp"] = disp + + # pyoptsparse print settings, optimizer agnostic + # if optimizer in ("SNOPT", "IPOPT"): + if verbosity == Verbosity.QUIET: + driver.options['print_results'] = False + elif verbosity < Verbosity.DEBUG: + driver.options['print_results'] = 'minimal' if verbosity > Verbosity.QUIET: if isinstance(verbosity, list): - driver.options['debug_print'] = verbosity + driver.options['debug_print'] = ['desvars'] elif verbosity == Verbosity.DEBUG: driver.options['debug_print'] = ['desvars', 'ln_cons', 'nl_cons', 'objs'] - if optimizer in ("SNOPT", "IPOPT"): - if verbosity == Verbosity.QUIET: - driver.options['print_results'] = False - elif verbosity < Verbosity.DEBUG: - driver.options['print_results'] = 'minimal' + driver.options['print_opt_prob'] = True def add_design_variables(self): """ @@ -2343,8 +2387,8 @@ def run_aviary_problem(self, make_plots : bool, optional If True (default), Dymos html plots will be generated as part of the output. """ - - if self.aviary_inputs.get_val(Settings.VERBOSITY).value >= 2: + verbosity = self.aviary_inputs.get_val(Settings.VERBOSITY) + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG self.final_setup() with open('input_list.txt', 'w') as outfile: self.model.list_inputs(out_stream=outfile) @@ -2366,11 +2410,20 @@ def run_aviary_problem(self, failed = self.run_model() warnings.filterwarnings('default', category=UserWarning) - if self.aviary_inputs.get_val(Settings.VERBOSITY).value >= 2: + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG with open('output_list.txt', 'w') as outfile: self.model.list_outputs(out_stream=outfile) + # TODO use failed.exit_status or failed.sucess for better query? + # TODO this is only used in a single test. Either this should be removed, or + # rework this option to be more helpful (store entired "failed" object?) + # and implement more rigorously in benchmark tests self.problem_ran_successfully = not failed + # Manually print out a failure message for low verbosity modes that suppress + # optimizer printouts, which may include the results message. Assumes success, + # alerts user on a failure + if failed.exit_status == "FAIL" and verbosity <= Verbosity.BRIEF: # QUIT, BRIEF + print("Aviary run failed. See the dashboard for more details.") def alternate_mission(self, run_mission=True, json_filename='sizing_problem.json', diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 6057925fe..e5f7dae61 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -43,11 +43,16 @@ def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): Parameters ---------- - vehicle_deck (str): - Path to the vehicle deck file. Default is an empty string. + vehicle_deck (str, AviaryValues): + Path to the vehicle deck file, or an AviaryValues object that contains aircraft + inputs. Default is an empty string. meta_data (dict): Variable metadata used when reading input file for unit validation, - default values, and other checks + default values, and other checks. + verbosity (int, Verbosity): + Verbosity level for the AviaryProblem. If provided, this overrides verbosity + specified in the aircraft data. Default is None, and verbosity will be taken + from aircraft data or defaulted to Verbosity.BRIEF is not found. Returns ------- @@ -89,7 +94,7 @@ def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): vehicle_deck=vehicle_deck, aircraft_values=aircraft_values, initialization_guesses=initialization_guesses, meta_data=meta_data) # make sure verbosity is always set - # if verbosity set via parameter, use that + # if verbosity set via parameter, use that - override what is in the file if verbosity is not None: # Enum conversion here, so user can pass either number or actual Enum as parameter aircraft_values.set_val(Settings.VERBOSITY, Verbosity(verbosity)) @@ -117,7 +122,6 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initializat """ if aircraft_values is None: aircraft_values = AviaryValues() - aircraft_values.set_val(Settings.VERBOSITY, Verbosity.BRIEF) if initialization_guesses is None: initialization_guesses = {} @@ -166,7 +170,7 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initializat continue elif var_name.startswith('initialization_guesses:'): - # get values labelled as initialization_guesses in .csv input file + # get values labeled as initialization_guesses in .csv input file initialization_guesses[var_name.removeprefix( 'initialization_guesses:')] = float(var_values[0]) continue From 834f6775e76614e1008db0ddc491725e8a7122a3 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 20 Dec 2024 11:41:09 -0500 Subject: [PATCH 02/30] fix warnings appearing in tests --- aviary/models/N3CC/N3CC_data.py | 1 + aviary/subsystems/mass/flops_based/wing_detailed.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/N3CC/N3CC_data.py index 4b4d66971..c155e8d30 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/N3CC/N3CC_data.py @@ -197,6 +197,7 @@ inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 0.0) num_engines = 2 inputs.set_val(Aircraft.Engine.NUM_ENGINES, num_engines) +inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) num_fuselage_engines = 0 inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuselage_engines) num_wing_engines = num_engines diff --git a/aviary/subsystems/mass/flops_based/wing_detailed.py b/aviary/subsystems/mass/flops_based/wing_detailed.py index c6f825bd8..eb105f79c 100644 --- a/aviary/subsystems/mass/flops_based/wing_detailed.py +++ b/aviary/subsystems/mass/flops_based/wing_detailed.py @@ -226,7 +226,9 @@ def compute(self, inputs, outputs): bte = 8 * np.sum((ea[:-1] + ea[1:]) * dy[:-1] * 0.5) - inertia_factor[i] = 1 - bte / bt * pod_mass[i] / gross_mass + inertia_factor_i = 1 - bte / bt * pod_mass[i] / gross_mass + # avoid passing an array into specific index of inertia_factor + inertia_factor[i] = inertia_factor_i[0] # increment idx to next engine set idx = idx2 From 2c494bf46957aa08630eba61917cfd3b4ec6cfae Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 20 Dec 2024 11:41:32 -0500 Subject: [PATCH 03/30] added backup for failed benchmark tests due to mpi failure --- aviary/run_all_benchmarks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aviary/run_all_benchmarks.py b/aviary/run_all_benchmarks.py index 6d9a2c3ce..f3f40f81e 100644 --- a/aviary/run_all_benchmarks.py +++ b/aviary/run_all_benchmarks.py @@ -1,3 +1,7 @@ import subprocess -subprocess.run(["testflo", "--testmatch=bench_test*"]) +status = subprocess.run(["testflo", "--testmatch=bench_test*"]) +if status.returncode == 1: + # disable mpi and try again - can cause PermissionError for "forbidden sockets" + print('Re-running all benchmark tests with MPI disabled') + subprocess.run(["testflo", "--testmatch=bench_test*", "--nompi"]) From c7f307258176819a0dc24fdcba0e70c2236f18dd Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 20 Dec 2024 17:50:29 -0500 Subject: [PATCH 04/30] fixed missing variable & updated associated tests --- .../test_aircraft/aircraft_for_bench_GwFm.csv | 2 +- .../benchmark_tests/test_bench_GwFm.py | 345 ++++++------------ 2 files changed, 106 insertions(+), 241 deletions(-) diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 703c223d2..092cfcf3e 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -59,7 +59,7 @@ 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: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 diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 7953cbeff..4ac45c992 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -27,250 +27,115 @@ class ProblemPhaseTestCase(unittest.TestCase): def setUp(self): expected_dict = {} - expected_dict['times'] = np.array([[120.], - [163.76271231], - [224.1463232], - [243.25752959], - [243.25752959], - [336.40818102], - [464.93706768], - [505.61602085], - [505.61602085], - [626.4698655], - [793.2235045], - [846.0004611], - [846.0004611], - [966.85430575], - [1133.60794474], - [1186.38490134], - [1186.38490134], - [1279.53555278], - [1408.06443943], - [1448.74339261], - [1448.74339261], - [1492.50610492], - [1552.88971581], - [1572.0009222], - [1572.0009222], - [10224.86854151], - [22164.05978091], - [25942.77298722], - [25942.77298722], - [26009.89831864], - [26102.51757551], - [26131.83125364], - [26131.83125364], - [26268.92025959], - [26458.07510754], - [26517.94197018], - [26517.94197018], - [26680.92723458], - [26905.81363368], - [26976.98941009], - [26976.98941009], - [27114.07841604], - [27303.23326399], - [27363.10012663], - [27363.10012663], - [27430.22545805], - [27522.84471492], - [27552.15839306]]) + # block auto-formatting of tables + # autopep8: off + # fmt: off + expected_dict['times'] = np.array( + [ + [0.0], [55.733689551933274], [132.63480572667558], [156.97374606550738], + [156.97374606550738], [275.60509258726296], [439.29213778700404], + [491.0985279348842], [491.0985279348842], [645.0110782250607], + [857.378983629686], [924.5926995890327], [924.5926995890327], + [1078.505249879209], [1290.8731552838344], [1358.0868712431811], + [1358.0868712431811], [1476.7182177649368], [1640.4052629646778], + [1692.211653112558], [1692.211653112558], [1747.9453426644914], + [1824.8464588392337], [1849.1853991780654], [1849.1853991780654], + [10330.947200407132], [22034.04733403507], [25738.038512583124], + [25738.038512583124], [25812.86796688032], [25916.117340902812], + [25948.795414763863], [25948.795414763863], [26101.61842940165], + [26312.482997983352], [26379.22091297826], [26379.22091297826], + [26560.912356969104], [26811.609465928253], [26890.954243762288], + [26890.954243762288], [27043.777258400078], [27254.64182698178], + [27321.379741976685], [27321.379741976685], [27396.20919627388], + [27499.458570296378], [27532.136644157425] + ] - expected_dict['altitudes'] = np.array([[10.668], - [0.], - [1176.78911697], - [1673.72886901], - [1673.72886901], - [3865.01102367], - [6195.61836863], - [6782.34302216], - [6782.34302216], - [8109.95869793], - [9272.93435889], - [9556.37792864], - [9556.37792864], - [10094.94809064], - [10559.35775736], - [10627.1932692], - [10627.1932692], - [10668.], - [10650.08598518], - [10649.95573356], - [10649.95573356], - [10657.29116463], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10307.54164946], - [10143.7274239], - [10143.7274239], - [9248.78597393], - [7827.69756506], - [7363.41307882], - [7363.41307882], - [6126.8939629], - [4470.55591283], - [3951.86624585], - [3951.86624585], - [2939.92813668], - [1471.34739294], - [982.44499735], - [982.44499735], - [449.58751714], - [10.83591043], - [10.668]]) + ) + + expected_dict['altitudes'] = np.array( + [ + [10.668000000000001], [235.4160647585811], [1280.7577161762033], + [1789.2240867373423], [1789.2240867373423], [4166.117812322907], + [6429.223292405268], [6899.915227304244], [6899.9152273042455], + [8008.2327449168815], [9160.939977223055], [9434.801587464375], + [9434.801587464375], [9935.29924394527], [10374.555901691507], + [10452.8629164997], [10452.8629164997], [10548.73019817695], + [10626.562722425131], [10638.043597267682], [10638.04359726768], + [10647.591875522832], [10662.732889513021], [10668.0], [10668.0], + [10668.0], [10668.0], [10668.0], [10668.0], [10626.3697117778], + [10459.417512771737], [10380.121892016292], [10380.121892016292], + [9838.94107534588], [8630.540312914369], [8136.5517903851705], + [8136.551790385171], [6731.689477098073], [4835.959501956426], + [4246.281358548518], [4246.281358548521], [3120.32996645691], + [1583.2631997282303], [1100.7768687071518], [1100.7768687071516], + [633.0094751176282], [224.47289606969227], [152.4000000000001] + ] + ) - expected_dict['masses'] = np.array([[68463.53921924], - [68388.16396576], - [68245.77323713], - [68201.21751908], - [68201.21751908], - [68008.46518048], - [67807.59357082], - [67754.96222353], - [67754.96222353], - [67619.16435342], - [67463.77290019], - [67418.37147793], - [67418.37147793], - [67321.58684141], - [67204.00255349], - [67170.96641995], - [67170.96641995], - [67116.2987407], - [67044.08894595], - [67020.83854678], - [67020.83854678], - [66995.00611866], - [66954.5572371], - [66939.76926892], - [66939.76926892], - [61880.26581581], - [55221.27982315], - [53175.67231214], - [53175.67231214], - [53158.01594442], - [53144.299632], - [53140.88521042], - [53140.88521042], - [53127.49149749], - [53111.02960542], - [53105.82637933], - [53105.82637933], - [53090.66670078], - [53066.21593581], - [53057.26691014], - [53057.26691014], - [53038.09861563], - [53006.77727746], - [52995.48090755], - [52995.48090755], - [52981.90805198], - [52962.16924161], - [52955.84313972]]) + expected_dict['masses'] = np.array( + [ + [77818.91890875385], [77688.27501012207], [77524.23950674829], + [77468.76019046773], [77468.76019046773], [77239.22039657168], + [76990.73913506811], [76926.80036671055], [76926.80036671055], + [76754.33897227133], [76543.86405635109], [76483.7192616358], + [76483.7192616358], [76354.17352305444], [76191.31940576647], + [76143.67243567819], [76143.67243567819], [76062.24259563042], + [75953.47376577006], [75919.91738782128], [75919.91738782128], + [75883.75438725074], [75832.8423125292], [75816.45141024028], + [75816.45141024028], [70515.89266171536], [63632.18566842271], + [61543.65557306416], [61543.65557306416], [61512.493641635716], + [61475.15980565045], [61464.41311500414], [61464.41311500414], + [61421.476775837866], [61381.46504437594], [61373.33572196399], + [61373.33572196399], [61354.67797641075], [61326.43296400884], + [61316.4035933201], [61316.4035933201], [61294.97892209769], + [61260.38645390502], [61247.776381418495], [61247.776381418495], + [61232.816693577166], [61211.323048859755], [61204.500051063435] + ] + ) - expected_dict['ranges'] = np.array([[1166.20699576], - [5593.37409715], - [15160.34254633], - [18452.29987419], - [18452.29987419], - [35953.4905749], - [61610.20915607], - [69693.60643145], - [69693.60643145], - [94109.378342], - [128861.35815474], - [140228.92014561], - [140228.92014561], - [166663.67193054], - [203797.88470247], - [215616.8251792], - [215616.8251792], - [236507.17277307], - [265348.67959522], - [274478.82401463], - [274478.82401463], - [284316.3485801], - [298061.71411326], - [302496.32074313], - [302496.32074313], - [2329499.36229261], - [5126349.84245871], - [6011543.45679734], - [6011543.45679734], - [6026497.11291725], - [6044998.00245228], - [6050451.95986915], - [6050451.95986915], - [6074179.71278433], - [6103973.32165406], - [6113145.04319224], - [6113145.04319224], - [6137396.13533869], - [6169641.84998078], - [6179602.4331379], - [6179602.4331379], - [6198630.75436767], - [6224716.73281895], - [6232974.51970883], - [6232974.51970883], - [6242235.03685456], - [6254092.42671214], - [6257352.4]]) + expected_dict['ranges'] = np.array( + [ + [1410.7246267645853], [7495.3855075223], [20669.444649304616], + [25331.75944015018], [25331.75944015018], [48156.17760692068], + [80276.4395807753], [90751.64747645857], [90751.64747645857], + [123003.73379975135], [169609.2345943904], [184688.57605961812], + [184688.57605961812], [219574.63609561243], [268234.4654645649], + [283700.48601368495], [283700.48601368495], [311021.12460668734], + [348717.6854537568], [360638.7338207807], [360638.7338207807], + [373458.75114105834], [391178.95399686357], [396804.3683204999], + [396804.3683204999], [2359117.1786281476], [5066704.90400833], + [5923646.330821189], [5923646.330821189], [5940603.245546197], + [5962922.359248149], [5969751.264817894], [5969751.264817894], + [6000362.008167493], [6039449.319180842], [6051171.448664183], + [6051171.448664183], [6081755.279179599], [6121391.20765825], + [6133468.632684376], [6133468.632684376], [6156271.164261458], + [6186727.665526107], [6196116.484579935], [6196116.484579935], + [6206400.38654244], [6219220.724162429], [6222720.0] + ] + ) - expected_dict['velocities'] = np.array([[64.4147653], - [133.69502146], - [174.31936373], - [180.24083219], - [180.24083219], - [196.61398458], - [200.67345509], - [200.77798066], - [200.77798066], - [204.32902616], - [213.53269554], - [216.30794138], - [216.30794138], - [220.90502555], - [223.85447586], - [224.18464453], - [224.18464453], - [224.33459955], - [224.43913124], - [224.63981271], - [224.63981271], - [225.38258712], - [230.7187408], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [212.06605788], - [188.96924746], - [183.2491682], - [183.2491682], - [164.64559845], - [153.53645555], - [151.57537965], - [151.57537965], - [146.52626765], - [140.88518413], - [139.7046818], - [139.7046818], - [138.44302405], - [138.07991553], - [138.08432897], - [138.08432897], - [136.46253134], - [116.34759903], - [102.07377559]]) + expected_dict['velocities'] = np.array( + [ + [70.41872863051675], [142.8426782139169], [190.85388104256134], + [193.53336168014812], [193.5333616801481], [193.97130207062534], + [200.66615582138846], [204.29712966333042], [204.2971296633304], + [214.52894401730563], [223.53071066321067], [225.23147649896515], + [225.23147649896515], [227.9612963574697], [229.9799417501587], + [230.21437887976137], [230.21437887976137], [230.34923495762445], + [230.1753140630945], [230.03381353938522], [230.0338135393852], + [230.08808978229095], [230.9140856209351], [231.35686943957475], + [231.35686943957478], [231.3566224727587], [231.35628170895902], + [231.35617385838154], [231.35617385838154], [222.01301741383028], + [210.6244396832895], [207.37442023458655], [207.3744202345866], + [193.625244800323], [177.92188888735785], [173.6922435472287], + [173.69224354722866], [163.6940205640424], [153.58581070698628], + [151.343324702535], [151.343324702535], [147.41604989710945], + [141.78284140393103], [139.9518515787329], [139.95185157873289], + [133.84033631181276], [112.04151628392903], [101.91044471952507] + ] + ) + # autopep8: on + # fmt: on self.expected_dict = expected_dict From 7102ba6765cb0388f5f55fc5f36b1f261495468b Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 23 Dec 2024 12:17:15 -0500 Subject: [PATCH 05/30] mass variable naming updates --- aviary/variable_info/variable_meta_data.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 6ef0e83de..e5076dcc1 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1221,11 +1221,11 @@ historical_name={ "GASP": None, # ['&DEFMSS.MISSIN.DOWE', '&FLOPS.RERUN.DOWE', 'ESB.DOWE'], - "FLOPS": 'MISSIN.DOWE', - "LEAPS1": 'aircraft.inputs.L0_mission.fixed_operating_weight_empty', + "FLOPS": None, + "LEAPS1": None, }, units='lbm', - desc='fixed operating empty mass', + desc='empty mass of the aircraft', default_value=0.0, ) @@ -1405,14 +1405,16 @@ historical_name={ "GASP": 'INGASP.OWE', # ['WTS.WSP(33, 2)', '~WEIGHT.WOWE', '~WTSTAT.WSP(33, 2)'], - "FLOPS": None, + "FLOPS": 'MISSIN.DOWE', "LEAPS1": [ '(WeightABC)self._operating_weight_empty', 'aircraft.outputs.L0_weights_summary.operating_weight_empty', ], }, units='lbm', - desc='operating mass empty of the aircraft', + desc='operating mass of the aircraft, or aircraft mass without mission fuel, or ' + 'passengers. Includes crew, unusable fuel, oil, and operational items like ' + 'cargo containers and passenger service mass.', ) add_meta_data( @@ -1541,6 +1543,8 @@ desc='Total systems & equipment group mass', ) +# TODO intermediate calculated values with no uses by other systems may not belong in the +# variable hierarchy add_meta_data( # Note in FLOPS/LEAPS1, this is the same variable as # Aircraft.Design.SYSTEMS_EQUIP_MASS, because FLOPS/LEAPS1 overwrite the From bcc5bcdfc722011827ae25e419bb741d5aedd8dc Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 23 Dec 2024 12:18:04 -0500 Subject: [PATCH 06/30] test bench cleanup --- .../test_aircraft/aircraft_for_bench_GwGm.csv | 1 + .../benchmark_tests/test_bench_FwFm.py | 329 +++++------------- 2 files changed, 89 insertions(+), 241 deletions(-) diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index 3a052eca2..9b25443da 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -29,6 +29,7 @@ aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:mass_scaler,1,unitless aircraft:engine:num_engines,2,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 diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 1a07bb967..c80ad1abe 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -28,250 +28,97 @@ class ProblemPhaseTestCase(unittest.TestCase): def setUp(self): expected_dict = {} - expected_dict['times'] = np.array([[120.], - [163.76268404], - [224.14625594], - [243.25744998], - [243.25744998], - [336.40804126], - [464.93684491], - [505.61577182], - [505.61577182], - [626.46953842], - [793.22306972], - [845.99999224], - [845.99999224], - [966.85375884], - [1133.60729014], - [1186.38421266], - [1186.38421266], - [1279.53480393], - [1408.06360758], - [1448.74253449], - [1448.74253449], - [1492.50521853], - [1552.88879042], - [1571.99998447], - [1571.99998447], - [10224.87383109], - [22164.07366288], - [25942.78958866], - [25942.78958866], - [26009.11685074], - [26100.63493484], - [26129.60009555], - [26129.60009555], - [26265.05921709], - [26451.96515722], - [26511.12024823], - [26511.12024823], - [26672.16774132], - [26894.38041154], - [26964.7099619], - [26964.7099619], - [27100.16908344], - [27287.07502357], - [27346.23011458], - [27346.23011458], - [27412.55737667], - [27504.07546076], - [27533.04062147]]) + # block auto-formatting of tables + # autopep8: off + # fmt: off + expected_dict['times'] = np.array( + [ + [120.],[163.76268404], [224.14625594], [243.25744998], [243.25744998], + [336.40804126], [464.93684491], [505.61577182], [505.61577182], + [626.46953842], [793.22306972], [845.99999224], [845.99999224], + [966.85375884], [1133.60729014], [1186.38421266], [1186.38421266], + [1279.53480393], [1408.06360758], [1448.74253449], [1448.74253449], + [1492.50521853], [1552.88879042], [1571.99998447], [1571.99998447], + [10224.87383109], [22164.07366288], [25942.78958866], [25942.78958866], + [26009.11685074], [26100.63493484], [26129.60009555], [26129.60009555], + [26265.05921709], [26451.96515722], [26511.12024823], [26511.12024823], + [26672.16774132], [26894.38041154], [26964.7099619], [26964.7099619], + [27100.16908344], [27287.07502357], [27346.23011458], [27346.23011458], + [27412.55737667], [27504.07546076], [27533.04062147] + ] + ) - expected_dict['altitudes'] = np.array([[10.668], - [0.], - [1001.70617719], - [1429.27176545], - [1429.27176545], - [3413.27102762], - [5642.3831233], - [6169.75300447], - [6169.75300447], - [7399.140983], - [8514.78661356], - [8803.21405264], - [8803.21405264], - [9373.68426297], - [10020.99237958], - [10196.42552457], - [10196.42552457], - [10451.72258036], - [10652.38789684], - [10668.], - [10668.], - [10660.42246376], - [10656.16585151], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10142.11478951], - [9922.15743555], - [9922.15743555], - [8891.66886638], - [7502.1861348], - [7069.1900852], - [7069.1900852], - [5896.44637998], - [4264.29354306], - [3737.8471594], - [3737.8471594], - [2702.15624637], - [1248.18960736], - [793.03526817], - [793.03526817], - [345.06939295], - [10.668], - [10.668]]) + expected_dict['altitudes'] = np.array( + [ + [10.668], [0.], [1001.70617719], [1429.27176545], [1429.27176545], + [3413.27102762], [5642.3831233], [6169.75300447], [6169.75300447], + [7399.140983], [8514.78661356], [8803.21405264], [8803.21405264], + [9373.68426297], [10020.99237958], [10196.42552457], [10196.42552457], + [10451.72258036], [10652.38789684], [10668.], [10668.], [10660.42246376], + [10656.16585151], [10668.], [10668.], [10668.], [10668.], [10668.], + [10668.], [10668.], [10142.11478951], [9922.15743555], [9922.15743555], + [8891.66886638], [7502.1861348], [7069.1900852], [7069.1900852], + [5896.44637998], [4264.29354306], [3737.8471594], [3737.8471594], + [2702.15624637], [1248.18960736], [793.03526817], [793.03526817], + [345.06939295], [10.668], [10.668] + ] + ) - expected_dict['masses'] = np.array([[79303.30184763], - [79221.39668215], - [79075.19453181], - [79028.6003426], - [79028.6003426], - [78828.82221909], - [78613.60466821], - [78557.84739563], - [78557.84739563], - [78411.06578989], - [78238.0916773], - [78186.75440341], - [78186.75440341], - [78077.23953313], - [77938.37965175], - [77896.59718975], - [77896.59718975], - [77825.81832958], - [77732.75016916], - [77704.11629998], - [77704.11629998], - [77673.32196072], - [77630.75735319], - [77617.25716885], - [77617.25716885], - [72178.78521803], - [65072.41395049], - [62903.84179505], - [62903.84179505], - [62896.27636813], - [62888.3612195], - [62885.93748938], - [62885.93748938], - [62874.48788511], - [62857.70600096], - [62852.13740881], - [62852.13740881], - [62835.97069937], - [62810.37776063], - [62801.1924259], - [62801.1924259], - [62781.32471014], - [62748.91017128], - [62737.32520462], - [62737.32520462], - [62723.59895849], - [62703.94977811], - [62697.71513264]]) + expected_dict['masses'] = np.array( + [ + [79303.30184763], [79221.39668215], [79075.19453181], [79028.6003426], + [79028.6003426], [78828.82221909], [78613.60466821], [78557.84739563], + [78557.84739563], [78411.06578989], [78238.0916773], [78186.75440341], + [78186.75440341], [78077.23953313], [77938.37965175], [77896.59718975], + [77896.59718975], [77825.81832958], [77732.75016916], [77704.11629998], + [77704.11629998], [77673.32196072], [77630.75735319], [77617.25716885], + [77617.25716885], [72178.78521803], [65072.41395049], [62903.84179505], + [62903.84179505], [62896.27636813], [62888.3612195], [62885.93748938], + [62885.93748938], [62874.48788511], [62857.70600096], [62852.13740881], + [62852.13740881], [62835.97069937], [62810.37776063], [62801.1924259], + [62801.1924259], [62781.32471014], [62748.91017128], [62737.32520462], + [62737.32520462], [62723.59895849], [62703.94977811], [62697.71513264] + ] + ) - expected_dict['ranges'] = np.array([[1452.84514351], - [6093.51223933], - [15820.03029119], - [19123.61258676], - [19123.61258676], - [36374.65336952], - [61265.3984918], - [69106.49687132], - [69106.49687132], - [92828.04820577], - [126824.13801408], - [138011.02420534], - [138011.02420534], - [164027.18014424], - [200524.66550565], - [212113.49107256], - [212113.49107256], - [232622.50720766], - [261189.53466522], - [270353.40501262], - [270353.40501262], - [280350.48472685], - [294356.27080588], - [298832.61221641], - [298832.61221641], - [2325837.11255987], - [5122689.60556392], - [6007883.85695889], - [6007883.85695889], - [6022237.43153219], - [6039575.06318219], - [6044873.89820027], - [6044873.89820027], - [6068553.1921364], - [6099290.23732297], - [6108673.67260778], - [6108673.67260778], - [6133535.09572671], - [6166722.19545137], - [6177077.72115854], - [6177077.72115854], - [6197011.1330154], - [6224357.63792683], - [6232920.45309764], - [6232920.45309764], - [6242332.46480721], - [6254144.50957549], - [6257352.4]]) + expected_dict['ranges'] = np.array( + [ + [1452.84514351], [6093.51223933], [15820.03029119], [19123.61258676], + [19123.61258676], [36374.65336952], [61265.3984918], [69106.49687132], + [69106.49687132], [92828.04820577], [126824.13801408], [138011.02420534], + [138011.02420534], [164027.18014424], [200524.66550565], + [212113.49107256], [212113.49107256], [232622.50720766], + [261189.53466522], [270353.40501262], [270353.40501262], + [280350.48472685], [294356.27080588], [298832.61221641], + [298832.61221641], [2325837.11255987], [5122689.60556392], + [6007883.85695889], [6007883.85695889], [6022237.43153219], + [6039575.06318219], [6044873.89820027], [6044873.89820027], + [6068553.1921364], [6099290.23732297], [6108673.67260778], + [6108673.67260778], [6133535.09572671], [6166722.19545137], + [6177077.72115854], [6177077.72115854], [6197011.1330154], + [6224357.63792683], [6232920.45309764], [6232920.45309764], + [6242332.46480721], [6254144.50957549], [6257352.4] + ] + ) - expected_dict['velocities'] = np.array([[69.30879167], - [137.49019035], - [174.54683946], - [179.28863383], - [179.28863383], - [191.76748742], - [194.33322917], - [194.52960387], - [194.52960387], - [199.01184603], - [209.81696863], - [212.86546124], - [212.86546124], - [217.37467051], - [219.67762167], - [219.97194272], - [219.97194272], - [220.67963782], - [224.38113484], - [226.77184704], - [226.77184704], - [230.01128033], - [233.72454583], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [201.23881], - [182.84158341], - [180.10650108], - [180.10650108], - [169.77497514], - [159.59034446], - [157.09907013], - [157.09907013], - [151.659491], - [147.52098882], - [147.07683999], - [147.07683999], - [147.05392009], - [145.31556891], - [143.47446173], - [143.47446173], - [138.99109332], - [116.22447082], - [102.07377559]]) + expected_dict['velocities'] = np.array( + [ + [69.30879167], [137.49019035], [174.54683946], [179.28863383], + [179.28863383], [191.76748742], [194.33322917], [194.52960387], + [194.52960387], [199.01184603], [209.81696863], [212.86546124], + [212.86546124], [217.37467051], [219.67762167], [219.97194272], + [219.97194272], [220.67963782], [224.38113484], [226.77184704], + [226.77184704], [230.01128033], [233.72454583], [234.25795132], + [234.25795132], [234.25795132], [234.25795132], [234.25795132], + [234.25795132], [201.23881], [182.84158341], [180.10650108], + [180.10650108], [169.77497514], [159.59034446], [157.09907013], + [157.09907013], [151.659491], [147.52098882], [147.07683999], + [147.07683999], [147.05392009], [145.31556891], [143.47446173], + [143.47446173], [138.99109332], [116.22447082], [102.07377559] + ] + ) + # autopep8: on + # fmt: on self.expected_dict = expected_dict @@ -377,7 +224,7 @@ def test_bench_FwFm_IPOPT(self): prob = run_aviary( 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, - verbosity=0, + verbosity=1, max_iter=50, optimizer='IPOPT', ) From 546e2caad4a3d98b9df1110c5255d33554c1ed5f Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 23 Dec 2024 13:55:59 -0500 Subject: [PATCH 07/30] verbosity updates --- aviary/interface/methods_for_level2.py | 114 +++++++++++++++++++++---- 1 file changed, 98 insertions(+), 16 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index cfe0a6eb7..5a9fe2d63 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -302,12 +302,14 @@ def load_inputs( This method is not strictly necessary; a user could also supply an AviaryValues object and/or phase_info dict of their own. """ - # We haven't read the input file yet, so by default self.verbosity is None - if self.verbosity is None: + # We haven't read the input data yet, we don't know what desired run verbosity is + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: # compatibility with being passed int for verbosity verbosity = Verbosity(verbosity) else: - verbosity = self.verbosity + verbosity = self.verbosity # usually None ## LOAD INPUT FILE ### # Create AviaryValues object from file (or process existing AviaryValues object @@ -316,6 +318,12 @@ def load_inputs( aircraft_data, meta_data=meta_data, verbosity=verbosity ) + # update verbosity now that we have read the input data + self.verbosity = aviary_inputs.get_val(Settings.VERBOSITY) + # if user did not ask for verbosity override for this method, use value from data + if verbosity is None: + verbosity = aviary_inputs.get_val(Settings.VERBOSITY) + # Now that the input file has been read, we have the desired verbosity for this # run stored in aviary_inputs. Save this to self. @@ -352,7 +360,7 @@ def load_inputs( # if verbosity level is BRIEF or higher, print that we're using the # outputted phase info - if verbosity is not None and verbosity >= Verbosity.BRIEF: + if verbosity >= Verbosity.BRIEF: print('Using outputted phase_info from current working directory') else: @@ -376,7 +384,7 @@ def load_inputs( phase_info, ) - if verbosity is not None and verbosity >= Verbosity.BRIEF: + if verbosity >= Verbosity.BRIEF: print( 'Loaded default phase_info for ' f'{self.mission_method.value.lower()} equations of motion' @@ -542,11 +550,19 @@ def phase_separator(self): if descent: self.descent_phases[name] = info - def check_and_preprocess_inputs(self): + def check_and_preprocess_inputs(self, verbosity=None): """ 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. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + aviary_inputs = self.aviary_inputs # Target_distance verification for all phases # Checks to make sure target_distance is positive, @@ -706,7 +722,7 @@ def check_and_preprocess_inputs(self): if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF, TWO_DEGREES_OF_FREEDOM): self.phase_separator() - def add_pre_mission_systems(self): + def add_pre_mission_systems(self, verbosity=None): """ Add pre-mission systems to the Aviary problem. These systems are executed before the mission. @@ -719,6 +735,14 @@ def add_pre_mission_systems(self): A user can override this method with their own pre-mission systems as desired. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + pre_mission = self.pre_mission self.model.add_subsystem( 'pre_mission', @@ -1187,7 +1211,7 @@ def _get_phase(self, phase_name, phase_idx): return phase - def add_phases(self, phase_info_parameterization=None): + def add_phases(self, phase_info_parameterization=None, verbosity=None): """ Add the mission phases to the problem trajectory based on the user-specified phase_info dictionary. @@ -1201,6 +1225,14 @@ def add_phases(self, phase_info_parameterization=None): ------- traj: The Dymos Trajectory object containing the added mission phases. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + if phase_info_parameterization is not None: self.phase_info, self.post_mission_info = phase_info_parameterization( self.phase_info, self.post_mission_info, self.aviary_inputs @@ -1351,7 +1383,7 @@ def add_subsystem_timeseries_outputs(phase, phase_name): return traj - def add_post_mission_systems(self, include_landing=True): + def add_post_mission_systems(self, include_landing=True, verbosity=None): """ Add post-mission systems to the aircraft model. This is akin to the pre-mission group or the "premission_systems", but occurs after the mission in the execution order. @@ -1370,6 +1402,13 @@ def add_post_mission_systems(self, include_landing=True): A user can override this with their own postmission systems. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF if ( self.pre_mission_info['include_takeoff'] @@ -1698,7 +1737,7 @@ def _link_phases_helper_with_options(self, phases, option_name, var, **kwargs): if len(phases_to_link) > 1: self.traj.link_phases(phases=phases_to_link, vars=[var], **kwargs) - def link_phases(self): + def link_phases(self, verbosity=None): """ Link phases together after they've been added. @@ -1706,6 +1745,14 @@ def link_phases(self): special logic to do the Dymos linkages correctly. Some of those connections for the simple GASP and FLOPS mission are shown here. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + self._add_bus_variables_and_connect() phases = list(self.phase_info.keys()) @@ -2118,7 +2165,7 @@ def add_driver( ] driver.options['print_opt_prob'] = True - def add_design_variables(self): + def add_design_variables(self, verbosity=None): """ Adds design variables to the Aviary problem. @@ -2143,6 +2190,14 @@ def add_design_variables(self): In all cases, a design variable is added for the final cruise mass of the aircraft, with no upper bound, and a residual mass constraint is added to ensure that the mass balances. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + # add the engine builder `get_design_vars` dict to a collected dict from # the external subsystems @@ -2283,7 +2338,7 @@ def add_design_variables(self): "h_fit.h_init_flaps", equals=400.0, units="ft", ref=400.0 ) - def add_objective(self, objective_type=None, ref=None): + def add_objective(self, objective_type=None, ref=None, verbosity=None): """ Add the objective function based on the given objective_type and ref. @@ -2299,12 +2354,22 @@ def add_objective(self, objective_type=None, ref=None): ref : float The reference value for the objective. If None, a default value will be used based on the objective type. Please see the `default_ref_values` dict for these default values. + verbosity : Verbosity or int + Controls the level of printouts for this method. If None, uses the value of Settings.VERBOSITY in provided aircraft data. Raises ------ ValueError: If an invalid problem type is provided. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + # Dictionary for default reference values default_ref_values = { 'mass': -5e4, @@ -2449,7 +2514,7 @@ def setup(self, **kwargs): warnings.simplefilter("ignore", om.PromotionWarning) super().setup(**kwargs) - def set_initial_guesses(self, parent_prob=None, parent_prefix=""): + def set_initial_guesses(self, parent_prob=None, parent_prefix="", verbosity=None): """ Call `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses. This is especially @@ -2463,6 +2528,14 @@ def set_initial_guesses(self, parent_prob=None, parent_prefix=""): guesses for states and controls according to the information available in the 'initial_guesses' attribute of the phase. """ + # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + setvalprob = self if parent_prob is not None and parent_prefix != "": setvalprob = parent_prob @@ -2930,12 +3003,21 @@ def run_aviary_problem( # TODO this is only used in a single test. Either this should be removed, or # rework this option to be more helpful (store entired "failed" object?) # and implement more rigorously in benchmark tests - self.problem_ran_successfully = not failed + if self.analysis_scheme is AnalysisScheme.SHOOTING: + self.problem_ran_successfully = not failed + else: + if failed.exit_status == "FAIL": + self.problem_ran_successfully = False + else: + self.problem_ran_successfully = True # Manually print out a failure message for low verbosity modes that suppress # optimizer printouts, which may include the results message. Assumes success, # alerts user on a failure - if failed.exit_status == "FAIL" and verbosity <= Verbosity.BRIEF: # QUIT, BRIEF - print("Aviary run failed. See the dashboard for more details.") + if ( + not self.problem_ran_successfully + and verbosity <= Verbosity.BRIEF # QUIET, BRIEF + ): + print("\nAviary run failed. See the dashboard for more details.\n") def alternate_mission( self, From 745c92147b3ed73bfb466359d06645b9f7500a83 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 23 Dec 2024 15:49:55 -0500 Subject: [PATCH 08/30] updates for turboprop more verbosity updates for preprocessor stack --- aviary/interface/methods_for_level2.py | 4 +- .../large_turboprop_freighter.csv | 10 +-- .../propulsion/propeller/propeller_builder.py | 26 +++---- aviary/utils/preprocessors.py | 75 +++++++++++++------ aviary/utils/process_input_decks.py | 4 +- .../test_bench_large_turboprop_freighter.py | 10 +-- 6 files changed, 79 insertions(+), 50 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 5a9fe2d63..e6e5f668c 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -652,7 +652,9 @@ def check_and_preprocess_inputs(self, verbosity=None): # PREPROCESSORS # # Fill in anything missing in the options with computed defaults. - preprocess_options(aviary_inputs, engine_models=self.engine_builders) + preprocess_options( + aviary_inputs, engine_models=self.engine_builders, verbosity=verbosity + ) mission_method = aviary_inputs.get_val(Settings.EQUATIONS_OF_MOTION) mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) diff --git a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv b/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv index 2fc5ebf5f..75da33239 100644 --- a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv +++ b/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv @@ -51,12 +51,12 @@ aircraft:engine:data_file, models/engines/turboshaft_4465hp.deck aircraft:engine:mass_scaler, 1, unitless aircraft:engine:mass_specific, 0.37026, lbm/lbf aircraft:engine:num_engines, 4, unitless -aircraft:engine:num_propeller_blades, 4, unitless +aircraft:engine:propeller:num_blades, 4, unitless aircraft:engine:pod_mass_scaler, 1, unitless -aircraft:engine:propeller_activity_factor, 167, unitless -aircraft:engine:propeller_diameter, 13.5, ft -aircraft:engine:propeller_integrated_lift_coefficient, 0.5, unitless -aircraft:engine:propeller_tip_speed_max, 720, ft/s +aircraft:engine:propeller:activity_factor, 167, unitless +aircraft:engine:propeller:diameter, 13.5, ft +aircraft:engine:propeller:integrated_lift_coefficient, 0.5, unitless +aircraft:engine:propeller:tip_speed_max, 720, ft/s aircraft:engine:pylon_factor, 0.7, unitless aircraft:engine:reference_diameter, 5.8, ft aircraft:engine:reference_sls_thrust, 5000, lbf diff --git a/aviary/subsystems/propulsion/propeller/propeller_builder.py b/aviary/subsystems/propulsion/propeller/propeller_builder.py index ddcb60e83..44d097f9b 100644 --- a/aviary/subsystems/propulsion/propeller/propeller_builder.py +++ b/aviary/subsystems/propulsion/propeller/propeller_builder.py @@ -43,19 +43,19 @@ def get_design_vars(self): # TODO bounds are rough placeholders DVs = { - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR: { + Aircraft.Engine.Propeller.ACTIVITY_FACTOR: { 'units': 'unitless', 'lower': 100, 'upper': 200, # 'val': 100, # initial value }, - Aircraft.Engine.PROPELLER_DIAMETER: { + Aircraft.Engine.Propeller.DIAMETER: { 'units': 'ft', 'lower': 0.0, 'upper': None, # 'val': 8, # initial value }, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT: { + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT: { 'units': 'unitless', 'lower': 0.0, 'upper': 0.5, @@ -79,27 +79,27 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): A dict of names for the propeller subsystem. """ parameters = { - Aircraft.Engine.PROPELLER_TIP_MACH_MAX: { + Aircraft.Engine.Propeller.TIP_MACH_MAX: { 'val': 1.0, 'units': 'unitless', }, - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX: { + Aircraft.Engine.Propeller.TIP_SPEED_MAX: { 'val': 0.0, 'units': 'unitless', }, - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX: { + Aircraft.Engine.Propeller.TIP_SPEED_MAX: { 'val': 0.0, 'units': 'ft/s', }, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT: { + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT: { 'val': 0.0, 'units': 'unitless', }, - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR: { + Aircraft.Engine.Propeller.ACTIVITY_FACTOR: { 'val': 0.0, 'units': 'unitless', }, - Aircraft.Engine.PROPELLER_DIAMETER: { + Aircraft.Engine.Propeller.DIAMETER: { 'val': 0.0, 'units': 'ft', }, @@ -116,9 +116,9 @@ def get_mass_names(self): def get_outputs(self): return [ - Dynamic.Mission.SHAFT_POWER + '_out', - Dynamic.Mission.SHAFT_POWER_MAX + '_out', - Dynamic.Mission.RPM + '_out', - Dynamic.Mission.TORQUE + '_out', + Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_out', + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_out', + Dynamic.Vehicle.Propulsion.RPM + '_out', + Dynamic.Vehicle.Propulsion.TORQUE + '_out', Mission.Constraints.GEARBOX_SHAFT_POWER_RESIDUAL, ] diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 6c37a972c..fafc59fb6 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -7,9 +7,11 @@ from aviary.utils.named_values import get_keys from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission, Settings +from aviary.variable_info.enums import Verbosity from aviary.utils.test_utils.variable_test import get_names_from_hierarchy +# TODO kwargs seems overkill/unnecessary here, just use arguments? def preprocess_options(aviary_options: AviaryValues, **kwargs): """ Run all preprocessors on provided AviaryValues object @@ -24,22 +26,35 @@ def preprocess_options(aviary_options: AviaryValues, **kwargs): except KeyError: engine_models = None + try: + verbosity = kwargs['verbosity'] + except KeyError: + if Settings.VERBOSITY in aviary_options: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + else: + aviary_options.set_val( + Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value'] + ) + if Settings.VERBOSITY not in aviary_options: - aviary_options.set_val( - Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value']) + verbosity = _MetaData[Settings.VERBOSITY]['default_value'] + aviary_options.set_val(Settings.VERBOSITY, verbosity) - preprocess_crewpayload(aviary_options) - preprocess_propulsion(aviary_options, engine_models) + preprocess_crewpayload(aviary_options, verbosity) + preprocess_propulsion(aviary_options, engine_models, verbosity) -def preprocess_crewpayload(aviary_options: AviaryValues): +def preprocess_crewpayload(aviary_options: AviaryValues, verbosity=None): """ Calculates option values that are derived from other options, and are not direct inputs. This function modifies the entries in the supplied collection, and for convenience also returns the modified collection. """ - - verbosity = aviary_options.get_val(Settings.VERBOSITY) + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = aviary_options.get_val(Settings.VERBOSITY) # Some tests, but not all, do not correctly set default values # # so we need to ensure all these values are available. @@ -72,12 +87,12 @@ def preprocess_crewpayload(aviary_options: AviaryValues): # or if it was set to it's default value of zero if passenger_count != 0 and aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) == 0: aviary_options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, passenger_count) - if verbosity >= 2: + if verbosity >= Verbosity.VERBOSE: print("User has specified supporting values for NUM_PASSENGERS but has left NUM_PASSENGERS=0. Replacing NUM_PASSENGERS with passenger_count.") if design_passenger_count != 0 and aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) == 0: aviary_options.set_val( Aircraft.CrewPayload.Design.NUM_PASSENGERS, design_passenger_count) - if verbosity >= 2: + if verbosity >= Verbosity.VERBOSE: print("User has specified supporting values for Design.NUM_PASSENGERS but has left Design.NUM_PASSENGERS=0. Replacing Design.NUM_PASSENGERS with design_passenger_count.") num_pax = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) @@ -109,7 +124,7 @@ def preprocess_crewpayload(aviary_options: AviaryValues): # Copy data over if only one set of data exists # User has given detailed values for 1TB as flow and NO design values at all if passenger_count != 0 and design_num_pax == 0 and design_passenger_count == 0: - if verbosity >= 2: + if verbosity >= Verbosity.VERBOSE: print( "User has not input design passengers data. Assuming design is equal to as-flow passenger data.") aviary_options.set_val( @@ -208,7 +223,9 @@ def preprocess_crewpayload(aviary_options: AviaryValues): return aviary_options -def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = None): +def preprocess_propulsion( + aviary_options: AviaryValues, engine_models: list = None, verbosity=None +): ''' Updates AviaryValues object with values taken from provided EngineModels. @@ -235,7 +252,12 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No EngineModel objects to be added to aviary_options. Replaced existing EngineModels in aviary_options ''' - # TODO add verbosity check to warnings + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + ############################## # Vectorize Engine Variables # ############################## @@ -372,27 +394,34 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No num_wing_engines_all[i] = num_engines # TODO is a warning overkill here? It can be documented wing mounted engines # are assumed default - warnings.warn( - f'Mount location for engines of type <{eng_name}> not specified. ' - 'Wing-mounted engines are assumed.') + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + f'Mount location for engines of type <{eng_name}> not specified. ' + 'Wing-mounted engines are assumed.' + ) # If wing mount type are specified but inconsistent, handle it elif total_engines_calc > num_engines: # more defined engine locations than number of engines - increase num engines eng_name = engine.name num_engines_all[i] = total_engines_calc - warnings.warn( - 'Sum of aircraft:engine:num_fueslage_engines and ' - 'aircraft:engine:num_wing_engines do not match ' - f'aircraft:engine:num_engines for EngineModel <{eng_name}>. Overwriting ' - 'with the sum of wing and fuselage mounted engines.') + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + 'Sum of aircraft:engine:num_fueslage_engines and ' + 'aircraft:engine:num_wing_engines do not match ' + f'aircraft:engine:num_engines for EngineModel <{ + eng_name}>. Overwriting ' + 'with the sum of wing and fuselage mounted engines.' + ) elif total_engines_calc < num_engines: # fewer defined locations than num_engines - assume rest are wing mounted eng_name = engine.name num_wing_engines_all[i] = num_engines - num_fuse_engines - warnings.warn( - 'Mount location was not defined for all engines of EngineModel ' - f'<{eng_name}> - unspecified engines are assumed wing-mounted.') + if verbosity >= Verbosity.BRIEF: + warnings.warn( + 'Mount location was not defined for all engines of EngineModel ' + f'<{eng_name}> - unspecified engines are assumed wing-mounted.' + ) aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, num_engines_all) aviary_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, num_wing_engines_all) diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 061f1d861..eeb24a37d 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -100,7 +100,9 @@ def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): aircraft_values.set_val(Settings.VERBOSITY, Verbosity(verbosity)) # else, if verbosity not specified anywhere, use default of BRIEF elif verbosity is None and Settings.VERBOSITY not in aircraft_values: - aircraft_values.set_val(Settings.VERBOSITY, Verbosity.BRIEF) + aircraft_values.set_val( + Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value'] + ) return aircraft_values, initialization_guesses diff --git a/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py b/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py index 1454af94d..5b8acb19c 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py @@ -19,14 +19,13 @@ @use_tempdirs -@unittest.skip("Skipping until all builders are updated with get_parameters()") -# TODO need to add asserts with "truth" values +# TODO need to add asserts with "truth" values, only verifying no errors here class LargeTurbopropFreighterBenchmark(unittest.TestCase): def build_and_run_problem(self): # Build problem - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) # load inputs from .csv to build engine options, _ = create_vehicle( @@ -41,8 +40,6 @@ def build_and_run_problem(self): two_dof_phase_info, engine_builders=[turboprop], ) - prob.aviary_inputs.set_val(Settings.VERBOSITY, 2) - # FLOPS aero specific stuff? Best guesses for values here prob.aviary_inputs.set_val(Mission.Constraints.MAX_MACH, 0.5) prob.aviary_inputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, 4.125, 'm') @@ -60,8 +57,7 @@ def build_and_run_problem(self): prob.set_initial_guesses() prob.run_aviary_problem("dymos_solution.db") - - om.n2(prob) + # om.n2(prob) if __name__ == '__main__': From 79fb3b93b170fc42f6e1a6d4f683e8848037aba5 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 23 Dec 2024 17:41:46 -0500 Subject: [PATCH 09/30] adjustments to turboprop bench --- .../large_turboprop_freighter.csv | 2 +- aviary/models/large_turboprop_freighter/phase_info.py | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv b/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv index 75da33239..f3e448331 100644 --- a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv +++ b/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv @@ -92,7 +92,7 @@ aircraft:fuselage:pressure_differential, 6.55, psi aircraft:fuselage:seat_pitch, 41.24, inch aircraft:fuselage:seat_width, 18, inch aircraft:fuselage:tail_fineness, 2.9, unitless -aircraft:fuselage:wetted_area_factor, 1, unitless +aircraft:fuselage:wetted_area_scaler, 1, unitless # H-Tail aircraft:horizontal_tail:area, 0, ft**2 diff --git a/aviary/models/large_turboprop_freighter/phase_info.py b/aviary/models/large_turboprop_freighter/phase_info.py index 3566a67c7..29915044f 100644 --- a/aviary/models/large_turboprop_freighter/phase_info.py +++ b/aviary/models/large_turboprop_freighter/phase_info.py @@ -217,7 +217,7 @@ 'num_segments': 1, 'order': 3, 'fix_initial': False, - 'EAS_target': (250, 'kn'), + 'EAS_target': (150, 'kn'), 'mach_cruise': 0.475, 'target_mach': False, 'final_altitude': (10.0e3, 'ft'), @@ -247,7 +247,7 @@ 'num_segments': 3, 'order': 3, 'fix_initial': False, - 'EAS_target': (250, 'kn'), + 'EAS_target': (160, 'kn'), 'mach_cruise': 0.475, 'target_mach': True, 'final_altitude': (21_000, 'ft'), @@ -271,7 +271,7 @@ 'initial_guesses': { 'time': ([216.0, 1300.0], 's'), 'distance': ([100.0e3, 200.0e3], 'ft'), - 'altitude': ([10_000, 21_000], 'ft'), + 'altitude': ([10_000, 20_000], 'ft'), 'throttle': ([0.956, 0.956], 'unitless'), }, }, @@ -295,7 +295,7 @@ 'order': 3, 'fix_initial': False, 'input_initial': False, - 'EAS_limit': (350, 'kn'), + 'EAS_limit': (160, 'kn'), 'mach_cruise': 0.475, 'input_speed_type': SpeedType.MACH, 'final_altitude': (10_000, 'ft'), @@ -360,5 +360,3 @@ }, }, } - -phase_info = two_dof_phase_info From fda0b5535f687644e6933fcf15184474194e8909 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 10:49:19 -0500 Subject: [PATCH 10/30] update optimizer printouts for SLSQP --- aviary/interface/methods_for_level2.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index e6e5f668c..233633fa9 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2148,13 +2148,14 @@ def add_driver( driver.options["tol"] = 1e-9 driver.options["maxiter"] = max_iter - # pyoptsparse print settings, optimizer agnostic - # if optimizer in ("SNOPT", "IPOPT"): - if verbosity == Verbosity.QUIET: - driver.options['print_results'] = False - elif verbosity < Verbosity.DEBUG: - driver.options['print_results'] = 'minimal' + # pyoptsparse print settings for both SNOPT, IPOPT + if optimizer in ("SNOPT", "IPOPT"): + if verbosity == Verbosity.QUIET: + driver.options['print_results'] = False + elif verbosity < Verbosity.DEBUG: + driver.options['print_results'] = 'minimal' + # optimizer agnostic settings if verbosity > Verbosity.QUIET: if isinstance(verbosity, list): driver.options['debug_print'] = ['desvars'] From c8e25293076d79ff8140bf1b0546ae13cd0a6f82 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 10:54:06 -0500 Subject: [PATCH 11/30] variable desc cleanup verbosity updates --- .../benchmark_tests/test_subsystems_within_a_mission.py | 6 +++--- aviary/variable_info/variable_meta_data.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) 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 9e20d75f5..c1a8e7fac 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 @@ -57,7 +57,7 @@ def setUp(self): def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) @@ -104,7 +104,7 @@ 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(reports=False) + prob = AviaryProblem(reports=False, verbosity=0) prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) @@ -115,7 +115,7 @@ def test_bad_initial_guess_key(self): with self.assertRaises(TypeError) as context: prob.add_phases() - print(str(context.exception)) + # print(str(context.exception)) self.assertTrue( 'EnergyPhase: cruise: unsupported initial guess: bad_guess_name' in str(context.exception)) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index e5076dcc1..d077c8cc2 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1909,11 +1909,11 @@ option=True, default_value=False, types=bool, - desc='If True, generate flight idle data by extrapolating from engine deck. Flight ' + desc='If True, generate flight idle data by extrapolating from engine data. Flight ' 'idle is defined as engine performance when thrust is reduced to the level ' - 'defined by Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION. Engine outputs are ' + 'defined by Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION. Other engine outputs are ' 'extrapolated to this thrust level, bounded by ' - 'Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT and Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT', + 'Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT and Aircraft.Engine.FLIGHT_IDLE_MAX_FRACT', ) add_meta_data( From c846ad88d4230118b09fae61cad8859ad6c0123d Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 13:55:34 -0500 Subject: [PATCH 12/30] more test verbosity updates --- .gitignore | 1 + aviary/interface/methods_for_level2.py | 2 +- aviary/validation_cases/benchmark_tests/test_0_iters.py | 2 +- .../benchmark_tests/test_battery_in_a_mission.py | 2 +- aviary/validation_cases/benchmark_tests/test_bench_FwFm.py | 2 +- .../test_bench_electrified_large_turboprop_freighter.py | 2 +- .../benchmark_tests/test_bench_multiengine.py | 6 +++--- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index dd8663cd2..26bc1c3c3 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ dmypy.json # Test and spec generated reports/ +aviary/reports/ *.out *.png *.sql diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 233633fa9..516627c1c 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2068,7 +2068,7 @@ def add_driver( """ # override verbosity for this function call if user desired if verbosity is None: - verbsity = self.verbosity + verbosity = self.verbosity else: # compatibility with being passed int for verbosity verbosity = Verbosity(verbosity) diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 8cb13bea8..eb581e809 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -16,7 +16,7 @@ class BaseProblemPhaseTestCase(unittest.TestCase): def build_and_run_problem(self, input_filename, phase_info, objective_type=None): # Build problem - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(input_filename, phase_info) diff --git a/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py b/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py index 7fe7e744e..c8b7662c1 100644 --- a/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py @@ -53,7 +53,7 @@ def setUp(self): def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() - prob = av.AviaryProblem() + prob = av.AviaryProblem(verbosity=0) prob.load_inputs( "models/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv", phase_info) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index c80ad1abe..df9925bf1 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -224,7 +224,7 @@ def test_bench_FwFm_IPOPT(self): prob = run_aviary( 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, - verbosity=1, + verbosity=0, max_iter=50, optimizer='IPOPT', ) diff --git a/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py b/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py index 054170193..8beee1d55 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py @@ -25,7 +25,7 @@ class LargeElectrifiedTurbopropFreighterBenchmark(unittest.TestCase): def build_and_run_problem(self): # Build problem - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) # load inputs from .csv to build engine options, guesses = create_vehicle( diff --git a/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py b/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py index 146a1f1be..cc7ecb8c7 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py @@ -64,7 +64,7 @@ def test_multiengine_fixed(self): engine2 = build_engine_deck(engine_2_inputs)[0] engine2.name = 'engine_2' - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(inputs, test_phase_info, engine_builders=[engine1, engine2]) @@ -105,7 +105,7 @@ def test_multiengine_static(self): engine1 = build_engine_deck(engine_1_inputs)[0] engine2 = build_engine_deck(engine_2_inputs)[0] - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(inputs, test_phase_info, engine_builders=[engine1, engine2]) @@ -143,7 +143,7 @@ def test_multiengine_dynamic(self): test_phase_info['cruise']['user_options']['throttle_allocation'] = method test_phase_info['descent']['user_options']['throttle_allocation'] = method - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) engine1 = build_engine_deck(engine_1_inputs)[0] engine2 = build_engine_deck(engine_2_inputs)[0] From 73049047402f42a044f1a7ed2b3ec3da36a26c43 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 14:08:43 -0500 Subject: [PATCH 13/30] fixed default verbosity for preprocessors when not provided when user --- aviary/subsystems/propulsion/test/test_engine_scaling.py | 3 ++- aviary/utils/preprocessors.py | 5 ++--- aviary/validation_cases/validation_tests.py | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/aviary/subsystems/propulsion/test/test_engine_scaling.py b/aviary/subsystems/propulsion/test/test_engine_scaling.py index cc30345ea..a4fb5d2f3 100644 --- a/aviary/subsystems/propulsion/test/test_engine_scaling.py +++ b/aviary/subsystems/propulsion/test/test_engine_scaling.py @@ -9,7 +9,7 @@ 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, Dynamic, Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings from aviary.subsystems.propulsion.utils import EngineModelVariables @@ -25,6 +25,7 @@ def test_case(self): filename = get_path(filename) options = AviaryValues() + options.set_val(Settings.VERBOSITY, 0) options.set_val(Aircraft.Engine.DATA_FILE, filename) options.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 0.9) # make supersonic scaling factor extremely high so it is obvious if it gets used diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index fafc59fb6..60ad2ef4d 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -32,9 +32,8 @@ def preprocess_options(aviary_options: AviaryValues, **kwargs): if Settings.VERBOSITY in aviary_options: verbosity = aviary_options.get_val(Settings.VERBOSITY) else: - aviary_options.set_val( - Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value'] - ) + verbosity = _MetaData[Settings.VERBOSITY]['default_value'] + aviary_options.set_val(Settings.VERBOSITY, verbosity) if Settings.VERBOSITY not in aviary_options: verbosity = _MetaData[Settings.VERBOSITY]['default_value'] diff --git a/aviary/validation_cases/validation_tests.py b/aviary/validation_cases/validation_tests.py index 9b6e25b23..3cfd3a61c 100644 --- a/aviary/validation_cases/validation_tests.py +++ b/aviary/validation_cases/validation_tests.py @@ -1,4 +1,3 @@ - import warnings from enum import Enum @@ -305,8 +304,11 @@ def get_flops_inputs(case_name: str, keys: str = None, preprocess: bool = False) flops_inputs_copy: AviaryValues = flops_data['inputs'].deepcopy() if preprocess: - preprocess_options(flops_inputs_copy, - engine_models=build_engine_deck(flops_inputs_copy)) + preprocess_options( + flops_inputs_copy, + engine_models=build_engine_deck(flops_inputs_copy), + verbosity=0, + ) if keys is None: return flops_inputs_copy keys_list = _assure_is_list(keys) From 78fad603d889ad45f6aa1f8e00df7ef11504c5de Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 14:38:50 -0500 Subject: [PATCH 14/30] another round of test verbosity updates/fixes --- aviary/interface/methods_for_level2.py | 42 +++++++++---------- aviary/interface/test/test_linkage_logic.py | 5 ++- .../flops_based/test/test_thrust_reverser.py | 11 +++-- .../flops_based/test/test_wing_detailed.py | 2 + .../mass/gasp_based/test/test_fixed.py | 3 +- aviary/utils/preprocessors.py | 2 +- 6 files changed, 37 insertions(+), 28 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 516627c1c..bb6a1dd9d 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2992,36 +2992,36 @@ def run_aviary_problem( solution_record_file=record_filename, restart=restart_filename, ) + + # TODO this is only used in a single test. Either self.problem_ran_sucessfully + # should be removed, or rework this option to be more helpful (store + # entired "failed" object?) and implement more rigorously in benchmark tests + if self.analysis_scheme is AnalysisScheme.SHOOTING: + self.problem_ran_successfully = not failed + else: + if failed.exit_status == "FAIL": + self.problem_ran_successfully = False + else: + self.problem_ran_successfully = True + # Manually print out a failure message for low verbosity modes that suppress + # optimizer printouts, which may include the results message. Assumes success, + # alerts user on a failure + if ( + not self.problem_ran_successfully + and verbosity <= Verbosity.BRIEF # QUIET, BRIEF + ): + print("\nAviary run failed. See the dashboard for more details.\n") else: # prevent UserWarning that is displayed when an event is triggered warnings.filterwarnings('ignore', category=UserWarning) + # TODO failed doesn't exist for run_model(), no return from method failed = self.run_model() warnings.filterwarnings('default', category=UserWarning) - if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG + if verbosity >= Verbosity.DEBUG: # DEBUG with open('output_list.txt', 'w') as outfile: self.model.list_outputs(out_stream=outfile) - # TODO use failed.exit_status or failed.sucess for better query? - # TODO this is only used in a single test. Either this should be removed, or - # rework this option to be more helpful (store entired "failed" object?) - # and implement more rigorously in benchmark tests - if self.analysis_scheme is AnalysisScheme.SHOOTING: - self.problem_ran_successfully = not failed - else: - if failed.exit_status == "FAIL": - self.problem_ran_successfully = False - else: - self.problem_ran_successfully = True - # Manually print out a failure message for low verbosity modes that suppress - # optimizer printouts, which may include the results message. Assumes success, - # alerts user on a failure - if ( - not self.problem_ran_successfully - and verbosity <= Verbosity.BRIEF # QUIET, BRIEF - ): - print("\nAviary run failed. See the dashboard for more details.\n") - def alternate_mission( self, run_mission=True, diff --git a/aviary/interface/test/test_linkage_logic.py b/aviary/interface/test/test_linkage_logic.py index 781ef562c..1c414d34b 100644 --- a/aviary/interface/test/test_linkage_logic.py +++ b/aviary/interface/test/test_linkage_logic.py @@ -181,4 +181,7 @@ def get_linkage_string(phase_1, var, phase_2): if __name__ == '__main__': - unittest.main() + # unittest.main() + test = AircraftMissionTestSuite() + test.setUp() + test.test_linkages() diff --git a/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py b/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py index e77408cf6..d510427a6 100644 --- a/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py +++ b/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py @@ -51,17 +51,20 @@ def test_case_multiengine(self): aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') engine_options = AviaryValues() - engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) - engine_options.set_val(Aircraft.Engine.DATA_FILE, - 'models/engines/turbofan_28k.deck') engine_options.set_val(Settings.VERBOSITY, 0) + engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + engine_options.set_val( + Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.deck' + ) engineModel1 = EngineDeck(options=engine_options) engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) engineModel2 = EngineDeck(options=engine_options) engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 4) engineModel3 = EngineDeck(options=engine_options) - preprocess_propulsion(aviary_options, [engineModel1, engineModel2, engineModel3]) + preprocess_propulsion( + aviary_options, [engineModel1, engineModel2, engineModel3], verbosity=0 + ) prob.model.add_subsystem('thrust_reverser_mass', ThrustReverserMass( aviary_options=aviary_options), promotes=['*']) diff --git a/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py b/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py index 075fd3261..fbb486d83 100644 --- a/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py +++ b/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py @@ -65,6 +65,7 @@ def test_case_multiengine(self): prob = self.prob aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') + aviary_options.set_val(Settings.VERBOSITY, 0) engine_options = AviaryValues() engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) @@ -127,6 +128,7 @@ def test_case_multiengine(self): def test_extreme_engine_loc(self): aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') + aviary_options.set_val(Settings.VERBOSITY, 0) engine_options = AviaryValues() engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) diff --git a/aviary/subsystems/mass/gasp_based/test/test_fixed.py b/aviary/subsystems/mass/gasp_based/test/test_fixed.py index 064e3e1a3..3e95d849c 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_fixed.py +++ b/aviary/subsystems/mass/gasp_based/test/test_fixed.py @@ -17,7 +17,7 @@ PayloadMass, TailMass) from aviary.utils.aviary_values import AviaryValues, get_keys from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Mission, Settings class MassParametersTestCase1(unittest.TestCase): @@ -26,6 +26,7 @@ class MassParametersTestCase1(unittest.TestCase): def setUp(self): options = get_option_defaults() + options.set_val(Settings.VERBOSITY, 0) options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=0) diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 60ad2ef4d..05d6c1245 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -11,7 +11,7 @@ from aviary.utils.test_utils.variable_test import get_names_from_hierarchy -# TODO kwargs seems overkill/unnecessary here, just use arguments? +# TODO document what kwargs are used, and by which preprocessors in docstring? def preprocess_options(aviary_options: AviaryValues, **kwargs): """ Run all preprocessors on provided AviaryValues object From 32d38d8bd14eba0045af70f0c1dce388fd2601e5 Mon Sep 17 00:00:00 2001 From: Jason Kirk <110835404+jkirk5@users.noreply.github.com> Date: Thu, 26 Dec 2024 14:48:33 -0500 Subject: [PATCH 15/30] Update aviary/interface/methods_for_level2.py --- aviary/interface/methods_for_level2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 516627c1c..515a6d3fa 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -303,7 +303,7 @@ def load_inputs( an AviaryValues object and/or phase_info dict of their own. """ # We haven't read the input data yet, we don't know what desired run verbosity is - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity From 4567556212ff8d2fe77d6a7f66ee55163f2a361f Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 14:50:44 -0500 Subject: [PATCH 16/30] better comments in L2 --- aviary/interface/methods_for_level2.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index bb6a1dd9d..4efcd235b 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -303,7 +303,7 @@ def load_inputs( an AviaryValues object and/or phase_info dict of their own. """ # We haven't read the input data yet, we don't know what desired run verbosity is - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -555,7 +555,7 @@ def check_and_preprocess_inputs(self, verbosity=None): 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. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -737,7 +737,7 @@ def add_pre_mission_systems(self, verbosity=None): A user can override this method with their own pre-mission systems as desired. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -1227,7 +1227,7 @@ def add_phases(self, phase_info_parameterization=None, verbosity=None): ------- traj: The Dymos Trajectory object containing the added mission phases. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -1404,7 +1404,7 @@ def add_post_mission_systems(self, include_landing=True, verbosity=None): A user can override this with their own postmission systems. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -1747,7 +1747,7 @@ def link_phases(self, verbosity=None): special logic to do the Dymos linkages correctly. Some of those connections for the simple GASP and FLOPS mission are shown here. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -2193,7 +2193,7 @@ def add_design_variables(self, verbosity=None): In all cases, a design variable is added for the final cruise mass of the aircraft, with no upper bound, and a residual mass constraint is added to ensure that the mass balances. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -2365,7 +2365,7 @@ def add_objective(self, objective_type=None, ref=None, verbosity=None): ValueError: If an invalid problem type is provided. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity @@ -2531,7 +2531,7 @@ def set_initial_guesses(self, parent_prob=None, parent_prefix="", verbosity=None guesses for states and controls according to the information available in the 'initial_guesses' attribute of the phase. """ - # `self.verbosity` = "true" verbosity for entire run. `verbosity` = verbosity + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity # override for just this method if verbosity is not None: # compatibility with being passed int for verbosity From ba8d89d635c49a6e7085c286c4d31fc3fb3cf6cf Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 14:52:22 -0500 Subject: [PATCH 17/30] suppress multimission bench plot --- ...multimission_example_large_single_aisle.py | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py b/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py index 2dab1dfb1..5d76cfbb2 100644 --- a/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py +++ b/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py @@ -266,32 +266,32 @@ def createN2(fileref, prob): createN2(__file__, super_prob) super_prob.run() - printoutputs = [ - (Mission.Design.GROSS_MASS, 'lbm'), - (Aircraft.Design.EMPTY_MASS, 'lbm'), - (Aircraft.Wing.SWEEP, 'deg'), - (Aircraft.LandingGear.MAIN_GEAR_MASS, 'lbm'), - (Aircraft.LandingGear.NOSE_GEAR_MASS, 'lbm'), - (Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 'unitless'), - (Aircraft.Furnishings.MASS, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 'lbm'), - (Mission.Summary.GROSS_MASS, 'lbm'), - (Mission.Summary.FUEL_BURNED, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_MASS, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), - (Aircraft.CrewPayload.CARGO_MASS, 'lbm'), - (Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm')] - super_prob.print_vars(vars=printoutputs) - - plotvars = [('altitude', 'ft'), - ('mass', 'lbm'), - ('drag', 'lbf'), - ('distance', 'nmi'), - ('throttle', 'unitless'), - ('mach', 'unitless')] - super_prob.create_timeseries_plots(plotvars=plotvars, show=False) - - plt.show() + # printoutputs = [ + # (Mission.Design.GROSS_MASS, 'lbm'), + # (Aircraft.Design.EMPTY_MASS, 'lbm'), + # (Aircraft.Wing.SWEEP, 'deg'), + # (Aircraft.LandingGear.MAIN_GEAR_MASS, 'lbm'), + # (Aircraft.LandingGear.NOSE_GEAR_MASS, 'lbm'), + # (Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 'unitless'), + # (Aircraft.Furnishings.MASS, 'lbm'), + # (Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 'lbm'), + # (Mission.Summary.GROSS_MASS, 'lbm'), + # (Mission.Summary.FUEL_BURNED, 'lbm'), + # (Aircraft.CrewPayload.PASSENGER_MASS, 'lbm'), + # (Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + # (Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + # (Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm')] + # super_prob.print_vars(vars=printoutputs) + + # plotvars = [('altitude', 'ft'), + # ('mass', 'lbm'), + # ('drag', 'lbf'), + # ('distance', 'nmi'), + # ('throttle', 'unitless'), + # ('mach', 'unitless')] + # super_prob.create_timeseries_plots(plotvars=plotvars, show=False) + + # plt.show() return super_prob From c3e49af4262c7ef3ab1ac8d2e27a9f746bdaf285 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 15:08:54 -0500 Subject: [PATCH 18/30] cleaner verbosity comments for L2 --- aviary/interface/methods_for_level2.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 4efcd235b..4ca5ebd9f 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2090,12 +2090,12 @@ def add_driver( driver.options["optimizer"] = optimizer if use_coloring: # define coloring options by verbosity - if verbosity <= Verbosity.VERBOSE: # if QUIET, BRIEF + if verbosity < Verbosity.VERBOSE: # QUIET, BRIEF driver.declare_coloring(show_summary=False) - elif verbosity == Verbosity.DEBUG: - driver.declare_coloring(show_summary=True, show_sparsity=True) - else: # if VERBOSE + elif verbosity == Verbosity.VERBOSE: driver.declare_coloring(show_summary=True) + else: # DEBUG + driver.declare_coloring(show_summary=True, show_sparsity=True) if driver.options["optimizer"] == "SNOPT": # Print Options # @@ -2103,7 +2103,7 @@ def add_driver( isumm, iprint = 0, 0 elif verbosity == Verbosity.BRIEF: isumm, iprint = 6, 0 - elif verbosity > Verbosity.BRIEF: + elif verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG isumm, iprint = 6, 9 driver.opt_settings["iSumm"] = isumm driver.opt_settings["iPrint"] = iprint @@ -2152,11 +2152,11 @@ def add_driver( if optimizer in ("SNOPT", "IPOPT"): if verbosity == Verbosity.QUIET: driver.options['print_results'] = False - elif verbosity < Verbosity.DEBUG: + elif verbosity < Verbosity.DEBUG: # QUIET, BRIEF, VERBOSE driver.options['print_results'] = 'minimal' # optimizer agnostic settings - if verbosity > Verbosity.QUIET: + if verbosity > Verbosity.QUIET: # BRIEF, VERBOSE, QUIET if isinstance(verbosity, list): driver.options['debug_print'] = ['desvars'] elif verbosity == Verbosity.DEBUG: From b21d704dfed65dc198daa7b1485e1aafc0f08681 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Thu, 26 Dec 2024 15:53:57 -0500 Subject: [PATCH 19/30] more verbosity fixes for tests --- aviary/interface/test/test_linkage_logic.py | 8 ++++---- .../flops_based/test/test_tabular_aero_group.py | 2 +- aviary/subsystems/mass/gasp_based/test/test_fixed.py | 6 +++--- aviary/utils/preprocessors.py | 10 +++------- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/aviary/interface/test/test_linkage_logic.py b/aviary/interface/test/test_linkage_logic.py index 1c414d34b..fd45b4d2d 100644 --- a/aviary/interface/test/test_linkage_logic.py +++ b/aviary/interface/test/test_linkage_logic.py @@ -181,7 +181,7 @@ def get_linkage_string(phase_1, var, phase_2): if __name__ == '__main__': - # unittest.main() - test = AircraftMissionTestSuite() - test.setUp() - test.test_linkages() + unittest.main() + # test = AircraftMissionTestSuite() + # test.setUp() + # test.test_linkages() 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 456b23524..2bc808c6d 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 @@ -95,7 +95,7 @@ def test_parameters(self): local_phase_info.pop('climb') local_phase_info.pop('descent') - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs( "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv", diff --git a/aviary/subsystems/mass/gasp_based/test/test_fixed.py b/aviary/subsystems/mass/gasp_based/test/test_fixed.py index 3e95d849c..57e0f8afb 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_fixed.py +++ b/aviary/subsystems/mass/gasp_based/test/test_fixed.py @@ -1683,7 +1683,7 @@ def test_case1(self): if __name__ == "__main__": - # unittest.main() + unittest.main() # test = GearTestCaseMultiengine() - test = EngineTestCaseMultiEngine() - test.test_case_1() + # test = EngineTestCaseMultiEngine() + # test.test_case_1() diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 05d6c1245..0b5afe3f2 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -35,10 +35,6 @@ def preprocess_options(aviary_options: AviaryValues, **kwargs): verbosity = _MetaData[Settings.VERBOSITY]['default_value'] aviary_options.set_val(Settings.VERBOSITY, verbosity) - if Settings.VERBOSITY not in aviary_options: - verbosity = _MetaData[Settings.VERBOSITY]['default_value'] - aviary_options.set_val(Settings.VERBOSITY, verbosity) - preprocess_crewpayload(aviary_options, verbosity) preprocess_propulsion(aviary_options, engine_models, verbosity) @@ -136,11 +132,11 @@ def preprocess_crewpayload(aviary_options: AviaryValues, verbosity=None): aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS)) # user has not supplied detailed information on design but has supplied summary information on passengers elif num_pax != 0 and design_num_pax == 0: - if verbosity >= 2: + if verbosity >= Verbosity.VERBOSE: print("User has specified as-flown NUM_PASSENGERS but not how many passengers the aircraft was designed for in Design.NUM_PASSENGERS. Assuming they are equal.") aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, num_pax) elif design_passenger_count != 0 and num_pax == 0 and passenger_count == 0: - if verbosity >= 1: + if verbosity >= Verbosity.BRIEF: print("User has specified Design.NUM_* passenger values but CrewPyaload.NUM_* has been left blank or set to zero.") print( "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") @@ -155,7 +151,7 @@ def preprocess_crewpayload(aviary_options: AviaryValues, verbosity=None): aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS)) # user has not supplied detailed information on design but has supplied summary information on passengers elif design_num_pax != 0 and num_pax == 0: - if verbosity >= 1: + if verbosity >= Verbosity.BRIEF: print("User has specified Design.NUM_PASSENGERS but CrewPayload.NUM_PASSENGERS has been left blank or set to zero.") print( "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") From 3dec4d128dacd8f588600e7f65e90bec207f8f74 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 27 Dec 2024 11:38:24 -0500 Subject: [PATCH 20/30] formatting fixes --- aviary/interface/methods_for_level2.py | 4 ++-- aviary/utils/preprocessors.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 4ca5ebd9f..cf2515e55 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2472,8 +2472,8 @@ def _add_bus_variables_and_connect(self): self.model.connect( f'pre_mission.{bus_variable}', - f'traj.{phase_name}.parameters:{ - mission_var_name}', + f'traj.{phase_name}.parameters:' + f'{mission_var_name}', ) else: diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 0b5afe3f2..c4554cfb1 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -402,11 +402,11 @@ def preprocess_propulsion( num_engines_all[i] = total_engines_calc if verbosity >= Verbosity.VERBOSE: warnings.warn( - 'Sum of aircraft:engine:num_fueslage_engines and ' + 'Sum of aircraft:engine:num_fuselage_engines and ' 'aircraft:engine:num_wing_engines do not match ' - f'aircraft:engine:num_engines for EngineModel <{ - eng_name}>. Overwriting ' - 'with the sum of wing and fuselage mounted engines.' + 'aircraft:engine:num_engines for EngineModel ' + f'<{eng_name}>. Overwriting with the sum of wing and fuselage ' + 'mounted engines.' ) elif total_engines_calc < num_engines: # fewer defined locations than num_engines - assume rest are wing mounted From 6c3b9e3cec5b4837b61dea4343cb2715f9e87a6f Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 27 Dec 2024 11:48:14 -0500 Subject: [PATCH 21/30] fixes for doc glue checks --- aviary/interface/methods_for_level2.py | 2 +- aviary/utils/preprocessors.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index cf2515e55..fbdacbf8f 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -3018,7 +3018,7 @@ def run_aviary_problem( failed = self.run_model() warnings.filterwarnings('default', category=UserWarning) - if verbosity >= Verbosity.DEBUG: # DEBUG + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG with open('output_list.txt', 'w') as outfile: self.model.list_outputs(out_stream=outfile) diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index c4554cfb1..693bec365 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -251,7 +251,10 @@ def preprocess_propulsion( # compatibility with being passed int for verbosity verbosity = Verbosity(verbosity) else: - verbosity = aviary_options.get_val(Settings.VERBOSITY) + if verbosity in aviary_options: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + else: + verbosity = Verbosity.BRIEF ############################## # Vectorize Engine Variables # From 935a023e86762878873abdc9f67cd7b43e3740dd Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 27 Dec 2024 15:31:30 -0500 Subject: [PATCH 22/30] fix invalid char warning for regex --- .gitignore | 1 + aviary/docs/examples/modified_aircraft.csv | 8 +-- aviary/docs/examples/outputted_phase_info.py | 23 ++++++++- aviary/utils/csv_data_file.py | 53 +++++++++++++------- 4 files changed, 62 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 26bc1c3c3..acc55570e 100644 --- a/.gitignore +++ b/.gitignore @@ -132,6 +132,7 @@ dmypy.json # Test and spec generated reports/ aviary/reports/ +*.openmdao_out *.out *.png *.sql diff --git a/aviary/docs/examples/modified_aircraft.csv b/aviary/docs/examples/modified_aircraft.csv index b2ab642a3..d354187a8 100644 --- a/aviary/docs/examples/modified_aircraft.csv +++ b/aviary/docs/examples/modified_aircraft.csv @@ -7,17 +7,17 @@ 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:design:num_business_class,0,unitless +aircraft:crew_and_payload:design:num_first_class,11,unitless +aircraft:crew_and_payload:design:num_passengers,169,unitless +aircraft:crew_and_payload:design:num_tourist_class,158,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_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 diff --git a/aviary/docs/examples/outputted_phase_info.py b/aviary/docs/examples/outputted_phase_info.py index daf97400c..0737bef2c 100644 --- a/aviary/docs/examples/outputted_phase_info.py +++ b/aviary/docs/examples/outputted_phase_info.py @@ -1,2 +1,21 @@ -phase_info = {'pre_mission': {'include_takeoff': True, 'optimize_mass': True}, 'climb_1': {'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, 'user_options': {'optimize_mach': True, 'optimize_altitude': True, 'polynomial_control_order': [1, 2], 'use_polynomial_control': True, 'num_segments': [1], 'order': 1, 'solve_for_distance': True, 'initial_mach': (1, None), 'final_mach': (2, None), 'mach_bounds': ( - (0.98, 2.02), None), 'initial_altitude': (1, None), 'final_altitude': (2, None), 'altitude_bounds': ((0.0, 502), None), 'throttle_enforcement': 'path_constraint', 'fix_initial': True, 'constrain_final': True, 'fix_duration': False, 'initial_bounds': ((0.0, 0.0), None), 'duration_bounds': ((0.5, 1.5), None)}, 'initial_guesses': {'time': ([1, 1], None)}}, 'post_mission': {'include_landing': True, 'constrain_range': True, 'target_range': (514.5, None)}} +phase_info = { + 'pre_mission': { + 'include_takeoff': True, 'optimize_mass': True}, 'climb_1': { + 'subsystem_options': { + 'core_aerodynamics': { + 'method': 'computed'}}, 'user_options': { + 'optimize_mach': True, 'optimize_altitude': True, 'polynomial_control_order': [ + 1, 2], 'use_polynomial_control': True, 'num_segments': [1], 'order': 1, 'solve_for_distance': True, 'initial_mach': ( + 1, None), 'final_mach': ( + 2, None), 'mach_bounds': ( + (0.98, 2.02), None), 'initial_altitude': ( + 1, None), 'final_altitude': ( + 2, None), 'altitude_bounds': ( + (0.0, 502), None), 'throttle_enforcement': 'path_constraint', 'fix_initial': True, 'constrain_final': True, 'fix_duration': False, 'initial_bounds': ( + (0.0, 0.0), None), 'duration_bounds': ( + (0.5, 1.5), None)}, 'initial_guesses': { + 'time': ( + [ + 1, 1], None)}}, 'post_mission': { + 'include_landing': True, 'constrain_range': True, 'target_range': ( + 514.5, None)}} diff --git a/aviary/utils/csv_data_file.py b/aviary/utils/csv_data_file.py index 551c938fe..de069fa02 100644 --- a/aviary/utils/csv_data_file.py +++ b/aviary/utils/csv_data_file.py @@ -11,11 +11,17 @@ from aviary.utils.named_values import get_items, get_keys from aviary.utils.functions import get_path from aviary.utils.named_values import NamedValues +from aviary.variable_info.enums import Verbosity # multiple type annotation uses "typeA | typeB" syntax, but requires Python 3.10+ -def read_data_file(filename: (str, Path), metadata=None, aliases=None, - save_comments=False): +def read_data_file( + filename, + metadata=None, + aliases=None, + save_comments=False, + verbosity=Verbosity.BRIEF, +): """ Read data file in Aviary format, which is data delimited by commas with any amount of whitespace allowed between data entries. Spaces are not allowed in openMDAO @@ -35,18 +41,22 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, are a list of headers that correspond to that variable. Alias matching is not case-sensitive, and underscores and spaces are treated as equivalent. save_comments : bool, optional - flag if comments in data file should be returned along with data. Defaults to + flag if comments in data file should be returned along with data. Defaults to False. + verbosity : (int, Verbosity), optional + controls level of printouts when running this method. Default is BRIEF (1). Returns ------- data : NamedValues - data read from file in NamedValues format, including variable name, units, and + data read from file in NamedValues format, including variable name, units, and values (stored in a numpy array) comments : list of str - any comments from file, with comment characters ('#') stripped out (only if + any comments from file, with comment characters ('#') stripped out (only if save_comments=True) """ + verbosity = Verbosity(verbosity) + filepath = get_path(filename) data = NamedValues() @@ -57,7 +67,7 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, for key in aliases: if isinstance(aliases[key], str): aliases[key] = [aliases[key]] - aliases[key] = [re.sub('\s', '_', item).lower() for item in aliases[key]] + aliases[key] = [re.sub('\\s', '_', item).lower() for item in aliases[key]] with open(filepath, newline=None, encoding='utf-8-sig') as file: # csv.reader() and other avaliable packages that can read csv files are not used @@ -92,8 +102,8 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, for index in range(len(line_data)): item = re.split('[(]', line_data[index]) item = [item[i].strip(') ') for i in range(len(item))] - # openMDAO vars can't have spaces, convert to underscores - name = re.sub('\s', '_', item[0]) + # OpenMDAO vars can't have spaces, convert to underscores + name = re.sub('\\s', '_', item[0]) if aliases: # "reverse" lookup name in alias dict for key in aliases: @@ -106,9 +116,11 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, # default_units if metadata is not None: if name not in metadata.keys(): - warnings.warn(f'Header <{name}> was not recognized, and ' - 'will be skipped' - ) + if verbosity > Verbosity.QUIET: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'<{filename}: Header <{name}> was not ' + 'recognized, and will be skipped' + ) continue else: default_units = metadata[name]['units'] @@ -136,10 +148,13 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, if metadata is not None and default_units != 'unitless': # units were not provided, but variable should have them # assume default units for that variable - warning = f'Units were not provided for column <{name}> '\ - f'while reading <{filepath}>. Using default '\ - f'units of {default_units}.' - warnings.warn(warning) + if verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG + warning = ( + f'Units were not provided for column <{name}> ' + f'while reading <{filepath}>. Using default ' + f'units of {default_units}.' + ) + warnings.warn(warning) units = default_units header[name] = units @@ -175,8 +190,12 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, # multiple type annotation uses "typeA | typeB" syntax, but requires Python 3.10+ -def write_data_file(filename: (str, Path) = None, data: NamedValues = None, - comments: (str, list) = [], include_timestamp: bool = False): +def write_data_file( + filename, + data: NamedValues = None, + comments=[], + include_timestamp: bool = False, +): """ Write data to a comma-separated values (csv) format file using the Aviary data table format. From e1bad534b3d63f98b03da540ff0e082af7a39472 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 27 Dec 2024 16:19:30 -0500 Subject: [PATCH 23/30] doc updates --- aviary/docs/examples/intro.ipynb | 4 +- .../getting_started/onboarding_level1.ipynb | 59 +++---------------- .../getting_started/onboarding_level2.ipynb | 4 +- .../misc_resources/planned_future_features.md | 5 -- aviary/docs/user_guide/aviary_commands.ipynb | 7 +-- aviary/utils/preprocessors.py | 4 +- 6 files changed, 18 insertions(+), 65 deletions(-) diff --git a/aviary/docs/examples/intro.ipynb b/aviary/docs/examples/intro.ipynb index 4c24a1ad7..b05eadba7 100644 --- a/aviary/docs/examples/intro.ipynb +++ b/aviary/docs/examples/intro.ipynb @@ -53,7 +53,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -67,7 +67,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level1.ipynb b/aviary/docs/getting_started/onboarding_level1.ipynb index bbae17fe3..e3cc295a4 100644 --- a/aviary/docs/getting_started/onboarding_level1.ipynb +++ b/aviary/docs/getting_started/onboarding_level1.ipynb @@ -113,9 +113,9 @@ "\n", "- `-o ––outdir`: Use specified directory to write output. The default is the current directory.\n", "\n", - "- `--optimizer`: Name of optimizer. Choices are: `SNOPT`, `IPOPT`, `SLSQP`, and `None`. The default is `SNOPT`. If optimizer is `None`, it will be set to `IPOPT` or `SNOPT` depending on the analysis scheme. The optimization objective is fuel burn for level 1 runs. The objective is\n", - " - `mission:objectives:fuel` if `mission_method` is `GASP` \n", - " - `fuel_burned` if `mission_method` is `FLOPS`.\n", + "- `--optimizer`: Name of optimizer. Choices are: `SNOPT`, `IPOPT`, `SLSQP`. The default is `IPOPT`. The optimization objective is fuel burn for level 1 runs. The objective is\n", + " - `mission:objectives:fuel` if `mission_method` is `TWO_DEGREES_OF_FREEDOM` \n", + " - `fuel_burned` if `mission_method` is `HEIGHT_ENERGY`.\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 `simple`.\n", "\n", @@ -223,50 +223,9 @@ "\n", "To find information about a variable (e.g. description, data type, etc.), users should read the [Variable Metadata Doc](../user_guide/variable_metadata).\n", "\n", - "There are special rules for the mapping from the input file variable names to the metadata. For example, variable `aircraft:wing:aspect_ratio` in `aircraft_for_bench_GwGm.csv` is mapped to `Aircraft.Wing.ASPECT_RATIO` in `aviary/variable_info/variable_meta_data.py`. So, the first part (e.g., `aircraft` or `mission`) is mapped to the same word but with the first letter capitalized (e.g., `Aircraft` or `Mission`). The third word is all caps (e.g., `ASPECT_RATIO`). The middle part (e.g., `wing`) is a little more complicated. In most cases, this part capitalizes the first letter (e.g., `Wing`). The following words have special mappings:\n", + "Variable names may be differently within the code from how they are formatted inside OpenMDAO components and in input files and outputs. For example, variable `aircraft:wing:aspect_ratio` in `aircraft_for_bench_GwGm.csv` is mapped to `Aircraft.Wing.ASPECT_RATIO` in `aviary/variable_info/variable_meta_data.py`. This is because OpenMDAO requires variable names to be strings, but for developer convenience those strings are mapped to Python classes and attributes. The top-level and sub-categories have capitalized first letters, and the final variable name is always in all-caps. For more information on Aviary's variable hierarchy, see the [Variable Hierarchy doc](../user_guide/variable_hierarchy.ipynb).\n", "\n", - "- `air_conditioning -> AirConditioning`\n", - "- `anti_icing -> AntiIcing`\n", - "- `blended_wing_body -> BWB`\n", - "- `crew_and_payload -> CrewPayload`\n", - "- `horizontal_tail -> HorizontalTail`\n", - "- `landing_gear -> LandingGear`\n", - "- `tail_boom -> TailBoom`\n", - "- `vertical_tail -> VerticalTail`\n", - "\n", - "This can be summarized as to capitalize the leading letter and to capitalize the first letter after special character “`_`”.\n", - "\n", - "File `aviary/variable_info/variables.py` is a variable hierarchy that is for a single mission. Each mission gets a copy of this hierarchy. Below is a snippet of this file:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f57d6c96", - "metadata": { - "tags": [ - "remove-input" - ] - }, - "outputs": [], - "source": [ - "import aviary.api as av\n", - "\n", - "# Get the path of variables.py within the aviary package\n", - "file_path = av.get_path('variable_info/variables.py')\n", - "\n", - "# Read and print the first 15 lines of the file\n", - "with open(file_path, 'r') as file:\n", - " for i in range(18):\n", - " print(file.readline().strip('\\n'))" - ] - }, - { - "cell_type": "markdown", - "id": "b597474e", - "metadata": {}, - "source": [ - "Aviary variables are always set to default values before the input file is read in. Then Aviary will update the values based on the user-provided `.csv` input file. If you want to set different values, you can set them in the `.csv` input file." + "Aviary variables that are not defined in the `.csv` input file are set to their default values, as described in the variable metadata." ] }, { @@ -329,14 +288,14 @@ "\n", "This [`fortran_to_aviary`](../user_guide/aviary_commands) tool converts FORTRAN namelists into Aviary's csv based format using the mappings found in the `historical_name` section of the [variable_meta_data](../user_guide/variable_metadata). The resulting csv is automatically sorted into three sections:\n", "1. **Input Values:**\n", - " Any FORTRAN variables that were mapped to input variables in Aviary components\n", + " Any FORTRAN variables that were mapped to input variables in the variable metadata, converted to their equivalent Aviary names\n", "2. **Initial Guesses:**\n", " Some variables are only used as initial guesses for the trajectory.\n", " These are displayed separately from the Input Values because they will not be passed directly to components\n", "3. **Unconverted Values:**\n", " If the fortran_to_aviary converter can't find an Aviary variable that matches the FORTRAN variable, it is added to the end of the csv file.\n", " We recommend that you check this section after converting a namelist to ensure that there aren't any variables you expected to be converted here.\n", - " Many of these unconverted variables represent features or options that are not used in Aviary and can be safely ignored. Variables related to mission definition are important, but Aviary defines mission profiles in a significantly different way. Currently, the user must build a new [mission definition file](../examples/simple_mission_example) that recreates the mission.\n", + " Many of these unconverted variables represent features or options that are not used in Aviary and can be ignored. Variables related to mission definition are important, but Aviary defines mission profiles in a significantly different way. Currently, the user must build a new [mission definition file](../examples/simple_mission_example) that recreates the mission.\n", " Aviary will ignore unconverted variables when loading the csv, so you can safely leave them.\n" ] }, @@ -764,7 +723,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -778,7 +737,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index cbad194b5..72585b24c 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -1006,7 +1006,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -1020,7 +1020,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/misc_resources/planned_future_features.md b/aviary/docs/misc_resources/planned_future_features.md index e2660c776..5b4c42ffb 100644 --- a/aviary/docs/misc_resources/planned_future_features.md +++ b/aviary/docs/misc_resources/planned_future_features.md @@ -3,17 +3,12 @@ Aviary is under active development and new features are being added regularly. The following is a non-exhaustive list of planned features that are not yet implemented. (The Aviary team reserves the right to remove features from this list if the need arises. This list is provided for informational purposes only and is not a commitment to perform work.) -- The ability to run off-design missions to develop payload-range diagrams - The full capabilities of FLOPS and GASP to model medium and large sized commercial aircraft, with a few exceptions that have been determined unnecessary -- The tested ability to have different types of engines on the same aircraft -- The ability to accept propeller maps for modeling propeller-driven aircraft - A converter to convert a table of mach/altitude combinations into a phase_info file. This capability exists in the simple mission GUI, but it will be tweaked to allow for the direct input of tabular data as an alternative to the GUI - Natively supported builders for certain high-interest external subsystem tools. Some potential tools to support are: NPSS, pyCycle, OpenVSP, VSPaero, OpenAeroStruct, etc. The Aviary team develops these builders as the need arises, and the development or lack of it for a certain tool does not indicate endorsement of the tool. - Improved cleanliness of the code - Improved ease-of-use for the user interface - Improved Fortran-to-Aviary converter which requires no human intervention or checking - Support for relevant FAA regulations governing aircraft design and operation -- Capability to fly reserve missions using the same mission analysis techniques as the main mission (right now reserve estimates are fixed values or fixed percentages of mission fuel) -- Improved model re-run capability - Full test suite that tests the code format, including testing for docstrings on all functions and classes - Fully tested code blocks in the documentation \ No newline at end of file diff --git a/aviary/docs/user_guide/aviary_commands.ipynb b/aviary/docs/user_guide/aviary_commands.ipynb index 853d6ec5e..eb9672896 100644 --- a/aviary/docs/user_guide/aviary_commands.ipynb +++ b/aviary/docs/user_guide/aviary_commands.ipynb @@ -138,8 +138,7 @@ "metadata": {}, "source": [ "`input_deck` is the path to vehicle input deck .csv file.\n", - "`-o` or `--outdir` is the directory to write outputs. The default is current directory.\n", - "`--optimizer` is the name of the optimizer. The default is `SNOPT`.\n", + "`--optimizer` is the name of the optimizer. The default is `IPOPT`.\n", "`--shooting` indicates that the integration method is shooting method instead of collocation scheme. The default is collocation.\n", "`--phase_info` is the path to phase info file. If it is missing, it depends on the integration method (collocation or shooting) and on the mission method (settings:equations+of_motion with value of `2DOF` or `height_energy`) which is defined in the .csv input file.\n", "`--max_iter` is the maximum number of iterations. The default is 50.\n", @@ -558,7 +557,7 @@ "metadata": { "celltoolbar": "Tags", "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -572,7 +571,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 693bec365..1f1b220d0 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -136,7 +136,7 @@ def preprocess_crewpayload(aviary_options: AviaryValues, verbosity=None): print("User has specified as-flown NUM_PASSENGERS but not how many passengers the aircraft was designed for in Design.NUM_PASSENGERS. Assuming they are equal.") aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, num_pax) elif design_passenger_count != 0 and num_pax == 0 and passenger_count == 0: - if verbosity >= Verbosity.BRIEF: + if verbosity >= Verbosity.VERBOSE: print("User has specified Design.NUM_* passenger values but CrewPyaload.NUM_* has been left blank or set to zero.") print( "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") @@ -151,7 +151,7 @@ def preprocess_crewpayload(aviary_options: AviaryValues, verbosity=None): aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS)) # user has not supplied detailed information on design but has supplied summary information on passengers elif design_num_pax != 0 and num_pax == 0: - if verbosity >= Verbosity.BRIEF: + if verbosity >= Verbosity.VERBOSE: print("User has specified Design.NUM_PASSENGERS but CrewPayload.NUM_PASSENGERS has been left blank or set to zero.") print( "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") From 844dab781dd0952b449051a1bf14a13f95bd5f0c Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Mon, 30 Dec 2024 10:47:52 -0500 Subject: [PATCH 24/30] formatting fix --- aviary/interface/methods_for_level2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index fbdacbf8f..dc66c9e13 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -2497,8 +2497,8 @@ def _add_bus_variables_and_connect(self): if 'post_mission_name' in variable_data: self.model.connect( f'pre_mission.{external_subsystem.name}.{bus_variable}', - f'post_mission.{external_subsystem.name}.{ - variable_data["post_mission_name"]}', + f'post_mission.{external_subsystem.name}.' + f'{variable_data["post_mission_name"]}', ) def setup(self, **kwargs): From 70e41278233e95dd3bc3b30db07aff2785d9c9ff Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Tue, 31 Dec 2024 13:49:04 -0500 Subject: [PATCH 25/30] properly incremented version number --- aviary/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/__init__.py b/aviary/__init__.py index 7f33873b3..50533e307 100644 --- a/aviary/__init__.py +++ b/aviary/__init__.py @@ -1 +1 @@ -__version__ = "0.9.4-dev" +__version__ = "0.9.6" From 8b02f1acbc92b3cc09394c439ac53ad34b9fe345 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Tue, 31 Dec 2024 15:14:26 -0500 Subject: [PATCH 26/30] mach -> Mach in comments/docstrings --- .../getting_started/input_csv_phase_info.ipynb | 4 ++-- aviary/docs/user_guide/aerodynamics.ipynb | 14 +++++++++++++- aviary/docs/user_guide/external_aero.ipynb | 4 ++-- .../default_phase_info/height_energy_fiti.py | 2 +- aviary/interface/default_phase_info/two_dof.py | 2 +- .../interface/default_phase_info/two_dof_fiti.py | 2 +- aviary/mission/gasp_based/ode/climb_ode.py | 6 +++--- .../ode/constraints/speed_constraints.py | 4 ++-- aviary/mission/gasp_based/ode/descent_ode.py | 9 ++++++--- aviary/mission/gasp_based/ode/flight_path_ode.py | 8 ++++++-- .../unsteady_solved_flight_conditions.py | 10 +++++----- .../subsystems/aerodynamics/flops_based/design.py | 7 ++++--- .../aerodynamics/flops_based/drag_polar.py | 2 +- .../aerodynamics/flops_based/skin_friction.py | 2 +- .../flops_based/test/test_solved_aero_group.py | 10 +++++++--- .../aerodynamics/gasp_based/flaps_model/Cl_max.py | 4 ++-- .../gasp_based/flaps_model/L_and_D_increments.py | 5 ++++- .../gasp_based/flaps_model/meta_model.py | 4 ++-- aviary/subsystems/atmosphere/flight_conditions.py | 8 ++++---- aviary/subsystems/mass/gasp_based/design_load.py | 9 ++++++--- aviary/subsystems/mass/gasp_based/fixed.py | 6 ++++-- aviary/subsystems/propulsion/engine_deck.py | 10 +++++----- aviary/utils/engine_deck_conversion.py | 4 ++-- aviary/variable_info/enums.py | 2 +- aviary/variable_info/variable_meta_data.py | 8 ++++---- 25 files changed, 89 insertions(+), 57 deletions(-) diff --git a/aviary/docs/getting_started/input_csv_phase_info.ipynb b/aviary/docs/getting_started/input_csv_phase_info.ipynb index 1195b3b9f..da28e12ff 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.ipynb +++ b/aviary/docs/getting_started/input_csv_phase_info.ipynb @@ -210,7 +210,7 @@ " - {glue:md}`include_landing`: the flag to indicate whether there is a landing phase.\n", " - {glue:md}`include_takeoff`: the flag to indicate whether there is a takeoff phase.\n", " - {glue:md}`optimize_mass`: if True, the gross takeoff mass of the aircraft is a design variable.\n", - " - {glue:md}`target_mach`: the flag to indicate whether to target mach number.\n", + " - {glue:md}`target_mach`: the flag to indicate whether to target Mach number.\n", "- {glue:md}`initial_guesses`: initial guesses of state variables.\n", "- `COLLOCATION` related keys:\n", " - {glue:md}`num_segments`: the number of segments in transcription creation in Dymos. The minimum value is 1. This is needed if 'AnalysisScheme' is `COLLOCATION`.\n", @@ -223,7 +223,7 @@ " - {glue:md}`EAS_target`: the target equivalent airspeed.\n", " - {glue:md}`initial_mach`: initial Mach number.\n", " - {glue:md}`linear_solver`: provide an instance of a [LinearSolver](https://openmdao.org/newdocs/versions/latest/features/core_features/controlling_solver_behavior/set_solvers.html) to the phase. \n", - " - {glue:md}`mach_cruise`: the cruise mach number.\n", + " - {glue:md}`mach_cruise`: the cruise Mach number.\n", " - {glue:md}`nonlinear_solver`: provide an instance of a [NonlinearSolver](https://openmdao.org/newdocs/versions/latest/features/core_features/controlling_solver_behavior/set_solvers.html) to the phase. \n", " - {glue:md}`polynomial_control_order`: default to `None`.\n", " - {glue:md}`fix_duration`: default to `False`.\n", diff --git a/aviary/docs/user_guide/aerodynamics.ipynb b/aviary/docs/user_guide/aerodynamics.ipynb index 023e8883a..04979105d 100644 --- a/aviary/docs/user_guide/aerodynamics.ipynb +++ b/aviary/docs/user_guide/aerodynamics.ipynb @@ -151,6 +151,18 @@ " pass" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -160,7 +172,7 @@ "\n", "You can also use GASP-based aero with the height-energy mission by using the `solved_alpha` method.\n", "\n", - "Gasp-based drag polars have 3 inputs: altitude, mach number, and angle of attack. Since the height-energy equations of motion do not incorporate angle of attack, `solved_alpha` creates an computational group with a solver that varies the angle of attack until the interpolated lift matches the weight force on the aircraft. The format for the table in the file is the same as for GASP-based aerodynamics used with the 2-DOF mission.\n", + "Gasp-based drag polars have 3 inputs: altitude, Mach number, and angle of attack. Since the height-energy equations of motion do not incorporate angle of attack, `solved_alpha` creates an computational group with a solver that varies the angle of attack until the interpolated lift matches the weight force on the aircraft. The format for the table in the file is the same as for GASP-based aerodynamics used with the 2-DOF mission.\n", "\n", "## Externally Computed Polars\n", "\n", diff --git a/aviary/docs/user_guide/external_aero.ipynb b/aviary/docs/user_guide/external_aero.ipynb index 40936bd6e..2548d2d6a 100644 --- a/aviary/docs/user_guide/external_aero.ipynb +++ b/aviary/docs/user_guide/external_aero.ipynb @@ -9,7 +9,7 @@ "\n", "This example shows how to build, using the level-2 interface, an aviary model that includes an external susbsystem that computes a lift and drag polar and passes them into the mission aerodynamics for a 3-phase mission (climb, cruise, descent). During the mission, Aviary will interpolate on the computed polars to compute actual lift and drag for a given flight condition.\n", "\n", - "We start with the assumption that we have an external component called `ExternalAero` that can compute the lift and drag at any given altitude, mach number, and angle of attack. The details of such a component may be highly complicated and not important for the purposes of this example. We will be using a structured grid, which assumes the data table is regularly spaced in all dimensions. We want to compute lift and drag over a grid of altitudes (in 'ft'), mach numbers, and angles of attack given by:" + "We start with the assumption that we have an external component called `ExternalAero` that can compute the lift and drag at any given altitude, Mach number, and angle of attack. The details of such a component may be highly complicated and not important for the purposes of this example. We will be using a structured grid, which assumes the data table is regularly spaced in all dimensions. We want to compute lift and drag over a grid of altitudes (in 'ft'), Mach numbers, and angles of attack given by:" ] }, { @@ -62,7 +62,7 @@ " self.options.declare(\"altitude\", default=None, allow_none=True,\n", " desc=\"List of altitudes in ascending order.\")\n", " self.options.declare(\"mach\", default=None, allow_none=True,\n", - " desc=\"List of mach numbers in ascending order.\")\n", + " desc=\"List of Mach numbers in ascending order.\")\n", " self.options.declare(\"angle_of_attack\", default=None, allow_none=True,\n", " desc=\"List of angles of attack in ascending order.\")\n", "\n", diff --git a/aviary/interface/default_phase_info/height_energy_fiti.py b/aviary/interface/default_phase_info/height_energy_fiti.py index dfb0b5901..e82986506 100644 --- a/aviary/interface/default_phase_info/height_energy_fiti.py +++ b/aviary/interface/default_phase_info/height_energy_fiti.py @@ -48,7 +48,7 @@ def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs: AviaryValues): """ Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise mach number, + for the following mission design inputs: cruise altitude, cruise Mach number, cruise range, design gross mass. Parameters diff --git a/aviary/interface/default_phase_info/two_dof.py b/aviary/interface/default_phase_info/two_dof.py index e5dd9e40c..7360f7c0e 100644 --- a/aviary/interface/default_phase_info/two_dof.py +++ b/aviary/interface/default_phase_info/two_dof.py @@ -291,7 +291,7 @@ 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, + for the following mission design inputs: cruise altitude, cruise Mach number, cruise range, design gross mass. Parameters diff --git a/aviary/interface/default_phase_info/two_dof_fiti.py b/aviary/interface/default_phase_info/two_dof_fiti.py index e8e66d501..ddda01e19 100644 --- a/aviary/interface/default_phase_info/two_dof_fiti.py +++ b/aviary/interface/default_phase_info/two_dof_fiti.py @@ -155,7 +155,7 @@ def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs: AviaryValues): """ Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise mach number, + for the following mission design inputs: cruise altitude, cruise Mach number, cruise range, design gross mass. Parameters diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index 19f17677e..2fb77a7ef 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -31,7 +31,7 @@ def initialize(self): "input_speed_type", default=SpeedType.EAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number", + desc="Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number", ) self.options.declare( "alt_trigger_units", @@ -47,11 +47,11 @@ def initialize(self): "input_speed_type", default=SpeedType.EAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number", + desc="Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number", ) self.options.declare("EAS_target", desc="target climbing EAS in knots") self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + "mach_cruise", default=0, desc="targeted cruise Mach number" ) def setup(self): diff --git a/aviary/mission/gasp_based/ode/constraints/speed_constraints.py b/aviary/mission/gasp_based/ode/constraints/speed_constraints.py index f171026a0..a79fe70d3 100644 --- a/aviary/mission/gasp_based/ode/constraints/speed_constraints.py +++ b/aviary/mission/gasp_based/ode/constraints/speed_constraints.py @@ -18,7 +18,7 @@ def initialize(self): " satisfied", ) self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + "mach_cruise", default=0, desc="targeted cruise Mach number" ) def setup(self): @@ -35,7 +35,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.ones(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.add_output( diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index 9cc39fed7..90343de0d 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -29,14 +29,17 @@ class DescentODE(BaseODE): def initialize(self): super().initialize() - self.options.declare("input_speed_type", types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") + self.options.declare( + "input_speed_type", + types=SpeedType, + desc="Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number", + ) self.options.declare("alt_trigger_units", default='ft', desc='The units that the altitude trigger is provided in') self.options.declare("speed_trigger_units", default='kn', desc='The units that the speed trigger is provided in.') self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + "mach_cruise", default=0, desc="targeted cruise Mach number" ) self.options.declare( "EAS_limit", default=0, desc="maximum descending EAS in knots" diff --git a/aviary/mission/gasp_based/ode/flight_path_ode.py b/aviary/mission/gasp_based/ode/flight_path_ode.py index dc87ee833..ae21e0b49 100644 --- a/aviary/mission/gasp_based/ode/flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/flight_path_ode.py @@ -21,8 +21,12 @@ class FlightPathODE(BaseODE): def initialize(self): super().initialize() self.options.declare("alpha_mode", default=AlphaModes.DEFAULT, types=AlphaModes) - self.options.declare("input_speed_type", default=SpeedType.TAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") + self.options.declare( + "input_speed_type", + default=SpeedType.TAS, + types=SpeedType, + desc="Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number", + ) self.options.declare( "ground_roll", types=bool, 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 af2b8bdea..8e5ab084e 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 @@ -48,7 +48,7 @@ def initialize(self): "input_speed_type", default=SpeedType.TAS, types=SpeedType, - desc="tells whether the input airspeed is equivalent airspeed, true airspeed, or mach number", + desc="tells whether the input airspeed is equivalent airspeed, true airspeed, or Mach number", ) self.options.declare("ground_roll", types=bool, default=False, desc="True if the aircraft is confined to the ground. " @@ -121,7 +121,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.declare_partials( @@ -187,7 +187,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.declare_partials( @@ -232,13 +232,13 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.add_input( "dmach_dr", val=np.zeros(nn), units="unitless/distance_units", - desc="change in mach number per unit range", + desc="change in Mach number per unit range", ) self.add_input( "dsos_dh", diff --git a/aviary/subsystems/aerodynamics/flops_based/design.py b/aviary/subsystems/aerodynamics/flops_based/design.py index e95d5df21..0ab64ccd4 100644 --- a/aviary/subsystems/aerodynamics/flops_based/design.py +++ b/aviary/subsystems/aerodynamics/flops_based/design.py @@ -1,7 +1,8 @@ """ -OpenMDAO component to compute the design mach number and design coefficient of lift, +OpenMDAO component to compute the design Mach number and design coefficient of lift, based on the calculations used in FLOPS and LEAPS 1.0. """ + import numpy as np import openmdao.api as om from openmdao.components.interp_util.interp import InterpND @@ -13,7 +14,7 @@ class Design(om.ExplicitComponent): """ - Calculates the design mach number and coefficient of lift. + Calculates the design Mach number and coefficient of lift. Based on subroutines MDESN and CLDESN in FLOPS. """ @@ -63,7 +64,7 @@ def compute(self, inputs, outputs): outputs[Mission.Design.LIFT_COEFFICIENT] = CLDES - # design mach equation selected based on thickness/chord ratio or maximum mach number + # design Mach equation selected based on thickness/chord ratio or maximum Mach number if TC.real > 0.065 or VMAX < 1.0: # subsonic TC23 = TC ** (2.0 / 3.0) diff --git a/aviary/subsystems/aerodynamics/flops_based/drag_polar.py b/aviary/subsystems/aerodynamics/flops_based/drag_polar.py index 1e673bb5c..4d55ed77b 100644 --- a/aviary/subsystems/aerodynamics/flops_based/drag_polar.py +++ b/aviary/subsystems/aerodynamics/flops_based/drag_polar.py @@ -13,7 +13,7 @@ class DragPolar(om.ExplicitComponent): """ This will need to create an instance of the dynamic aero group, perhaps as a - subproblem, and run it at the table of mach numbers and lift coefficients. Right now, + subproblem, and run it at the table of Mach numbers and lift coefficients. Right now, it is a placeholder, and also serves as a sink for all parts of the aircraft data structures that are passed to the dynamic portion, so that they can be overridden if needed. diff --git a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py index aa6d9373a..0f79e9fcb 100644 --- a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py +++ b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py @@ -11,7 +11,7 @@ class SkinFriction(om.ImplicitComponent): in FLOPS AERSCL. The fixed-point iteration scheme has been replaced with Newton's method, which can - converge the equations for multiple mach numbers and characteristic lengths + converge the equations for multiple Mach numbers and characteristic lengths simultaneously. """ 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 5e752099b..b0dd467ba 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 @@ -214,8 +214,12 @@ def initialize(self): """ self.options.declare("altitude", default=None, allow_none=True, desc="List of altitudes in ascending order.") - self.options.declare("mach", default=None, allow_none=True, - desc="List of mach numbers in ascending order.") + self.options.declare( + "mach", + default=None, + allow_none=True, + desc="List of Mach numbers in ascending order.", + ) self.options.declare("alpha", default=None, allow_none=True, desc="List of angles of attack in ascending order.") @@ -252,7 +256,7 @@ class FakeDragPolarBuilder(SubsystemBuilderBase): altitude : list or None List of altitudes in ascending order. (Optional) mach : list or None - List of mach numbers in ascending order. (Optional) + List of Mach numbers in ascending order. (Optional) alpha : list or None List of angles of attack in ascending order. (Optional) """ diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py index 81e8b1f38..c4941f256 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py @@ -81,7 +81,7 @@ def setup(self): "VLAM14", val=0.99124, units='unitless', - desc="VLAM14: mach number correction factor ", + desc="VLAM14: Mach number correction factor ", ) # other inputs @@ -154,7 +154,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=0.17522, units='unitless', - desc="SMN: mach number", + desc="SMN: Mach number", ) self.add_output( "reynolds", val=157.1111, units='unitless', desc="RNW: reynolds number" diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py index cdeead0e1..095b4a01f 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py @@ -85,7 +85,10 @@ def setup(self): "VLAM13", val=1.03512, units='unitless', desc="VLAM13: reynolds number correction factor" ) self.add_input( - "VLAM14", val=0.99124, units='unitless', desc="VLAM14: mach number correction factor " + "VLAM14", + val=0.99124, + units='unitless', + desc="VLAM14: Mach number correction factor ", ) # outputs 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 12b1d920a..e45bfecd6 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py @@ -794,7 +794,7 @@ def setup(self): 0.17522, training_data=[0.0, 0.2, 0.4, 0.6, 0.8, 1.0], units="unitless", - desc="mach number", + desc="Mach number", ) VLAM14_interp.add_output( @@ -802,7 +802,7 @@ def setup(self): 0.99124, training_data=[1.0, 0.99, 0.94, 0.87, 0.78, 0.66], units="unitless", - desc="mach number correction factor", + desc="Mach number correction factor", ref=100, ) diff --git a/aviary/subsystems/atmosphere/flight_conditions.py b/aviary/subsystems/atmosphere/flight_conditions.py index a83d535d5..180d41da9 100644 --- a/aviary/subsystems/atmosphere/flight_conditions.py +++ b/aviary/subsystems/atmosphere/flight_conditions.py @@ -18,7 +18,7 @@ def initialize(self): "input_speed_type", default=SpeedType.TAS, types=SpeedType, - desc="defines input airspeed as equivalent airspeed, true airspeed, or mach number", + desc="defines input airspeed as equivalent airspeed, true airspeed, or Mach number", ) def setup(self): @@ -63,7 +63,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.declare_partials( @@ -101,7 +101,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.declare_partials( @@ -131,7 +131,7 @@ def setup(self): Dynamic.Atmosphere.MACH, val=np.zeros(nn), units="unitless", - desc="mach number", + desc="Mach number", ) self.add_output( "EAS", diff --git a/aviary/subsystems/mass/gasp_based/design_load.py b/aviary/subsystems/mass/gasp_based/design_load.py index d88a41ea2..fabde2be2 100644 --- a/aviary/subsystems/mass/gasp_based/design_load.py +++ b/aviary/subsystems/mass/gasp_based/design_load.py @@ -377,7 +377,7 @@ def compute_partials(self, inputs, partials): class LoadParameters(om.ExplicitComponent): """ - Computation of load parameters (such as maximum operating mach number, + Computation of load parameters (such as maximum operating Mach number, density ratio, etc.) """ @@ -404,7 +404,10 @@ def setup(self): ) self.add_output( - "max_mach", val=0, units="unitless", desc="EMM0: maximum operating mach number" + "max_mach", + val=0, + units="unitless", + desc="EMM0: maximum operating Mach number", ) self.add_output( "density_ratio", @@ -650,7 +653,7 @@ def compute_partials(self, inputs, partials): class LiftCurveSlopeAtCruise(om.ExplicitComponent): """ - Computation of lift curve slope at cruise mach number + Computation of lift curve slope at cruise Mach number """ def setup(self): diff --git a/aviary/subsystems/mass/gasp_based/fixed.py b/aviary/subsystems/mass/gasp_based/fixed.py index 3f083f3b3..75b85f2d7 100644 --- a/aviary/subsystems/mass/gasp_based/fixed.py +++ b/aviary/subsystems/mass/gasp_based/fixed.py @@ -45,8 +45,10 @@ def setup(self): add_aviary_input(self, Aircraft.Wing.SPAN, val=117.8) self.add_input( - "max_mach", val=0.9, units="unitless", - desc="EMM0: maximum operating mach number" + "max_mach", + val=0.9, + units="unitless", + desc="EMM0: maximum operating Mach number", ) add_aviary_input( diff --git a/aviary/subsystems/propulsion/engine_deck.py b/aviary/subsystems/propulsion/engine_deck.py index 024d98a9d..9d391a536 100644 --- a/aviary/subsystems/propulsion/engine_deck.py +++ b/aviary/subsystems/propulsion/engine_deck.py @@ -1376,7 +1376,7 @@ def _hybrid_throttle_norm(hybrid_throttle_list): def _sort_data(self): """ - Sort unpacked engine data in order of mach number, altitude, throttle, + Sort unpacked engine data in order of Mach number, altitude, throttle, hybrid throttle. """ engine_data = self.data @@ -1448,10 +1448,10 @@ def _count_data(self): number. """ mach_count = 0 - # First mach number must have at least one altitude associated with it + # First Mach number must have at least one altitude associated with it alt_count = 1 max_alt_count = 0 - # First mach number must have at least one data point associated with it + # First Mach number must have at least one data point associated with it data_count = 1 max_data_count = 0 @@ -1478,7 +1478,7 @@ def _count_data(self): data_count += 1 else: - # new altitude for this mach number, count it + # new altitude for this Mach number, count it curr_alt = alt alt_count += 1 data_indices = extend_array(data_indices, [mach_count, alt_count]) @@ -1501,7 +1501,7 @@ def _count_data(self): f'<{self.get_val(Aircraft.Engine.DATA_FILE).name}>' ) - # record and count mach numbers + # record and count Mach numbers curr_mach = mach_num mach_count += 1 diff --git a/aviary/utils/engine_deck_conversion.py b/aviary/utils/engine_deck_conversion.py index 80d296103..540aa5b0a 100644 --- a/aviary/utils/engine_deck_conversion.py +++ b/aviary/utils/engine_deck_conversion.py @@ -469,7 +469,7 @@ def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow" # step size in t4/t2 ratio used in generating the structured grid # t2t2_step = 0.5 # original value t4t2_step = throttle_step - # step size in mach number used in generating the structured grid + # step size in Mach number used in generating the structured grid # mach_step = 0.02 # original value mach_step = 0.05 @@ -504,7 +504,7 @@ def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow" # would explicitly use lagrange3 here to mimic GASP, but some engine # decks may not have enough points per dimension # For GASP engine deck, try to provide at least 4 Mach numbers. - # For GASP_TP engine deck, try to provide at least 4 Mach numbers + # For GASP_TS engine deck, try to provide at least 4 Mach numbers # avoid devide-by-zero RuntimeWarning if len(mach) == 3 and method == "lagrange3": method = "lagrange2" diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index e2d2edaff..5fe248e6c 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -215,7 +215,7 @@ def values(cls): class OutMachType(Enum): ''' - OutMachType is an indicator which mach number to output. + OutMachType is an indicator which Mach number to output. helical_mach = sqrt(mach*mach + tip_mach*tip_mach) ''' MACH = 'mach' diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index d077c8cc2..33b271aac 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1355,7 +1355,7 @@ meta_data=_MetaData, historical_name={"GASP": 'INGASP.CLALPH', "FLOPS": None, "LEAPS1": None}, units="1/rad", - desc='lift curve slope at cruise mach number', + desc='lift curve slope at cruise Mach number', ) add_meta_data( @@ -6637,7 +6637,7 @@ ], }, units='unitless', - desc='aircraft cruise mach number', + desc='aircraft cruise Mach number', # TODO: derived default value: Mission.Summary.CRUISE_MACH ??? default_value=None, option=True, @@ -6972,7 +6972,7 @@ meta_data=_MetaData, historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, units="unitless", - desc='approach mach number', + desc='approach Mach number', default_value=0.1, ) @@ -7172,7 +7172,7 @@ ], }, units='unitless', - desc='aircraft cruise mach number', + desc='aircraft cruise Mach number', default_value=0.0, # TODO: required ) From a319a1545f34ba05838a4183511bf1482dbcd606 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Tue, 14 Jan 2025 14:36:00 -0500 Subject: [PATCH 27/30] add skip for OAS test if ambiance not installed --- .../OAS_weight/test_OAS_wing_weight_builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py b/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py index 302e85775..bfd91c663 100644 --- a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py +++ b/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py @@ -1,5 +1,6 @@ import unittest import aviary.api as av +import importlib.util path_to_builder = 'OAS_weight.OAS_wing_weight_builder.OASWingWeightBuilder' @@ -7,6 +8,9 @@ @av.skipIfMissingDependencies(OASWingWeightBuilder) +@unittest.skipUnless( + importlib.util.find_spec('ambiance'), "'ambiance' is not installed" +) class TestStructures(av.TestSubsystemBuilderBase): """Test OAS structure builder""" From 952e4999ccb72a161ee66f4658b265ee53d5f470 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Fri, 17 Jan 2025 14:32:48 -0500 Subject: [PATCH 28/30] minor cleanup --- aviary/subsystems/mass/flops_based/wing_detailed.py | 2 +- aviary/validation_cases/validation_tests.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/aviary/subsystems/mass/flops_based/wing_detailed.py b/aviary/subsystems/mass/flops_based/wing_detailed.py index 65d01b9f9..f645f812a 100644 --- a/aviary/subsystems/mass/flops_based/wing_detailed.py +++ b/aviary/subsystems/mass/flops_based/wing_detailed.py @@ -275,7 +275,7 @@ def compute(self, inputs, outputs): inertia_factor_i = 1 - bte / bt * pod_mass[i] / gross_mass # avoid passing an array into specific index of inertia_factor - inertia_factor[i] = inertia_factor_i[0] + inertia_factor[i] = inertia_factor_i # increment idx to next engine set idx = idx2 diff --git a/aviary/validation_cases/validation_tests.py b/aviary/validation_cases/validation_tests.py index b0cc69fd2..045decaea 100644 --- a/aviary/validation_cases/validation_tests.py +++ b/aviary/validation_cases/validation_tests.py @@ -110,7 +110,6 @@ def do_validation_test(prob: om.Problem, prob.set_val(key, desired, units) prob.run_model() - print(case_name) if list_options: list_options_func(prob.model, aviary_keys=aviary_option_key_list) From d8ccd5d91f104c07c5fad2c868b75e313cca3b31 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Wed, 22 Jan 2025 18:21:16 -0500 Subject: [PATCH 29/30] CI fixes Addressed review comments --- aviary/docs/getting_started/onboarding_level1.ipynb | 2 +- aviary/subsystems/mass/gasp_based/test/test_fixed.py | 2 +- aviary/utils/preprocessors.py | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/aviary/docs/getting_started/onboarding_level1.ipynb b/aviary/docs/getting_started/onboarding_level1.ipynb index e3cc295a4..0c4bf8601 100644 --- a/aviary/docs/getting_started/onboarding_level1.ipynb +++ b/aviary/docs/getting_started/onboarding_level1.ipynb @@ -223,7 +223,7 @@ "\n", "To find information about a variable (e.g. description, data type, etc.), users should read the [Variable Metadata Doc](../user_guide/variable_metadata).\n", "\n", - "Variable names may be differently within the code from how they are formatted inside OpenMDAO components and in input files and outputs. For example, variable `aircraft:wing:aspect_ratio` in `aircraft_for_bench_GwGm.csv` is mapped to `Aircraft.Wing.ASPECT_RATIO` in `aviary/variable_info/variable_meta_data.py`. This is because OpenMDAO requires variable names to be strings, but for developer convenience those strings are mapped to Python classes and attributes. The top-level and sub-categories have capitalized first letters, and the final variable name is always in all-caps. For more information on Aviary's variable hierarchy, see the [Variable Hierarchy doc](../user_guide/variable_hierarchy.ipynb).\n", + "Variable names may appear differently within the code from how they are formatted inside OpenMDAO components and in input files and outputs. For example, variable `aircraft:wing:aspect_ratio` in `aircraft_for_bench_GwGm.csv` is mapped to `Aircraft.Wing.ASPECT_RATIO` in `aviary/variable_info/variable_meta_data.py`. This is because OpenMDAO requires variable names to be strings, but for developer convenience those strings are mapped to Python classes and attributes. The top-level and sub-categories have capitalized first letters, and the final variable name is always in all-caps. For more information on Aviary's variable hierarchy, see the [Variable Hierarchy doc](../user_guide/variable_hierarchy.ipynb).\n", "\n", "Aviary variables that are not defined in the `.csv` input file are set to their default values, as described in the variable metadata." ] diff --git a/aviary/subsystems/mass/gasp_based/test/test_fixed.py b/aviary/subsystems/mass/gasp_based/test/test_fixed.py index 36bc36ffa..e3152d175 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_fixed.py +++ b/aviary/subsystems/mass/gasp_based/test/test_fixed.py @@ -642,7 +642,7 @@ def test_case_1(self): ) # bug fixed value and original value partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TailTestCase(unittest.TestCase): # this is the large single aisle 1 V3 test case diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index 93b380f7c..db6e0941d 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -359,8 +359,10 @@ def preprocess_propulsion( # update aviary options and outputs with new vectors # if data is numerical, store in a numpy array # keep tuples as tuples, lists get converted to numpy arrays - if type(vec[0]) in (int, float, np.int64, np.float64)\ - and type(vec) is not tuple: + if ( + type(vec[0]) in (int, float, np.int32, np.int64, np.float32, np.float64) + and type(vec) is not tuple + ): vec = np.array(vec, dtype=dtype) aviary_options.set_val(var, vec, units) From 129ea201b1e95338e22107c2cdf385c3add5cc20 Mon Sep 17 00:00:00 2001 From: jkirk5 Date: Wed, 22 Jan 2025 18:39:08 -0500 Subject: [PATCH 30/30] removed docs artifact file (it should be generated while building the docs) --- aviary/docs/examples/outputted_phase_info.py | 21 -------------------- 1 file changed, 21 deletions(-) delete mode 100644 aviary/docs/examples/outputted_phase_info.py diff --git a/aviary/docs/examples/outputted_phase_info.py b/aviary/docs/examples/outputted_phase_info.py deleted file mode 100644 index 0737bef2c..000000000 --- a/aviary/docs/examples/outputted_phase_info.py +++ /dev/null @@ -1,21 +0,0 @@ -phase_info = { - 'pre_mission': { - 'include_takeoff': True, 'optimize_mass': True}, 'climb_1': { - 'subsystem_options': { - 'core_aerodynamics': { - 'method': 'computed'}}, 'user_options': { - 'optimize_mach': True, 'optimize_altitude': True, 'polynomial_control_order': [ - 1, 2], 'use_polynomial_control': True, 'num_segments': [1], 'order': 1, 'solve_for_distance': True, 'initial_mach': ( - 1, None), 'final_mach': ( - 2, None), 'mach_bounds': ( - (0.98, 2.02), None), 'initial_altitude': ( - 1, None), 'final_altitude': ( - 2, None), 'altitude_bounds': ( - (0.0, 502), None), 'throttle_enforcement': 'path_constraint', 'fix_initial': True, 'constrain_final': True, 'fix_duration': False, 'initial_bounds': ( - (0.0, 0.0), None), 'duration_bounds': ( - (0.5, 1.5), None)}, 'initial_guesses': { - 'time': ( - [ - 1, 1], None)}}, 'post_mission': { - 'include_landing': True, 'constrain_range': True, 'target_range': ( - 514.5, None)}}