Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Implementation of Height Energy in SGM #97

Merged
merged 45 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d4fd2ac
Initial commit for Height Energy SGM phase
crecine Nov 30, 2023
ca34560
moved empty execcomp into a function to be shared amongst ODEs
crecine Dec 1, 2023
a7c18fc
Converted takeoff and landing ODEs to be compatible with SGM
crecine Dec 5, 2023
27d6c12
Updated variable pass through from outer problem to SimuPy problem Ad…
crecine Dec 6, 2023
f3b8fcd
temp for debugging
crecine Dec 6, 2023
7d3b46e
temp commit for debugging
crecine Dec 8, 2023
2c4701f
Reduced usage of blocked_state_names by specifying states in more phases
crecine Dec 29, 2023
2285655
Added ability to auto-promote all auto_ivs variables
crecine Dec 29, 2023
5fc9c65
Added debug prints
crecine Dec 29, 2023
4676eab
added more prints
crecine Dec 29, 2023
6a6f5a6
Remove debug prints
crecine Dec 29, 2023
0e6f3fc
Added SGM phases for detailed takeoff and landing
crecine Jan 11, 2024
27490e8
Merge branch 'main' into flops_sgm
crecine Jan 17, 2024
7349550
Switched from mission_ODE to simple_mission_ODE
crecine Jan 17, 2024
f4c7017
Converting simple_mission to SGM
crecine Jan 18, 2024
c53993d
Merge branch 'sgm-update' into flops_sgm
crecine Jan 23, 2024
218e803
prepared for testing detailed takeoff and landing
crecine Jan 24, 2024
f5fff48
Merge branch 'main' into flops_sgm
crecine Jan 24, 2024
c999f70
Merge branch 'main' into flops_sgm
johnjasa Jan 25, 2024
f8596a1
Merge branch 'main' into flops_sgm
crecine Jan 31, 2024
f2fb553
cleaned up comments and removed unused values
crecine Jan 31, 2024
62c1d20
Adding flexible triggers and removing unused trajectories
crecine Feb 5, 2024
a9e8b68
Using flexible triggers
crecine Feb 6, 2024
28f9a78
fixed missing squeeze
crecine Feb 6, 2024
abd6143
Merge branch 'main' into flops_sgm
crecine Feb 6, 2024
52ea87e
fixing units and type hint
crecine Feb 6, 2024
abd99f7
Merge branch 'main' into flops_sgm
crecine Feb 7, 2024
6042876
Added some temporary debugging statements and tweaked triggers
crecine Feb 8, 2024
8335270
added debug environment files to gitignore
crecine Feb 10, 2024
33c0e8b
fixed typo
crecine Feb 12, 2024
35bc9dd
adding phase names to ascent subphases and adding states to phases
crecine Feb 14, 2024
edec537
restoring descent estimation
crecine Feb 14, 2024
546f1fa
reverted temporary debugging
crecine Feb 14, 2024
104f765
Merge branch 'main' into flops_sgm
crecine Feb 14, 2024
3ec4f9b
updated debug to verbosity
crecine Feb 14, 2024
0856940
added a bench test for SGM and add some key to list conversion
crecine Feb 14, 2024
6a9a2e3
Merge branch 'main' into flops_sgm
crecine Feb 14, 2024
afd6e8d
Merge branch 'main' into flops_sgm
crecine Feb 15, 2024
cfdb0da
moving HE SGM example to test case and minor refactoring
crecine Feb 16, 2024
ee630fe
Merge branch 'flops_sgm' of https://github.com/crecine/om-Aviary into…
crecine Feb 16, 2024
5e912d0
adding skip for missing pyoptsparse
crecine Feb 17, 2024
591a671
reverted test values
crecine Feb 20, 2024
7b09c6e
minor changes to tests
crecine Feb 20, 2024
a4f04ed
fixed value when clearing triggers
crecine Feb 20, 2024
d5a24eb
PR feedback
crecine Feb 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ venv/
ENV/
env.bak/
venv.bak/
.github/*_environment.yml

# Spyder project settings
.spyderproject
Expand Down
1 change: 1 addition & 0 deletions aviary/interface/default_phase_info/two_dof_fiti.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def create_2dof_based_ascent_phases(
)
accel_vals = {}

# need to set trigger units
climb1_kwargs = dict(
input_speed_type=SpeedType.EAS,
input_speed_units='kn',
Expand Down
2 changes: 1 addition & 1 deletion aviary/interface/methods_for_level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def load_inputs(self, aviary_inputs, phase_info=None, engine_builder=None):
elif self.mission_method is SOLVED:
from aviary.interface.default_phase_info.solved import phase_info

print('Loaded default phase_info for'
print('Loaded default phase_info for '
f'{self.mission_method.value.lower()} equations of motion')

# create a new dictionary that only contains the phases from phase_info
Expand Down
17 changes: 17 additions & 0 deletions aviary/mission/flops_based/ode/landing_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
from aviary.mission.flops_based.ode.landing_eom import FlareEOM, StallSpeed
from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE as _TakeoffODE
from aviary.mission.gasp_based.flight_conditions import FlightConditions
from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs
from aviary.utils.aviary_values import AviaryValues
from aviary.utils.functions import set_aviary_initial_values, promote_aircraft_and_mission_vars
from aviary.variable_info.variables import Aircraft, Dynamic, Mission
from aviary.variable_info.variables_in import VariablesIn
from aviary.variable_info.enums import AnalysisScheme


class ExternalSubsystemGroup(om.Group):
Expand Down Expand Up @@ -60,14 +62,29 @@ def initialize(self):
'external_subsystems', default=[],
desc='list of external subsystem builder instances to be added to the ODE')

self.options.declare(
"analysis_scheme",
default=AnalysisScheme.COLLOCATION,
types=AnalysisScheme,
desc="The analysis method that will be used to close the trajectory; for example collocation or time integration",
)

def setup(self):
options = self.options

nn = options["num_nodes"]
analysis_scheme = options['analysis_scheme']
aviary_options = options['aviary_options']
subsystem_options = options['subsystem_options']
core_subsystems = options['core_subsystems']

if analysis_scheme is AnalysisScheme.SHOOTING:
SGM_required_inputs = {
't_curr': {'units': 's'},
Dynamic.Mission.DISTANCE: {'units': 'm'},
}
add_SGM_required_inputs(self, SGM_required_inputs)

self.add_subsystem(
'input_port', VariablesIn(aviary_options=aviary_options),
promotes_inputs=['*'], promotes_outputs=['*'])
Expand Down
85 changes: 83 additions & 2 deletions aviary/mission/flops_based/ode/mission_ODE.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
from dymos.models.atmosphere import USatm1976Comp

from aviary.mission.flops_based.ode.mission_EOM import MissionEOM
from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs, add_SGM_required_outputs
from aviary.utils.aviary_values import AviaryValues
from aviary.utils.functions import promote_aircraft_and_mission_vars
from aviary.variable_info.variable_meta_data import _MetaData
from aviary.variable_info.variables import Dynamic, Mission
from aviary.variable_info.variables import Dynamic, Mission, Aircraft
from aviary.variable_info.variables_in import VariablesIn
from aviary.variable_info.enums import AnalysisScheme


class ExternalSubsystemGroup(om.Group):
Expand Down Expand Up @@ -44,15 +46,29 @@ def initialize(self):
values=['path_constraint', 'boundary_constraint', 'bounded', None],
desc='flag to enforce throttle constraints on the path or at the segment boundaries or using solver bounds'
)
self.options.declare(
"analysis_scheme",
default=AnalysisScheme.COLLOCATION,
types=AnalysisScheme,
desc="The analysis method that will be used to close the trajectory; for example collocation or time integration",
)

def setup(self):
options = self.options
nn = options['num_nodes']
analysis_scheme = options['analysis_scheme']
aviary_options = options['aviary_options']
core_subsystems = options['core_subsystems']
subsystem_options = options['subsystem_options']
engine_count = len(aviary_options.get_val('engine_models'))

if analysis_scheme is AnalysisScheme.SHOOTING:
SGM_required_inputs = {
't_curr': {'units': 's'},
Dynamic.Mission.DISTANCE: {'units': 'm'},
}
add_SGM_required_inputs(self, SGM_required_inputs)

self.add_subsystem(
'input_port',
VariablesIn(aviary_options=aviary_options,
Expand Down Expand Up @@ -169,9 +185,42 @@ def setup(self):
promotes_inputs=['*'],
promotes_outputs=['*'])

self.set_input_defaults(Mission.Design.GROSS_MASS, val=1, units='kg')
self.set_input_defaults(
Aircraft.Fuselage.CHARACTERISTIC_LENGTH, val=1, units='ft')
self.set_input_defaults(Aircraft.Fuselage.FINENESS, val=1, units='unitless')
self.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=1, units='ft**2')
self.set_input_defaults(
Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, val=1, units='ft')
self.set_input_defaults(Aircraft.VerticalTail.FINENESS, val=1, units='unitless')
self.set_input_defaults(Aircraft.VerticalTail.WETTED_AREA, val=1, units='ft**2')
self.set_input_defaults(
Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, val=1, units='ft')
self.set_input_defaults(Aircraft.HorizontalTail.FINENESS,
val=1, units='unitless')
self.set_input_defaults(
Aircraft.HorizontalTail.WETTED_AREA, val=1, units='ft**2')
self.set_input_defaults(Aircraft.Wing.CHARACTERISTIC_LENGTH, val=1, units='ft')
self.set_input_defaults(Aircraft.Wing.FINENESS, val=1, units='unitless')
self.set_input_defaults(Aircraft.Wing.WETTED_AREA, val=1, units='ft**2')
self.set_input_defaults(
Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, val=1, units='unitless')
self.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=1, units='unitless')
self.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD,
val=1, units='unitless')
self.set_input_defaults(Aircraft.Wing.SWEEP, val=1, units='deg')
self.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=1, units='unitless')
self.set_input_defaults(
Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, val=1, units='unitless')
self.set_input_defaults(
Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, val=1, units='unitless')

self.set_input_defaults(Dynamic.Mission.MACH, val=np.ones(nn), units='unitless')
crecine marked this conversation as resolved.
Show resolved Hide resolved
self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones(nn), units='kg')
self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s')
self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.ones(nn), units='m')
self.set_input_defaults(Dynamic.Mission.ALTITUDE_RATE,
val=np.ones(nn), units='m/s')
self.set_input_defaults(
Dynamic.Mission.THROTTLE, val=np.ones((nn, engine_count)),
units='unitless')
Expand All @@ -198,11 +247,43 @@ def setup(self):
],
promotes_outputs=['initial_mass_residual'])

if analysis_scheme is AnalysisScheme.SHOOTING:
SGM_required_outputs = {
Dynamic.Mission.ALTITUDE_RATE: {'units': 'm/s'},
}
add_SGM_required_outputs(self, SGM_required_outputs)

print_level = 0 if analysis_scheme is AnalysisScheme.SHOOTING else 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of wonder why the default is 2 for colocation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's what it was on line 208, so I didn't want to change it.


if analysis_scheme is AnalysisScheme.SHOOTING and False:
crecine marked this conversation as resolved.
Show resolved Hide resolved
from aviary.utils.functions import create_printcomp
dummy_comp = create_printcomp(
all_inputs=[
't_curr',
Mission.Design.RESERVE_FUEL,
Dynamic.Mission.MASS,
Dynamic.Mission.DISTANCE,
Dynamic.Mission.ALTITUDE,
Dynamic.Mission.FLIGHT_PATH_ANGLE,
],
input_units={
't_curr': 's',
Dynamic.Mission.FLIGHT_PATH_ANGLE: 'deg',
Dynamic.Mission.DISTANCE: 'NM',
})
self.add_subsystem(
"dummy_comp",
dummy_comp(),
promotes_inputs=["*"],)
self.set_input_defaults(
Dynamic.Mission.DISTANCE, val=0, units='NM')
self.set_input_defaults('t_curr', val=0, units='s')

self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True,
atol=1.0e-10,
rtol=1.0e-10,
)
self.nonlinear_solver.linesearch = om.BoundsEnforceLS()
self.linear_solver = om.DirectSolver(assemble_jac=True)
self.nonlinear_solver.options['err_on_non_converge'] = True
self.nonlinear_solver.options['iprint'] = 2
self.nonlinear_solver.options['iprint'] = print_level
17 changes: 17 additions & 0 deletions aviary/mission/flops_based/ode/takeoff_ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

from aviary.mission.flops_based.ode.takeoff_eom import StallSpeed, TakeoffEOM
from aviary.mission.gasp_based.flight_conditions import FlightConditions
from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs
from aviary.utils.aviary_values import AviaryValues
from aviary.utils.functions import set_aviary_initial_values, promote_aircraft_and_mission_vars
from aviary.variable_info.variables import Aircraft, Dynamic, Mission
from aviary.variable_info.variables_in import VariablesIn
from aviary.variable_info.enums import AnalysisScheme


class ExternalSubsystemGroup(om.Group):
Expand Down Expand Up @@ -58,14 +60,29 @@ def initialize(self):
'climbing', default=False, types=bool,
desc='mode of operation (ground roll or flight)')

self.options.declare(
"analysis_scheme",
default=AnalysisScheme.COLLOCATION,
types=AnalysisScheme,
desc="The analysis method that will be used to close the trajectory; for example collocation or time integration",
)

def setup(self):
options = self.options

nn = options["num_nodes"]
analysis_scheme = options['analysis_scheme']
aviary_options = options['aviary_options']
subsystem_options = options['subsystem_options']
core_subsystems = options['core_subsystems']

if analysis_scheme is AnalysisScheme.SHOOTING:
SGM_required_inputs = {
't_curr': {'units': 's'},
Dynamic.Mission.DISTANCE: {'units': 'm'},
}
add_SGM_required_inputs(self, SGM_required_inputs)

self.add_subsystem(
'input_port', VariablesIn(aviary_options=aviary_options),
promotes_inputs=['*'], promotes_outputs=['*'])
Expand Down
Loading
Loading