from aviary.core.aviary_problem import AviaryProblem, reload_aviary_problem
from aviary.interface.run_aviary import run_aviary
from aviary.utils.doctape import glue_variable

glue_variable(run_aviary.__name__, md_code=True)
glue_variable(f'{run_aviary.__name__}()', md_code=True)

glue_variable(AviaryProblem.__name__, md_code=True)

glue_variable(reload_aviary_problem.__name__, md_code=True)
glue_variable(f'{AviaryProblem.run_off_design_mission.__name__}()', md_code=True)
glue_variable(f'{reload_aviary_problem.__name__}()', md_code=True)

run_aviary

run_aviary()

AviaryProblem

reload_aviary_problem

run_off_design_mission()

reload_aviary_problem()

Off-Design Missions#

Once an aircraft has been sized, it is common to test how it performs on missions different than its design mission. In Aviary, these missions (which do not modify the aircraft design in any way) are referred to as off-design missions. There are two main ways that off-design missions can be run: immediately following a design mission run in a Python script, or at a later time by loading the results of a perviously run design mission.

Running Off-Design Missions in the Same Script#

It is fairly simple to run the initial aircraft sizing and all desired off-design missions in the same script. The following script runs the inital design problem - it is almost identical to the simple mission example, but in this case we modify the target range to be longer. This is done so when we run the aircraft on a shorter range off-design mission later there is a more obvious change in takeoff gross mass and mission fuel burn. We also save the AviaryProblem object returned by the run_aviary function call. We will use this later to run our off-design missions.

import aviary.api as av

# We will size the aircraft in this example for a longer design range than specified in the default
# phase_info
phase_info = av.default_energy_state_phase_info
phase_info['post_mission']['target_range'] = (2500.0, 'nmi')

# Sizing Mission
design_prob = av.run_aviary(
    aircraft_data='models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv',
    phase_info=phase_info,
    verbosity=0,
)

Now we will run two off-design missions, one of each pre-defined type in Aviary. First is an “off_deign_max_range” mission, which is a mission where the takeoff gross mass of the aircraft is pre-defined, and the aircraft is flown as far as it can with the amount of fuel allowed under that gross mass limit. Second is an “off_design_min_fuel” mission, where the range of the mission is known, and Aviary solves the minimum amount of fuel (and therefore the takeoff gross mass) needed for the aircraft to fly that range.

An off-design mission is run using the run_off_design_mission() method of AviaryProblem. This method has significantly more flexibility than demonstrated in this example, including the ability to change the passengers and cargo loaded on the aircraft, and the option to change the mission profile flown via providing new phase_info.

Here we are using the same basic mission profile and payload of passengers and cargo as the design mission. Aviary will use information from the design mission by default if not explicitly defined when running the off-design mission.

# OFF_DESIGN_MAX_RANGE Mission - fixed mass, solve for max range
off_design_max_range_prob = design_prob.run_off_design_mission(
    problem_type='off_design_max_range',
    mission_gross_mass=115000,
    name='off_design_max_range_mission',
)

# OFF_DESIGN_MIN_FUEL Mission - fixed range, solve for min fuel
off_design_min_fuel_prob = design_prob.run_off_design_mission(
    problem_type='off_design_min_fuel', mission_range=1250, name='off_design_min_fuel_mission'
)

Once both missions are complete, we can compare the difference between the design and off-design missions. We are expecting fundamental design parameters of the aircraft, such as its maximum takeoff gross mass and its design range to remain unchanged. However, the takeoff gross mass for each particular mission should change, due to a change in the amount of fuel the aircraft is loaded with before takeoff, as well as mission range. We should see a reduction in both of these quantities for the off-design missions, with the pre-defined properties (gross mass for the off_design_max_range mission, mission range for the off_design_min_fuel mission) matching what we asked Aviary to fly.

Sizing Results
--------------
Design Range = 3500.0 nmi
Mission Range = 2500.0 nmi
Fuel Mass = 17778.843208047372 lbm
Operating Empty Mass = 72076.74372045652 lbm
Payload Mass = 30800.0 lbm
Design Gross Mass = 120655.5869285039 lbm
Mission Gross Mass = 120655.5869285039 lbm

OFF_DESIGN_MAX_RANGE Results
---------------
Design Range = 3500.0 nmi
Mission Range = 1645.8066975702475 nmi
Fuel Mass = 12123.256279543479 lbm
Operating Empty Mass = 72076.74372045652 lbm
Payload Mass = 30800.0 lbm
Design Gross Mass = 120655.5869285039 lbm
Mission Gross Mass = 115000.0 lbm

OFF_DESIGN_MIN_FUEL Results
-----------------
Design Range = 3500.0 nmi
Mission Range = 1250.0 nmi
Fuel Mass = 9548.64788974222 lbm
Operating Empty Mass = 72076.74372045652 lbm
Payload Mass = 30800.0 lbm
Design Gross Mass = 120655.5869285039 lbm
Mission Gross Mass = 112425.39161019874 lbm

Reloading a Design Mission#

The other way to run an off-design mission is by loading the results of a design mission that has already been run. This is useful because aircraft designers often want to test out new off-design missions, and we don’t want to have to re-run the sizing mission every time.

This is done with a helper function reload_aviary_problem(). This function returns a fresh AviaryProblem loaded with all of the information from the sizing run. To reconstruct the design aircraft, reload_aviary_problem needs two pieces of information: a specific results file generated by Aviary after sizing an aircraft, and the original phase info used by the design mission.

Here we will reload the design problem, then use that reloaded problem to run the same “off_design_max_range” mission as before. When viewing the results, we can see they exactly match the results we got earlier.

reloaded_problem = av.reload_aviary_problem(
    'advanced_single_aisle_FLOPS_out/reports/sizing_results.json', phase_info
)

new_off_design_max_range_prob = design_prob.run_off_design_mission(
    problem_type='off_design_max_range',
    mission_gross_mass=115000,
    name='off_design_max_range_mission',
)
New OFF_DESIGN_MAX_RANGE Results
---------------
Design Range = 3500.0 nmi
Mission Range = 1645.8066975702475 nmi
Fuel Mass = 12123.256279543479 lbm
Operating Empty Mass = 72076.74372045652 lbm
Payload Mass = 30800.0 lbm
Design Gross Mass = 120655.5869285039 lbm
Mission Gross Mass = 115000.0 lbm