Skip to content

Commit

Permalink
Merge pull request #567 from xjjiang/geodetic
Browse files Browse the repository at this point in the history
Change atmosphere comp defaults from geopotential to Geodetic
  • Loading branch information
jkirk5 authored Oct 16, 2024
2 parents 2652e69 + a3844bb commit dc2eead
Show file tree
Hide file tree
Showing 45 changed files with 1,307 additions and 373 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
uses: ./actions/.github/actions/prepare_environment
with:
NAME: 'latest'
PY: 3
PY: 3.12
NUMPY: 1
SCIPY: 1
PYOPTSPARSE: 'v2.9.1'
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/test_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
# Allow running the workflow manually from the Actions tab
workflow_dispatch:


jobs:

latest_docs:
Expand All @@ -28,31 +28,31 @@ jobs:
sparse-checkout: |
.github/actions
path: actions

- name: prepare_docs_environment
uses: ./actions/.github/actions/prepare_environment
with:
NAME: 'latest'
PY: 3
PY: 3.12
NUMPY: 1
SCIPY: 1
PYOPTSPARSE: 'v2.9.1'
SNOPT: '7.7'
#OPENMDAO: 'latest'
OPENMDAO: '3.34.2'
DYMOS: 'latest'
DYMOS: 'latest'
SSH_PRIVATE_KEY: ${{secrets.SSH_PRIVATE_KEY}}
SSH_KNOWN_HOSTS: ${{secrets.SSH_KNOWN_HOSTS}}
SNOPT_LOCATION_77: ${{ secrets.SNOPT_LOCATION_77 }}

- name: Check docs linting
shell: bash -l {0}
run: |
echo "============================================================="
echo "Lint the docs"
echo "============================================================="
python aviary/docs/tests/check_jupyter_output_linting.py
- name: Build docs
id: build_docs
shell: bash -l {0}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_workflow_dev_deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
# latest released version of pyoptsparse
# development versions of openmdao/dymos
- NAME: dev
PY: 3
PY: 3.12
NUMPY: 1
SCIPY: 1
PYOPTSPARSE: 'latest'
Expand Down
2 changes: 1 addition & 1 deletion aviary/docs/developer_guide/codebase_overview.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
" 'interface':'is where most code that users interact with is located',\n",
" 'mission':'contains OpenMDAO components and groups for modeling the aircraft mission',\n",
" 'models':'contains aircraft and propulsion models for use in Aviary examples and tests',\n",
" 'subsystems':'is where the aerodynamic, propulsion, mass, and geometry core subsystems are located',\n",
" 'subsystems':'is where the aerodynamic, atmosphere, energy, propulsion, mass, and geometry core subsystems are located',\n",
" 'utils':'contains utility functions for use in Aviary code, examples, and tests',\n",
" 'validation_cases':'contains validation cases for testing and benchmarking Aviary',\n",
" 'variable_info':'contains the variable meta data as well as several variable classes that are used in Aviary',\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@
"aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n",
"optimizer = \"IPOPT\"\n",
"make_plots = True\n",
"max_iter = 200\n",
"max_iter = 100\n",
"\n",
"prob = av.run_aviary(aircraft_filename, phase_info, optimizer=optimizer,\n",
" make_plots=make_plots, max_iter=max_iter)"
Expand Down
74 changes: 38 additions & 36 deletions aviary/interface/methods_for_level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def configure(self):
# Find promoted name of every input in the model.
all_prom_inputs = []

# We can call list_inputs on the groups.
for system in self.system_iter(recurse=False, typ=om.Group):
# We can call list_inputs on the subsystems.
for system in self.system_iter(recurse=False):
var_abs = system.list_inputs(out_stream=None, val=False)
var_prom = [v['prom_name'] for k, v in var_abs]
all_prom_inputs.extend(var_prom)
Expand Down Expand Up @@ -662,6 +662,7 @@ def _add_two_dof_takeoff_systems(self):
cruise_mach=self.cruise_mach,
cruise_alt=self.cruise_alt,
reserve_fuel='reserve_fuel_estimate',
all_subsystems=self._get_all_subsystems(),
)

# Add thrust-to-weight ratio subsystem
Expand Down Expand Up @@ -1099,6 +1100,7 @@ def add_phases(self, phase_info_parameterization=None):
src_indices=[-1],
flat_src_indices=True,
)
self.traj = full_traj
return traj

