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

Off Design Payload #623

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
edb87a6
add design payload weight into calculation for design fuel mass requi…
cmbenne3 Dec 9, 2024
cf1ca15
update PayloadMass calculations to allow for specification of design …
cmbenne3 Dec 9, 2024
01e2b6b
updates to allow for design vs as flown cargo
cmbenne3 Dec 9, 2024
ea9a51e
addition of max_cargo_mass variable to h nable ackwards compatability…
cmbenne3 Dec 9, 2024
8aa98a5
update preprocessors to manage cargo_mass variables and print cargo a…
cmbenne3 Dec 9, 2024
d44b6c3
set assumed cargo parameters at end of logic flow and clean up warnin…
cmbenne3 Dec 9, 2024
292871f
update preprocessors with error message when flying with more payload…
cmbenne3 Dec 9, 2024
9d8a693
setting Design.CARGO_MASS as a promoted aviary_input rather than an o…
cmbenne3 Dec 9, 2024
9ed9093
update variable_meta_data
cmbenne3 Dec 10, 2024
44d7c92
update variable meta_data and improvements to error messaging in prep…
cmbenne3 Dec 10, 2024
777df7b
updates to load_off_design function to handle num_pax and cargo. WIP …
cmbenne3 Dec 10, 2024
20416d6
rename actual_range as Mission.Summary.Range
Dec 12, 2024
aa3baaf
typo fixes
Dec 12, 2024
85ea83a
fixing more case sensitive typos
Dec 12, 2024
ae0b97d
Merge branch 'OpenMDAO:main' into fallout_summary_range
cmbenne3 Jan 8, 2025
748297c
Merge branch 'main' into fallout_summary_range
jkirk5 Jan 8, 2025
eb283a2
update test value of Mission.Summary.Range in GwGm shooting to correc…
Jan 13, 2025
82c134f
Merge branch 'main' into off_des_payload3
cmbenne3 Jan 13, 2025
2f04c3d
updates required due to changes made to accessing aviary_options
Jan 13, 2025
79a57e4
Merge branch 'fallout_summary_range' of https://github.com/cmbenne3/A…
Jan 13, 2025
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
26 changes: 15 additions & 11 deletions aviary/interface/methods_for_level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,8 @@ def add_post_mission_systems(self, include_landing=True):
mass_resid={'units': 'lbm'})

if self.mass_method is GASP:
payload_mass_src = Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS
#payload_mass_src = Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS
payload_mass_src = Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS
else:
payload_mass_src = Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS

Expand Down Expand Up @@ -1546,7 +1547,7 @@ def link_phases(self):
connected=true_unless_mpi)

self.model.connect(f'traj.{self.regular_phases[-1]}.timeseries.distance',
'actual_range',
Mission.Summary.RANGE,
src_indices=[-1], flat_src_indices=True)

elif self.mission_method is SOLVED_2DOF:
Expand Down Expand Up @@ -1672,14 +1673,14 @@ def link_phases(self):
Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])

connect_map = {
f"traj.{self.regular_phases[-1]}.timeseries.distance": 'actual_range',
f"traj.{self.regular_phases[-1]}.timeseries.distance": Mission.Summary.RANGE,
}

else:
connect_map = {
"taxi.mass": "traj.mass_initial",
Mission.Takeoff.ROTATION_VELOCITY: "traj.SGMGroundroll_velocity_trigger",
"traj.distance_final": 'actual_range',
"traj.distance_final": Mission.Summary.RANGE,
"traj.mass_final": Mission.Landing.TOUCHDOWN_MASS,
}

Expand Down Expand Up @@ -2887,7 +2888,7 @@ def _add_objectives(self):
"val": self.target_range, "units": "NM"},
),
promotes_inputs=[
"actual_range",
("actual_range", Mission.Summary.RANGE),
("ascent_duration", Mission.Takeoff.ASCENT_DURATION),
],
promotes_outputs=[("reg_objective", Mission.Objectives.RANGE)],
Expand All @@ -2913,8 +2914,8 @@ def _add_objectives(self):
range_resid={"val": 30, "units": "NM"},
),
promotes_inputs=[
"actual_range",
("target_range", Mission.Summary.RANGE),
("actual_range", Mission.Summary.RANGE),
"target_range",
],
promotes_outputs=[
("range_resid", Mission.Constraints.RANGE_RESIDUAL)],
Expand Down Expand Up @@ -3077,7 +3078,7 @@ def _read_sizing_json(aviary_problem, json_filename):


