Skip to content

Commit

Permalink
Merge branch 'main' into shooting_reserve
Browse files Browse the repository at this point in the history
  • Loading branch information
crecine authored Apr 22, 2024
2 parents eaf9164 + c34fa6e commit 59d7e39
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 16 deletions.
90 changes: 90 additions & 0 deletions aviary/docs/user_guide/aviary_commands.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,96 @@
"source": [
"!aviary hangar -h"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(aviary-EDC-command)=\n",
"### aviary convert_engine\n",
"\n",
"The `aviary convert_engine` command will convert a legacy formatted (FLOPS or GASP) engine deck into an Aviary formatted engine deck.\n",
"\n",
"Users must provide the path or name of an input deck, the path to the output file, and the engine format being converted.\n",
"If an invalid filepath is given for the input file, pre-packaged resources will be checked for input decks with a matching name.\n",
"\n",
"Notes for input decks:\n",
"- TurboFan decks for both FLOPS and GASP can be converted\n",
"- TurboProp decks for GASP can also be converted\n",
"- Comments can be added using #\n",
"\n",
"\n",
"Example usage:\n",
"```\n",
"`aviary convert_engine GASP_turbofan_23k_1.eng turbofan_23k_1_lbm_s.deck GASP` Convert a GASP based turbofan\n",
"`aviary convert_engine turbofan_22k.eng turbofan_22k.txt FLOPS` Convert a FLOPS based turbofan\n",
"`aviary convert_engine turboprop_4465hp.eng turboprop_4465hp.deck GASP_TP` Convert a GASP based turboprop\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"aviary convert_engine -h\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!aviary convert_engine -h"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(aviary-ATC-command)=\n",
"### aviary convert_aero_table\n",
"\n",
"The `aviary convert_aero_table` command will convert a legacy formatted (FLOPS or GASP) aero table into an Aviary formatted aero table.\n",
"\n",
"Users must provide the path or name of an input deck and the data format being converted.\n",
"Optionally, the path to the output file can also be specified, otherwise the default output file will be in the same location and have the same name as input file, but with '_aviary' appended to filename.\n",
"If an invalid filepath is given for the input file, pre-packaged resources will be checked for input decks with a matching name.\n",
"\n",
"Notes for input decks:\n",
"- Aero tables for both FLOPS and GASP can be converted\n",
"- GASP tables will create a single file containing all the lift and drag information\n",
"- FLOPS tables will create two files, one containing the lift-dependent drag and the other containing the lift-independent drag.\n",
"- Comments can be added using #\n",
"\n",
"\n",
"Example usage:\n",
"```\n",
"`aviary convert_engine GASP_turbofan_23k_1.eng turbofan_23k_1_lbm_s.deck GASP` Convert a GASP based turbofan\n",
"`aviary convert_engine turbofan_22k.eng turbofan_22k.txt FLOPS` Convert a FLOPS based turbofan\n",
"`aviary convert_engine turboprop_4465hp.eng turboprop_4465hp.deck GASP_TP` Convert a GASP based turboprop\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"aviary convert_aero_table -h\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!aviary convert_aero_table -h"
]
}
],
"metadata": {
Expand Down
3 changes: 3 additions & 0 deletions aviary/interface/cmd_entry_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from aviary.interface.methods_for_level1 import _exec_level1, _setup_level1_parser
from aviary.utils.fortran_to_aviary import _exec_F2A, _setup_F2A_parser
from aviary.utils.engine_deck_conversion import _exec_EDC, _setup_EDC_parser, EDC_description
from aviary.utils.aero_table_conversion import _exec_ATC, _setup_ATC_parser
from aviary.visualization.dashboard import _dashboard_setup_parser, _dashboard_cmd
from aviary.interface.graphical_input import _exec_flight_profile, _setup_flight_profile_parser
from aviary.interface.download_models import _exec_hangar, _setup_hangar_parser
Expand Down Expand Up @@ -52,6 +53,8 @@ def _load_and_exec(script_name, user_args):
'hangar': (_setup_hangar_parser, _exec_hangar,
"Allows users that pip installed Aviary to download models from the Aviary hangar"),
'convert_engine': (_setup_EDC_parser, _exec_EDC, EDC_description),
'convert_aero_table': (_setup_ATC_parser, _exec_ATC,
'Converts FLOPS- or GASP-formatted aero data files into Aviary csv format.'),
}