def add_subsystem_timeseries_outputs(phase, phase_name):
Expand Down Expand Up @@ -1947,59 +1949,53 @@ def _add_bus_variables_and_connect(self):
for external_subsystem in all_subsystems:
bus_variables = external_subsystem.get_bus_variables()
if bus_variables is not None:
for bus_variable in bus_variables:
mission_variable_name = bus_variables[bus_variable]['mission_name']
for bus_variable, variable_data in bus_variables.items():
mission_variable_name = variable_data['mission_name']

# check if mission_variable_name is a list
if not isinstance(mission_variable_name, list):
mission_variable_name = [mission_variable_name]

# loop over the mission_variable_name list and add each variable to the trajectory
for mission_var_name in mission_variable_name:
if 'mission_name' in bus_variables[bus_variable]:
if mission_var_name not in self.meta_data:
# base_units = self.model.get_io_metadata(includes=f'pre_mission.{external_subsystem.name}.{bus_variable}')[f'pre_mission.{external_subsystem.name}.{bus_variable}']['units']
base_units = bus_variables[bus_variable]['units']
if mission_var_name not in self.meta_data:
# base_units = self.model.get_io_metadata(includes=f'pre_mission.{external_subsystem.name}.{bus_variable}')[f'pre_mission.{external_subsystem.name}.{bus_variable}']['units']
base_units = variable_data['units']

shape = bus_variables[bus_variable].get(
'shape', _unspecified)
shape = variable_data.get('shape', _unspecified)

targets = mission_var_name
if '.' in mission_var_name:
# Support for non-hierarchy variables as parameters.
mission_var_name = mission_var_name.split('.')[-1]
targets = mission_var_name
if '.' in mission_var_name:
# Support for non-hierarchy variables as parameters.
mission_var_name = mission_var_name.split('.')[-1]

if 'phases' in bus_variables[bus_variable]:
# Support for connecting bus variables into a subset of
# phases.
phases = bus_variables[bus_variable]['phases']
if 'phases' in variable_data:
# Support for connecting bus variables into a subset of
# phases.
for phase_name in variable_data['phases']:
phase = getattr(self.traj.phases, phase_name)

for phase_name in phases:
phase = getattr(self.traj.phases, phase_name)
phase.add_parameter(mission_var_name, opt=False, static_target=True,
units=base_units, shape=shape, targets=targets)

phase.add_parameter(mission_var_name, opt=False, static_target=True,
units=base_units, shape=shape, targets=targets)
self.model.connect(f'pre_mission.{bus_variable}',
f'traj.{phase_name}.parameters:{mission_var_name}')

self.model.connect(f'pre_mission.{bus_variable}',
f'traj.{phase_name}.parameters:{mission_var_name}')
else:
self.traj.add_parameter(mission_var_name, opt=False, static_target=True,
units=base_units, shape=shape, targets={
phase_name: [mission_var_name] for phase_name in base_phases})

else:
phases = base_phases
self.model.connect(
f'pre_mission.{bus_variable}', f'traj.parameters:'+mission_var_name)

self.traj.add_parameter(mission_var_name, opt=False, static_target=True,
units=base_units, shape=shape, targets={
phase_name: [mission_var_name] for phase_name in phases})

self.model.connect(
f'pre_mission.{bus_variable}', f'traj.parameters:'+mission_var_name)

if 'post_mission_name' in bus_variables[bus_variable]:
if 'post_mission_name' in variable_data:
self.model.connect(f'pre_mission.{external_subsystem.name}.{bus_variable}',
f'post_mission.{external_subsystem.name}.{bus_variables[bus_variable]["post_mission_name"]}')
f'post_mission.{external_subsystem.name}.{variable_data["post_mission_name"]}')

def setup(self, **kwargs):
"""
Lightly wrappd setup() method for the problem.
Lightly wrapped setup() method for the problem.
"""
# suppress warnings:
# "input variable '...' promoted using '*' was already promoted using 'aircraft:*'
Expand Down Expand Up @@ -2701,6 +2697,12 @@ def _add_two_dof_landing_systems(self):
(Dynamic.Vehicle.MASS, Mission.Landing.TOUCHDOWN_MASS)],
promotes_outputs=['mission:*'],
)
self.model.connect(
'pre_mission.interference_independent_of_shielded_area',
'landing.interference_independent_of_shielded_area')
self.model.connect(
'pre_mission.drag_loss_due_to_shielded_wing_area',
'landing.drag_loss_due_to_shielded_wing_area')