def _load_off_design(json_filename, ProblemType, phase_info,
payload, mission_range, mission_gross_mass):
num_pax, cargo_mass, mission_range, mission_gross_mass):
"""
This function loads a sized aircraft, and sets up an aviary problem
for a specified off design mission.
Expand All @@ -3090,8 +3091,10 @@ def _load_off_design(json_filename, ProblemType, phase_info,
Alternate or Fallout. Alternate requires mission_range input and
Fallout requires mission_fuel input
phase_info: phase_info dictionary for off design mission
payload: float
Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS
num_pax: integer
Aircraft.CrewPayload.NUM_PASSENGERS
cargo_mass: float
Aircraft.CrewPayload.CARGO_MASS
mission_range float
Mission.Summary.RANGE 'NM'
mission_gross_mass float
Expand All @@ -3114,7 +3117,8 @@ def _load_off_design(json_filename, ProblemType, phase_info,

# Set Payload
prob.aviary_inputs.set_val(
Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, payload, units='lbm')
Aircraft.CrewPayload.NUM_PASSENGERS, num_pax, units='unitless')
prob.aviary_inputs.set_val(Aircraft.CrewPayload.CARGO_MASS, cargo_mass, 'lbm')

if ProblemType == ProblemType.ALTERNATE:
# Set mission range, aviary will calculate required fuel
Expand Down
2 changes: 2 additions & 0 deletions aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ aircraft:controls:control_mass_increment,0,lbm
aircraft:controls:stability_augmentation_system_mass,0,lbm
aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless
aircraft:crew_and_payload:cargo_mass,10040,lbm
#aircraft:crew_and_payload:design:cargo_mass,0,lbm
#aircraft:crew_and_payload:max_cargo_mass,0,lbm
aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm
aircraft:crew_and_payload:design:num_passengers,180,unitless
aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm
Expand Down
12 changes: 10 additions & 2 deletions aviary/subsystems/mass/gasp_based/fixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,15 @@ def initialize(self):
add_aviary_option(self, Aircraft.CrewPayload.NUM_PASSENGERS)
add_aviary_option(self, Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS,
units='lbm')
add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS)
add_aviary_option(self, Aircraft.CrewPayload.MAX_CARGO_MASS)

def setup(self):
add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, val=10040)
add_aviary_input(self, Aircraft.CrewPayload.Design.CARGO_MASS, val=0)

add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=0)
add_aviary_output(self, Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, val=0)

self.add_output(
"payload_mass_des", val=0, units="lbm", desc="WPLDES: design payload"
Expand All @@ -278,12 +282,16 @@ def setup(self):
def compute(self, inputs, outputs):
pax_mass, _ = self.options[Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS]
PAX = self.options[Aircraft.CrewPayload.NUM_PASSENGERS]
PAX_des = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS]
cargo_mass = inputs[Aircraft.CrewPayload.CARGO_MASS]
cargo_mass_des = inputs[Aircraft.CrewPayload.Design.CARGO_MASS]
cargo_mass_max = self.options[Aircraft.CrewPayload.MAX_CARGO_MASS]

outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = \
payload_mass = pax_mass * PAX
outputs["payload_mass_des"] = payload_mass
outputs["payload_mass_max"] = pax_mass * PAX + cargo_mass
outputs["payload_mass_des"] = pax_mass * PAX_des + cargo_mass_des
outputs["payload_mass_max"] = pax_mass * PAX_des + cargo_mass_max
outputs[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS] = pax_mass * PAX + cargo_mass


class ElectricAugmentationMass(om.ExplicitComponent):
Expand Down
2 changes: 1 addition & 1 deletion aviary/subsystems/mass/gasp_based/fuel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ def compute(self, inputs, outputs):
- control_wt
- fixed_equip_wt
- useful_wt
- payload_wt
- payload_wt_des
- fuel_sys_wt
) / GRAV_ENGLISH_LBM
outputs["fuel_mass_min"] = (
Expand Down
85 changes: 85 additions & 0 deletions aviary/utils/preprocessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from aviary.utils.named_values import get_keys
from aviary.variable_info.variable_meta_data import _MetaData
from aviary.variable_info.variables import Aircraft, Mission, Settings
from aviary.variable_info.enums import ProblemType
from aviary.utils.test_utils.variable_test import get_names_from_hierarchy


Expand Down Expand Up @@ -162,6 +163,90 @@ def preprocess_crewpayload(aviary_options: AviaryValues):
raise om.AnalysisError(
f"ERROR: In preprocesssors.py: NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS)}) is larger than the number of seats set by Design.NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS)}) .")

# Check and process cargo variables
input_cargo = Aircraft.CrewPayload.CARGO_MASS in aviary_options
input_max_cargo = Aircraft.CrewPayload.MAX_CARGO_MASS in aviary_options
input_des_cargo = Aircraft.CrewPayload.Design.CARGO_MASS in aviary_options

problem_type = aviary_options.get_val(Settings.PROBLEM_TYPE)

if input_cargo:
cargo = aviary_options.get_val(Aircraft.CrewPayload.CARGO_MASS,'lbm')
if input_max_cargo:
max_cargo = aviary_options.get_val(Aircraft.CrewPayload.MAX_CARGO_MASS,'lbm')
if input_des_cargo:
des_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.CARGO_MASS,'lbm')
if problem_type == ProblemType.SIZING and cargo != des_cargo:
cargo = des_cargo
print('Warning! Aircraft.CrewPayload.CARGO_MASS != Aircraft.CrewPayload.Design.CARGO_MASS for sizing mission. Setting as-flown CARGO_MASS = Design.CARGO_MASS')
# user has set all three check if consistent
else:
# user has set cargo & max: assume des = max
des_cargo = max_cargo
print('Aircraft.CrewPayload.Design.CARGO_MASS missing, assume Design.CARGO_MASS = MAX_CARGO_MASS')
elif input_des_cargo:
# user has set cargo & des: assume max = des
des_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.CARGO_MASS,'lbm')
max_cargo = des_cargo
print('Aircraft.CrewPayload.MAX_CARGO_MASS missing, assume MAX_CARGO_MASS = Design.CARGO_MASS')
else:
# user has set cargo only: assume intention to set max only and
print('WARNING: User has only set Aircraft.CrewPayload.CARGO_MASS. For backwards compatiability, Aviary is assuming user intended to set MAX_CARGO_MASS. Setting CARGO_MASS and Design.CARGO_MASS = 0')
max_cargo = cargo
cargo = 0
des_cargo = 0

elif input_max_cargo:
max_cargo = aviary_options.get_val(Aircraft.CrewPayload.MAX_CARGO_MASS,'lbm')
if input_des_cargo:
des_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.CARGO_MASS,'lbm')
# user has set max & des: assume flown = 0
cargo = 0
print('Aircraft.CrewPayload.CARGO_MASS missing, assume CARGO_MASS = 0')
else:
# user has set max only: assume flown = des = 0
cargo = 0
des_cargo = 0
print('Aircraft.CrewPayload.CARGO_MASS and Aircraft.CrewPayload.Design.CARGO_MASS missing, assume CARGO_MASS and Design.CARGO_MASS = 0. No Cargo is flown on any mission')

elif input_des_cargo:
des_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.CARGO_MASS,'lbm')
# user has only input des: assume max = des and flown = 0
max_cargo = des_cargo
cargo = 0
print('Aircraft.CrewPayload.CARGO_MASS and Aircraft.CrewPayload.MAX_CARGO_MASS missing, assume CARGO_MASS = 0 and MAX_CARGO_MASS = Design.CARGO_MASS')

else:
#user has input no cargo information
cargo = max_cargo = des_cargo = 0
print('No CARGO variables detected, assume CARGO_MASS = MAX_CARGO_MASS = Design.CARGO_MASS = 0')

# check for potential cargo errors:
if cargo > des_cargo:
print('WARNING! as flown cargo > design cargo')

if cargo > max_cargo or des_cargo > max_cargo:
print('WARNING! as flown and/or design cargo > max_cargo')
raise om.AnalysisError(
f"ERROR: In preprocesssors.py: Aircraft.CrewPayload.CARGO_MASS {cargo} and/or Aircraft.CrewPayload.Design.CARGO_MASS {des_cargo} > Aircraft.CrewPayload.MAX_CARGO_MASS {max_cargo}")

# calculate and check total payload NOTE this is only used for error messaging the calculations for analysis are subsystems/mass/gasp_based:
pax_mass = aviary_options.get_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS,'lbm')
design_passenger_payload_mass = design_num_pax * pax_mass
des_payload = design_passenger_payload_mass + des_cargo
num_pax = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS)
as_flown_passenger_payload_mass = num_pax * pax_mass
as_flown_payload = as_flown_passenger_payload_mass + cargo
if as_flown_payload > des_payload:
print('WARNING! as flown payload > design payload! Please re-design the aircraft!')
#raise om.AnalysisError(
# f"ERROR: In preprocesssors.py: as_flown payload {as_flown_payload} = passenger_payload_mass {as_flown_passenger_payload_mass} + cargo_mass {cargo} is larger than the design payload {des_payload} = design_passenger_payload {design_passenger_payload_mass} + Design.cargo_mass {des_cargo} : Aricraft must be re-designed")

# set assumed cargo mass variables:
aviary_options.set_val(Aircraft.CrewPayload.CARGO_MASS, cargo, 'lbm')
aviary_options.set_val(Aircraft.CrewPayload.MAX_CARGO_MASS, max_cargo, 'lbm')
aviary_options.set_val(Aircraft.CrewPayload.Design.CARGO_MASS, des_cargo, 'lbm')

if Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS not in aviary_options:
flight_attendants_count = 0 # assume no passengers

Expand Down
2 changes: 1 addition & 1 deletion aviary/validation_cases/benchmark_tests/test_bench_GwGm.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def test_bench_GwGm_shooting(self):
)

assert_near_equal(
prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol
prob.get_val(Mission.Summary.RANGE, units='NM'), 3765.48, tolerance=rtol
)

assert_near_equal(
Expand Down
24 changes: 23 additions & 1 deletion aviary/variable_info/variable_meta_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,17 @@
add_meta_data(
Aircraft.CrewPayload.CARGO_MASS,
meta_data=_MetaData,
historical_name={"GASP": None,
"FLOPS": None,
"LEAPS1": None
},
units='lbm',
desc='total mass of as-flown cargo'
)

add_meta_data(
Aircraft.CrewPayload.MAX_CARGO_MASS,
meta_data=_MetaData,
historical_name={
"GASP": 'INGASP.WCARGO',
# ['WTS.WSP(36,2)', '~WEIGHT.WCARGO', '~WTSTAT.WSP(36,2)', '~INERT.WCARGO',],
Expand All @@ -707,7 +718,7 @@
],
},
units='lbm',
desc='total mass of cargo',
desc='Maximum mass of cargo'
)

add_meta_data(
Expand Down Expand Up @@ -787,6 +798,17 @@
default_value=0,
)

add_meta_data(
Aircraft.CrewPayload.Design.CARGO_MASS,
meta_data=_MetaData,
historical_name={"GASP": None,
"FLOPS": None,
"LEAPS1": None
},
units='lbm',
desc='total mass of cargo flown on design mission'
)

add_meta_data(
# Note user override
# - see also: Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER
Expand Down
2 changes: 2 additions & 0 deletions aviary/variable_info/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class CrewPayload:
FLIGHT_CREW_MASS_SCALER = 'aircraft:crew_and_payload:flight_crew_mass_scaler'

MASS_PER_PASSENGER = 'aircraft:crew_and_payload:mass_per_passenger'
MAX_CARGO_MASS = 'aircraft:crew_and_payload:max_cargo_mass'

MISC_CARGO = 'aircraft:crew_and_payload:misc_cargo'

Expand Down Expand Up @@ -135,6 +136,7 @@ class Design:
NUM_FIRST_CLASS = 'aircraft:crew_and_payload:design:num_first_class'
NUM_TOURIST_CLASS = 'aircraft:crew_and_payload:design:num_tourist_class'
NUM_PASSENGERS = 'aircraft:crew_and_payload:design:num_passengers'
CARGO_MASS = 'aircraft:crew_and_payload:design:cargo_mass'

class Design:
# These variables are values that do not fall into a particular aircraft
Expand Down
Loading