Expand Down
25 changes: 25 additions & 0 deletions aviary/interface/methods_for_level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,8 +1065,33 @@ def add_phases(self, phase_info_parameterization=None):
(phases['climb3']['ode'], Dynamic.Mission.ALTITUDE, 0,),
(phases['cruise']['ode'], Dynamic.Mission.MASS, 0,),
],
traj_intermediate_state_output=[
('cruise', Dynamic.Mission.DISTANCE),
('cruise', Dynamic.Mission.MASS),
]
)
traj = self.model.add_subsystem('traj', full_traj)

self.model.add_subsystem(
'actual_descent_fuel',
om.ExecComp('actual_descent_fuel = traj_cruise_mass_final - traj_mass_final',
actual_descent_fuel={'units': 'lbm'},
traj_cruise_mass_final={'units': 'lbm'},
traj_mass_final={'units': 'lbm'},
))

self.model.connect(
'traj.mass_final',
'actual_descent_fuel.traj_mass_final',
src_indices=[-1],
flat_src_indices=True,
)
self.model.connect(
'traj.cruise_mass_final',
'actual_descent_fuel.traj_cruise_mass_final',
src_indices=[-1],
flat_src_indices=True,
)
return traj

def add_subsystem_timeseries_outputs(phase, phase_name):
Expand Down
52 changes: 48 additions & 4 deletions aviary/mission/gasp_based/ode/time_integration_base_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ def setup_params(
traj_promote_initial_input=None,
traj_initial_state_input=None,
traj_event_trigger_input=None,
traj_intermediate_state_output=None,
# traj_promote_intermediate_output=None,
):
"""
API requirements:
Expand All @@ -463,17 +465,23 @@ def setup_params(
declare initial state(s) as parameters to take derivative wrt
assume all other inputs are parameters for deriv?
"""
if traj_final_state_output is None:
traj_final_state_output = []
if traj_promote_final_output is None:
traj_promote_final_output = []
if traj_promote_initial_input is None:
traj_promote_initial_input = {}
if traj_initial_state_input is None:
traj_initial_state_input = []
# if traj_promote_intermediate_output is None:
# traj_promote_intermediate_output = []
if traj_intermediate_state_output is None:
traj_intermediate_state_output = []
if traj_final_state_output is None:
traj_final_state_output = []
if traj_promote_final_output is None:
traj_promote_final_output = []
if traj_event_trigger_input is None:
traj_event_trigger_input = []

self.phase_names = [ode.phase_name for ode in ODEs]