def _add_objectives(self):
self.model.add_subsystem(
Expand Down
17 changes: 16 additions & 1 deletion aviary/mission/gasp_based/idle_descent_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def add_descent_estimation_as_submodel(
cruise_alt=None,
cruise_mach=None,
reserve_fuel=None,
all_subsystems=None,
verbosity=Verbosity.QUIET,
):
"""
Expand All @@ -26,6 +27,9 @@ def add_descent_estimation_as_submodel(
descent_phases as phases, add_default_sgm_args
add_default_sgm_args(phases, ode_args)

if all_subsystems is None:
all_subsystems = []

traj = FlexibleTraj(
Phases=phases,
traj_initial_state_input=[
Expand Down Expand Up @@ -74,9 +78,20 @@ def add_descent_estimation_as_submodel(
promotes_outputs=['mass_initial']
)

all_bus_vars = set()
for subsystem in all_subsystems:
bus_vars = subsystem.get_bus_variables()
for var, data in bus_vars.items():
mission_variable_name = data['mission_name']
if not isinstance(mission_variable_name, list):
mission_variable_name = [mission_variable_name]
for mission_var_name in mission_variable_name:
all_bus_vars.add(mission_var_name)

model.add_subsystem(
'descent_traj', traj,
promotes_inputs=['altitude_initial', 'mass_initial', 'aircraft:*'],
promotes_inputs=['altitude_initial', 'mass_initial', 'aircraft:*'] +
[(var, 'parameters:'+var) for var in all_bus_vars],
promotes_outputs=['mass_final', 'distance_final'],
)

Expand Down
4 changes: 0 additions & 4 deletions aviary/mission/gasp_based/ode/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,9 @@ def promote_params(sys, trajs=None, phases=None):
Aircraft.Wing.MOUNTING_TYPE: dict(units="unitless", val=0),
Aircraft.Design.STATIC_MARGIN: dict(units="unitless", val=0.03),
Aircraft.Design.CG_DELTA: dict(units="unitless", val=0.25),
Aircraft.Wing.FORM_FACTOR: dict(units="unitless", val=1.25),
Aircraft.Fuselage.FORM_FACTOR: dict(units="unitless", val=1.25),
Aircraft.Nacelle.FORM_FACTOR: dict(units="unitless", val=1.5),
Aircraft.VerticalTail.FORM_FACTOR: dict(units="unitless", val=1.25),
Aircraft.HorizontalTail.FORM_FACTOR: dict(units="unitless", val=1.25),
Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=1.1),
Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=0),
Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units="unitless", val=0.00175),
Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT: dict(units="ft**2", val=0.25),
Aircraft.Wing.CENTER_DISTANCE: dict(units="unitless", val=0.463),
Expand Down
2 changes: 2 additions & 0 deletions aviary/mission/gasp_based/ode/test/test_ascent_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def test_ascent_partials(self):

self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn")
self.prob.set_val("t_curr", [1, 2], units="s")
self.prob.set_val("interference_independent_of_shielded_area", 1.89927266)
self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834)

set_params_for_unit_tests(self.prob)

Expand Down
10 changes: 6 additions & 4 deletions aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def test_cruise(self):
self.prob.setup(check=False, force_alloc_complex=True)

self.prob.set_val(Dynamic.Atmosphere.MACH, [0.7, 0.7], units="unitless")
self.prob.set_val("interference_independent_of_shielded_area", 1.89927266)
self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834)

set_params_for_unit_tests(self.prob)

Expand All @@ -45,18 +47,18 @@ def test_cruise(self):
)
assert_near_equal(
self.prob[Dynamic.Mission.DISTANCE], np.array(
[0.0, 881.8116]), tol)
[0.0, 882.5769]), tol)
assert_near_equal(
self.prob["time"], np.array(
[0, 7906.83]), tol)
[0, 7913.69]), tol)
assert_near_equal(
self.prob[Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS],
np.array([3.429719, 4.433518]),
np.array([3.439203, 4.440962]),
tol,
)
assert_near_equal(
self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX],
np.array([-17.63194, -16.62814]),
np.array([-17.622456, -16.62070]),
tol,
)

Expand Down
31 changes: 19 additions & 12 deletions aviary/mission/gasp_based/ode/test/test_climb_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from aviary.subsystems.propulsion.utils import build_engine_deck
from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems
from aviary.utils.test_utils.IO_test_util import check_prob_outputs
from aviary.variable_info.enums import Verbosity
from aviary.variable_info.options import get_option_defaults
from aviary.variable_info.variables import Aircraft, Dynamic

Expand All @@ -22,6 +23,7 @@ def setUp(self):
self.prob = om.Problem()

aviary_options = get_option_defaults()
aviary_options.set_val('verbosity', Verbosity.BRIEF)
default_mission_subsystems = get_default_mission_subsystems(
'GASP', build_engine_deck(aviary_options))

Expand All @@ -47,6 +49,8 @@ def test_start_of_climb(self):
self.prob.set_val("EAS", 250, units="kn")
# slightly greater than zero to help check partials
self.prob.set_val(Aircraft.Wing.INCIDENCE, 0.0000001, units="deg")
self.prob.set_val("interference_independent_of_shielded_area", 1.89927266)
self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834)

set_params_for_unit_tests(self.prob)

Expand All @@ -56,11 +60,12 @@ def test_start_of_climb(self):
"alpha": 5.16398,
"CL": 0.59766664,
"CD": 0.03070836,
Dynamic.Mission.ALTITUDE_RATE: 3414.63 / 60, # ft/s
# TAS (kts -> ft/s) * cos(gamma), 253.6827 * 1.68781 * cos(0.13331060446181708)
Dynamic.Mission.ALTITUDE_RATE: 3414.624 / 60, # ft/s
# TAS (kts -> ft/s) * cos(gamma), 253.6827 * 1.68781 *
# cos(0.13331060446181708)
Dynamic.Mission.DISTANCE_RATE: 424.36918705874785, # ft/s
Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -13448.29, # lbm/h
"theta": 0.22343879616956605, # rad (12.8021 deg)
"theta": 0.22343906, # rad (12.8021 deg)
Dynamic.Mission.FLIGHT_PATH_ANGLE: 0.13331060446181708, # rad (7.638135 deg)
}
check_prob_outputs(self.prob, testvals, rtol=1e-6)
Expand All @@ -87,25 +92,27 @@ def test_end_of_climb(self):
)
self.prob.set_val(Dynamic.Vehicle.MASS, np.array([174149, 171592]), units="lbm")
self.prob.set_val("EAS", np.array([270, 270]), units="kn")
self.prob.set_val("interference_independent_of_shielded_area", 1.89927266)
self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834)

set_params_for_unit_tests(self.prob)

self.prob.run_model()

testvals = {
"alpha": [4.05559, 4.08245],
"CL": [0.512629, 0.617725],
"CD": [0.02692764, 0.03311237],
Dynamic.Mission.ALTITUDE_RATE: [3053.754 / 60, 429.665 / 60], # ft/s
"alpha": [4.0557, 4.06615],
"CL": [0.512628, 0.615819],
"CD": [0.02692759, 0.03299578],
Dynamic.Mission.ALTITUDE_RATE: [3053.64 / 60, 430.746 / 60], # ft/s
# TAS (kts -> ft/s) * cos(gamma), [319, 459] kts
Dynamic.Mission.DISTANCE_RATE: [536.2835, 774.4118], # ft/s
Dynamic.Mission.DISTANCE_RATE: [536.23446, 774.40085], # ft/s
Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: [
-11420.05,
-11419.94,
-6050.26,
],
"theta": [0.16540479, 0.08049912], # rad ([9.47699, 4.61226] deg),
Dynamic.Mission.FLIGHT_PATH_ANGLE: [0.09462135, 0.00924686], # rad, gamma
Dynamic.Vehicle.Propulsion.THRUST_TOTAL: [25560.51, 10784.25],
"theta": [0.16541191, 0.08023799], # rad ([9.47740, 4.59730] deg),
Dynamic.Mission.FLIGHT_PATH_ANGLE: [0.09462652, 0.00927027], # rad, gamma
Dynamic.Vehicle.Propulsion.THRUST_TOTAL: [25561.393, 10784.245],
}
check_prob_outputs(self.prob, testvals, 1e-6)

Expand Down
Loading

0 comments on commit dc2eead

Please sign in to comment.