Off-Design Missions#
Overview#
Off-design missions are missions that take an already designed and sized aircraft and attempt to run different mission trajectories, different payload quantities, or both.
Off-design missions are enabled for the following mission types:
HEIGHT_ENERGY
TWO_DEGREES_OF_FREEDOM
There are currently two types of off-design missions supported in Aviary:
Alternate Missions: the mission’s target range and aircraft payload mass are inputs and the fuel mass required is solved for.
Fallout Missions: the aircraft payload and gross mass as inputs and the range of the aircraft is solved for.
The off-design missions correspond to the different problem types that can have differing objectives which are discussed in detail in Level 2. The problem type determines what the optimizer can control to find a valid solution.
Sizing Missions allow the optimizer to control both the
mission:summary:gross_mass
andmission:design:gross_mass
for the given mission and objective.Alternate Missions allow the optimizer to only control the
mission:summary:gross_mass
for the mission.Fallout Missions don’t allow the optimizer to control either
mission:summary:gross_mass
ormission:design:gross_mass
but allows the optimizer to extend the range until the summary matches the design.
There are currently 3 different methods for running an off-design mission within Aviary.
The first method is to take the input deck of an already sized aircraft and change its problem type to either fallout
or alternate
.
Note
The user may need to revise some of the values in their input deck for the off-design mission. Since the aircraft is not re-designed, it is assumed that provided inputs constitute a valid aircraft.
The second method is to run off-design missions in the same script used to solve the design mission.
An example of this is shown in aviary/examples/run_off_design_example.py
.
The third method is to run a sizing mission to design the aircraft, save the sizing information to a JSON file, then load the off-design mission in another script.
Note
If the sizing mission did not converge to a valid aircraft design, any off-design analysis will be invalid even if the off-design missions themselves converged. Therefore the validity of off-design analysis depends entirely on the validity of its source sizing mission.
Off-Design from an already sized aircraft.#
The first method of running an off-design mission requires that the user has an input deck of a fully sized and valid aircraft.
ex: aircraft_for_bench_FwFm.csv
.
This is done by adding one of the following lines to its csv file:
settings:problem_type, fallout
or
settings:problem_type, alternate
Once the problem type is specified, run Aviary as you would any other mission.
Note
Off-design missions are run with the assumption that the sizing mission’s mission:design:gross_mass
is the maximum structural mass the aircraft can support.
However, Aviary is capable of running a converging off-design missions with mission:summary:gross_mass
that exceed that structural constraint.
Therefore the user should check the mission:summary:gross_mass
of the off-design to ensure the optimization is valid.
Sizing & off-design in the same script.#
Firstly, we highly recommend users first read through and understand the Level 2 onboarding guide before attempting an off-design mission.
This is the Aviary Team’s preferred method for running off-design missions as it allows the user to interrogate both the sizing and off-design missions together in the same script.
Off-design functionality within the script involves first running a sizing mission then transferring the sizing parameters via JSON file into a new AviaryProblem()
object.
User input payload, phase_info
, and mission_mass
or mission_range
is parsed to the new problem object and the problem is executed within the level 2 method.
Running an off-design mission first requires a sizing mission setup similar to aviary/examples/run_level2_example.py
then the addition of save_sizing_to_json()
to the AviaryProblem
.
prob.save_sizing_to_json(json_filename = 'sizing_problem.json')
The save_sizing_to_json()
argument saves the sizing mission’s parameters to a JSON filename of the user’s choosing where sizing_problem.json
is the default filename.
To run a fallout or alternate mission these level 2 functions can be added to the end of the script.
prob.fallout_mission(json_filename = 'sizing_problem.json')
prob.alternate_mission(json_filename = 'sizing_problem.json')
If an argument is left empty Aviary will assume it is the same as that of the sizing mission. Both off-design mission types take payload as an input parameter. The mission’s payload is split up into the 3 passenger classes and the 2 cargo loadings. The respective Aviary variables are then updated with the user’s off-design passenger and cargo quantities.
Note
As of v0.9.10 Aviary’s off-design capabilities do not allow missions to be run with 0 passengers, so a minimum of 1 passenger must be specified. This is a known bug and is currently being investigated.
|
|
|
---|---|---|
|
aircraft:crew_and_payload:num_first_class |
The number of first class passengers |
|
aircraft:crew_and_payload:num_business_class |
The number of business class passengers |
|
aircraft:crew_and_payload:num_tourist_class |
The number of tourist class passengers |
|
aircraft:crew_and_payload:num_passengers |
Total number of passengers |
|
aircraft:crew_and_payload:wing_cargo |
Cargo carried in wing |
|
aircraft:crew_and_payload:misc_cargo |
Additional cargo carried in fuselage |
|
aircraft:crew_and_payload:cargo_mass |
Total mass of as-flown cargo |
|
phase_info |
The mission trajectory for the aircraft |
|
|
The target range for alternate missions |
|
|
The mission mass for fallout missions |
Note
Off-design missions cannot be run with more passengers than the original sizing mission.
For example, if aircraft:crew_and_payload:num_first_class within the Aviary inputs csv was set to 3, an off-design mission cannot be run where num_first = 8
as the cabin for first class was sized for precisely 3 passengers.
The phase_info
argument allows the user to specify a different phase information for an off-design mission trajectory, more information can be found in The phase_info
Format.
This can be due to the off-design mission requiring a different trajectory shape or phase durations than the sizing mission.
For example, an aircraft sized for long-range cruise might need its climb and descent profiles modified to operate on shorter routes.
Note
In cases where passengers or cargo are changed and the user has not specified a aircraft:crew_and_payload:cargo_container_mass
in the Aviary input deck, off-design missions recalculates it in the off-design mission.
It is the only parameter within the operating mass that gets recalculated between off-design and sizing.
%%capture
"""
This is an example of a sizing mission and alternate mission being run in the same script.
This is done with
"""
import aviary.api as av
# inputs that run_aviary() requires
aircraft_data = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'
optimizer = 'SLSQP'
phase_info = av.default_height_energy_phase_info
max_iter = 15
# Set up and run avairy problem.
prob = av.AviaryProblem(verbosity=0)
# This is the default FwFm (Flops weights Flops mission) aircraft.
prob.load_inputs(aircraft_data, phase_info)
prob.check_and_preprocess_inputs()
prob.add_pre_mission_systems()
prob.add_phases()
prob.add_post_mission_systems()
prob.link_phases()
prob.add_driver(optimizer, max_iter=max_iter)
prob.add_design_variables()
prob.add_objective()
prob.setup()
prob.set_initial_guesses()
prob.run_aviary_problem()
# save the sizing mission to a JSON file
prob.save_sizing_to_json(json_filename='off_design_documentation_example.json')
# initialize alternate mission flying a much shorter distance.
# if payload values are unspecified, off-design will uses the values from the sizing mission.
# the mission_range argument is much shorter than the sizing mission's 1906 NM range.
prob.alternate_mission(
json_filename='off_design_documentation_example.json',
num_first=0,
num_business=0,
num_tourist=50,
num_pax=50,
wing_cargo=0,
misc_cargo=0,
cargo_mass=0,
mission_range=1000,
phase_info=phase_info,
verbosity=0,
)
Off-design missions separately#
The third method in running an off-design mission requires saving the sizing information as a JSON file using save_sizing_to_json()
then calls the JSON file into an off-design mission in another script.
This method allows for off-design missions to be run without re-executing the sizing mission every time.
Once saved, the third method works identically to the second method except that the user must manually run the _load_off_design()
function to create a new Aviary problem.
The _load_off_design()
function then requires the json_filename
input along with 3 additional problem definition parameters problem_type
, equations_of_motion
, and mass_method
.
Once defined, the _load_off_design()
function essentially replaces the load_inputs()
step of a standard level 2 problem.
The user can then adjust payload quantities and mission_range
/mission_gross_mass
then complete the level 2 script as shown below.
problem_type
: Determines which type of off-design analysis the user would like to run. (alternate or fallout)equations_of_motion
: Determines the type of trajectory calculations the user is running. (HEIGHT_ENERGY
orTWO_DEGREES_OF_FREEDOM
)mass_method
: Specifies how mass calculations are handled (FLOPS or GASP)
%%capture
"""
This is an example of running off-design mission directly form a saved sized aircraft JSON file
Note: If there were external subsystems in the original sized aircraft model
these will NOT be transferred (since these are not saved in the JSON file).
"""
from aviary.interface.methods_for_level2 import _load_off_design
from aviary.variable_info.enums import LegacyCode
import aviary.api as av
optimizer = 'SLSQP'
phase_info = av.default_height_energy_phase_info
max_iter = 15
# Load aircraft and options data from provided sources
# To run an alternate mission, we need the sized aircraft JSON file from the sizing mission.
# Set ProblemType to ALTERNATE, and specify the mission range and payload mass.
# mission_gross_mass does nothing).
# Use specific _load_off_design function to define the off-design mission.
prob_alternate = _load_off_design(
json_filename='off_design_documentation_example.json',
problem_type=av.ProblemType.ALTERNATE,
equations_of_motion=av.EquationsOfMotion.HEIGHT_ENERGY,
mass_method=LegacyCode.FLOPS,
phase_info=phase_info,
num_first=0,
num_business=0,
num_tourist=50,
num_pax=50,
wing_cargo=0,
misc_cargo=0,
cargo_mass=0,
mission_range=1000,
verbosity=0,
)
# Run off-design mission the same way as any Level 2 aviary problem.
prob_alternate.check_and_preprocess_inputs()
prob_alternate.add_pre_mission_systems()
prob_alternate.add_phases()
prob_alternate.add_post_mission_systems()
prob_alternate.link_phases()
prob_alternate.add_driver(optimizer=optimizer, max_iter=max_iter)
prob_alternate.add_design_variables()
prob_alternate.add_objective()
prob_alternate.setup()
prob_alternate.set_initial_guesses()
prob_alternate.run_aviary_problem()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 21
13 max_iter = 15
14 # Load aircraft and options data from provided sources
15
16 # To run an alternate mission, we need the sized aircraft JSON file from the sizing mission.
(...) 19
20 # Use specific _load_off_design function to define the off-design mission.
---> 21 prob_alternate = _load_off_design(
22 json_filename='off_design_documentation_example.json',
23 problem_type=av.ProblemType.ALTERNATE,
24 equations_of_motion=av.EquationsOfMotion.HEIGHT_ENERGY,
25 mass_method=LegacyCode.FLOPS,
26 phase_info=phase_info,
27 num_first=0,
28 num_business=0,
29 num_tourist=50,
30 num_pax=50,
31 wing_cargo=0,
32 misc_cargo=0,
33 cargo_mass=0,
34 mission_range=1000,
35 verbosity=0,
36 )
38 # Run off-design mission the same way as any Level 2 aviary problem.
39 prob_alternate.check_and_preprocess_inputs()
File ~/work/Aviary/Aviary/aviary/interface/methods_for_level2.py:2014, in _load_off_design(json_filename, problem_type, equations_of_motion, mass_method, phase_info, num_first, num_business, num_tourist, num_pax, wing_cargo, misc_cargo, cargo_mass, mission_range, mission_gross_mass, verbosity)
2011 phase_info['post_mission']['target_range'] = (mission_range, 'nmi')
2012 # set initial guess for Mission.Summary.GROSS_MASS to help optimizer with new design variable bounds.
2013 prob.aviary_inputs.set_val(
-> 2014 Mission.Summary.GROSS_MASS, mission_gross_mass * 0.9, units='lbm'
2015 )
2017 elif problem_type == ProblemType.FALLOUT:
2018 # Set mission fuel and calculate gross weight, aviary will calculate range
2019 if mission_gross_mass is None:
TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'