if promote_all_auto_ivc:
for ode in ODEs:
ode: SimuPyProblem
Expand Down Expand Up @@ -504,6 +512,20 @@ def setup_params(
}
for final_state_output in traj_final_state_output
}
self.traj_intermediate_state_output = {
phase_name+'_'+intermediate_state_output+final_suffix: {
**dict(
phase_name=phase_name,
state_name=intermediate_state_output,
),
**self.add_output(
phase_name+'_'+intermediate_state_output+final_suffix,
units=ODEs[self.phase_names.index(
phase_name)].states[intermediate_state_output]['units'],
)
}
for phase_name, intermediate_state_output in traj_intermediate_state_output
}
self.traj_promote_final_output = {
promoted_final_output: {
**dict(
Expand All @@ -517,8 +539,23 @@ def setup_params(
}
for promoted_final_output in traj_promote_final_output
}
# self.traj_promote_intermediate_output = {
# promoted_intermediate_output: {
# **dict(
# name=phase_name+'_'+promoted_intermediate_output+final_suffix,
# output_name=promoted_intermediate_output,
# ),
# **self.add_output(
# phase_name+'_'+promoted_intermediate_output,
# units=ODEs[-1].outputs[promoted_intermediate_output],
# ),
# }
# for phase_name,promoted_intermediate_output in traj_promote_intermediate_output
# }
self.all_traj_outputs = {
**self.traj_intermediate_state_output,
**self.traj_final_state_output,
# **self.traj_promote_intermediate_output,
**self.traj_promote_final_output,
}
initial_suffix = "_initial"
Expand Down Expand Up @@ -600,6 +637,13 @@ def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None):
t = sim_result.t[-1]
x = sim_result.x[-1, :]

for output_name, output in self.traj_intermediate_state_output.items():
if output['phase_name'] == current_problem.phase_name:
outputs[output_name] = sim_result.x[
-1,
current_problem.state_names.index(output["state_name"])
]

# TODO: is there a better way to do this? Perhaps don't use for loop -- use
# while True ?Ij
try:
Expand Down
2 changes: 2 additions & 0 deletions aviary/mission/gasp_based/phases/time_integration_traj.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def initialize(self):
super().initialize()
self.options.declare('Phases', default=None)
self.options.declare('promote_all_auto_ivc', default=False)
self.options.declare('traj_intermediate_state_output', default=None)
self.options.declare('traj_final_state_output', default=None)
self.options.declare('traj_promote_final_output', default=None)
self.options.declare('traj_promote_initial_input', default=None)
Expand All @@ -47,6 +48,7 @@ def setup(self):
traj_promote_initial_input=self.options['traj_promote_initial_input'],
traj_initial_state_input=self.options['traj_initial_state_input'],
traj_event_trigger_input=self.options['traj_event_trigger_input'],
traj_intermediate_state_output=self.options['traj_intermediate_state_output'],
)
self.declare_partials(["*"], ["*"],)

Expand Down
16 changes: 11 additions & 5 deletions aviary/utils/aero_table_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,22 @@ def _load_gasp_aero_table(filepath: Path):
return data, comments


if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Converts FLOPS- or GASP-formatted '
'aero data files into Aviary csv format.\n')
def _setup_ATC_parser(parser):
parser.add_argument('input_file', type=str,
help='path to engine deck file to be converted')
help='path to aero data file to be converted')
parser.add_argument('output_file', type=str,
help='path to file where new converted data will be written')
parser.add_argument('data_format', type=str, choices=[origin.value for origin in CodeOrigin],
help='data format used by input_file')

args = parser.parse_args()

def _exec_ATC(args, user_args):
AeroDataConverter(**vars(args))


if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Converts FLOPS- or GASP-formatted '
'aero data files into Aviary csv format.\n')
_setup_ATC_parser(parser)
args = parser.parse_args()
_exec_ATC(args, None)
2 changes: 0 additions & 2 deletions aviary/utils/engine_deck_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType):
path to file where new converted data will be written
data_format : (EngineDeckType)
data format used by input_file (FLOPS or GASP)
readable : (bool)
output_file will be organized with consistent column widths for easier reading
'''
# TODO rounding for calculated values?

Expand Down
5 changes: 4 additions & 1 deletion aviary/validation_cases/benchmark_tests/test_bench_GwGm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from aviary.interface.default_phase_info.two_dof import phase_info
from aviary.interface.methods_for_level1 import run_aviary
from aviary.variable_info.variables import Aircraft, Mission
from aviary.variable_info.variables import Aircraft, Mission, Dynamic
from aviary.variable_info.enums import AnalysisScheme, Verbosity


Expand Down Expand Up @@ -128,6 +128,9 @@ def test_bench_GwGm_shooting(self):
assert_near_equal(prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'),
136823.47, tolerance=rtol)

assert_near_equal(prob.get_val('traj.cruise_' + Dynamic.Mission.DISTANCE + '_final',
units='nmi'), 3668.3, tolerance=rtol)


if __name__ == '__main__':
# unittest.main()
Expand Down
Loading

0 comments on commit 59d7e39

Please sign in to comment.