-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
681 additions
and
329 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
107 changes: 107 additions & 0 deletions
107
aviary/examples/external_subsystems/custom_aero/custom_aero_builder.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
""" | ||
Builder for a simple drag calculation that replaces Aviary's calculation. | ||
""" | ||
import openmdao.api as om | ||
|
||
from aviary.examples.external_subsystems.custom_aero.simple_drag import SimpleAeroGroup | ||
from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase | ||
from aviary.variable_info.variables import Aircraft, Dynamic | ||
|
||
|
||
class CustomAeroBuilder(SubsystemBuilderBase): | ||
""" | ||
Prototype of a subsystem that overrides an aviary internally computed var. | ||
It also provides a method to build OpenMDAO systems for the pre-mission and mission computations of the subsystem. | ||
Attributes | ||
---------- | ||
name : str ('simple_aero') | ||
object label | ||
""" | ||
|
||
def __init__(self, name='simple_aero'): | ||
super().__init__(name) | ||
|
||
def build_mission(self, num_nodes, aviary_inputs, **kwargs): | ||
""" | ||
Build an OpenMDAO system for the mission computations of the subsystem. | ||
Returns | ||
------- | ||
Returns | ||
------- | ||
mission_sys : openmdao.core.System | ||
An OpenMDAO system containing all computations that need to happen | ||
during the mission. This includes time-dependent states that are | ||
being integrated as well as any other variables that vary during | ||
the mission. | ||
""" | ||
aero_group = SimpleAeroGroup( | ||
num_nodes=num_nodes, | ||
) | ||
return aero_group | ||
|
||
def mission_inputs(self, **kwargs): | ||
promotes = [ | ||
Dynamic.Atmosphere.STATIC_PRESSURE, | ||
Dynamic.Atmosphere.MACH, | ||
Dynamic.Vehicle.MASS, | ||
'aircraft:*', | ||
] | ||
return promotes | ||
|
||
def mission_outputs(self, **kwargs): | ||
promotes = [ | ||
Dynamic.Vehicle.DRAG, | ||
Dynamic.Vehicle.LIFT, | ||
] | ||
return promotes | ||
|
||
def get_parameters(self, aviary_inputs=None, phase_info=None): | ||
""" | ||
Return a dictionary of fixed values for the subsystem. | ||
Optional, used if subsystems have fixed values. | ||
Used in the phase builders (e.g. cruise_phase.py) when other parameters are added to the phase. | ||
This is distinct from `get_design_vars` in a nuanced way. Design variables | ||
are variables that are optimized by the problem that are not at the phase level. | ||
An example would be something that occurs in the pre-mission level of the problem. | ||
Parameters are fixed values that are held constant throughout a phase, but if | ||
`opt=True`, they are able to change during the optimization. | ||
Parameters | ||
---------- | ||
phase_info : dict | ||
The phase_info subdict for this phase. | ||
Returns | ||
------- | ||
fixed_values : dict | ||
A dictionary where the keys are the names of the fixed variables | ||
and the values are dictionaries with the following keys: | ||
- 'value': float or array | ||
The fixed value for the variable. | ||
- 'units': str | ||
The units for the fixed value (optional). | ||
- any additional keyword arguments required by OpenMDAO for the fixed | ||
variable. | ||
""" | ||
params = {} | ||
params[Aircraft.Wing.AREA] = { | ||
'shape': (1, ), | ||
'static_target': True, | ||
'units': 'ft**2', | ||
} | ||
return params | ||
|
||
def needs_mission_solver(self, aviary_inputs): | ||
""" | ||
Return True if the mission subsystem needs to be in the solver loop in mission, otherwise | ||
return False. Aviary will only place it in the solver loop when True. The default is | ||
True. | ||
""" | ||
return False |
60 changes: 60 additions & 0 deletions
60
aviary/examples/external_subsystems/custom_aero/run_simple_aero.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" | ||
Run the a mission with a simple external component that computes the wing | ||
and horizontal tail mass. | ||
""" | ||
from copy import deepcopy | ||
|
||
import aviary.api as av | ||
from aviary.examples.external_subsystems.custom_aero.custom_aero_builder import CustomAeroBuilder | ||
|
||
|
||
phase_info = deepcopy(av.default_height_energy_phase_info) | ||
|
||
# Just do cruise in this example. | ||
phase_info.pop('climb') | ||
phase_info.pop('descent') | ||
|
||
# Add custom aero. | ||
# TODO: This API for replacing aero will be changed an upcoming release. | ||
phase_info['cruise']['external_subsystems'] = [CustomAeroBuilder()] | ||
|
||
# Disable internal aero | ||
# TODO: This API for replacing aero will be changed an upcoming release. | ||
phase_info['cruise']['subsystem_options']['core_aerodynamics'] = { | ||
'method': 'external', | ||
} | ||
|
||
|
||
if __name__ == '__main__': | ||
prob = av.AviaryProblem() | ||
|
||
# Load aircraft and options data from user | ||
# Allow for user overrides here | ||
prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) | ||
|
||
# Preprocess inputs | ||
prob.check_and_preprocess_inputs() | ||
|
||
prob.add_pre_mission_systems() | ||
|
||
prob.add_phases() | ||
|
||
prob.add_post_mission_systems() | ||
|
||
# Link phases and variables | ||
prob.link_phases() | ||
|
||
# Note, SLSQP might have troubles here. | ||
prob.add_driver("SLSQP") | ||
|
||
prob.add_design_variables() | ||
|
||
prob.add_objective() | ||
|
||
prob.setup() | ||
|
||
prob.set_initial_guesses() | ||
|
||
prob.run_aviary_problem(suppress_solver_print=True) | ||
|
||
print('done') |
104 changes: 104 additions & 0 deletions
104
aviary/examples/external_subsystems/custom_aero/simple_drag.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import numpy as np | ||
|
||
import openmdao.api as om | ||
|
||
from aviary.subsystems.aerodynamics.aero_common import DynamicPressure | ||
from aviary.subsystems.aerodynamics.flops_based.lift import LiftEqualsWeight | ||
from aviary.subsystems.aerodynamics.flops_based.drag import SimpleDrag | ||
from aviary.variable_info.variables import Aircraft, Dynamic, Mission | ||
|
||
|
||
class SimplestDragCoeff(om.ExplicitComponent): | ||
""" | ||
Simple representation of aircraft drag as CD = CD_zero + k * CL**2 | ||
Values are fictional. Typically, some higher fidelity method will go here instead. | ||
""" | ||
|
||
def initialize(self): | ||
self.options.declare( | ||
"num_nodes", default=1, types=int, | ||
desc="Number of nodes along mission segment" | ||
) | ||
|
||
self.options.declare("CD_zero", default=0.01) | ||
self.options.declare("k", default=0.065) | ||
|
||
def setup(self): | ||
nn = self.options["num_nodes"] | ||
|
||
self.add_input('cl', val=np.zeros(nn)) | ||
|
||
self.add_output('CD', val=np.zeros(nn)) | ||
|
||
def setup_partials(self): | ||
nn = self.options["num_nodes"] | ||
arange = np.arange(nn) | ||
|
||
self.declare_partials('CD', 'cl', rows=arange, cols=arange) | ||
|
||
def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): | ||
CD_zero = self.options["CD_zero"] | ||
k = self.options["k"] | ||
|
||
cl = inputs['cl'] | ||
|
||
outputs['CD'] = CD_zero + k * cl**2 | ||
|
||
def compute_partials(self, inputs, partials, discrete_inputs=None): | ||
k = self.options["k"] | ||
|
||
cl = inputs['cl'] | ||
|
||
partials['CD', 'cl'] = 2.0 * k * cl | ||
|
||
|
||
class SimpleAeroGroup(om.Group): | ||
|
||
def initialize(self): | ||
self.options.declare( | ||
"num_nodes", default=1, types=int, | ||
desc="Number of nodes along mission segment" | ||
) | ||
|
||
def setup(self): | ||
nn = self.options["num_nodes"] | ||
|
||
self.add_subsystem( | ||
'DynamicPressure', | ||
DynamicPressure(num_nodes=nn), | ||
promotes_inputs=[ | ||
Dynamic.Atmosphere.MACH, | ||
Dynamic.Atmosphere.STATIC_PRESSURE, | ||
], | ||
promotes_outputs=[Dynamic.Atmosphere.DYNAMIC_PRESSURE], | ||
) | ||
|
||
self.add_subsystem( | ||
"Lift", | ||
LiftEqualsWeight(num_nodes=nn), | ||
promotes_inputs=[ | ||
Aircraft.Wing.AREA, | ||
Dynamic.Vehicle.MASS, | ||
Dynamic.Atmosphere.DYNAMIC_PRESSURE, | ||
], | ||
promotes_outputs=['cl', Dynamic.Vehicle.LIFT], | ||
) | ||
|
||
self.add_subsystem( | ||
"SimpleDragCoeff", | ||
SimplestDragCoeff(num_nodes=nn), | ||
promotes_inputs=['cl'], | ||
promotes_outputs=['CD'], | ||
) | ||
|
||
self.add_subsystem( | ||
"SimpleDrag", | ||
SimpleDrag(num_nodes=nn), | ||
promotes_inputs=[ | ||
'CD', | ||
Dynamic.Atmosphere.DYNAMIC_PRESSURE, | ||
Aircraft.Wing.AREA, | ||
], | ||
promotes_outputs=[Dynamic.Vehicle.DRAG], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.