Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
20 changes: 10 additions & 10 deletions aviary/docs/theory_guide/gasp_based_bwb.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,16 @@
"# Testing Cell\n",
"\n",
"from aviary.api import Aircraft\n",
"from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import (\n",
"from aviary.subsystems.mass.gasp_based.equipment_and_operating_items import (\n",
" BWBACMass,\n",
" BWBFurnishingMass,\n",
" EquipAndUsefulLoadMassGroup,\n",
" UsefulLoadMassGroup,\n",
" EquipAndOperatingItemsMassGroup,\n",
" OperatingItemsMassGroup,\n",
")\n",
"from aviary.utils.doctape import get_variable_name, glue_variable\n",
"\n",
"glue_variable(get_variable_name(EquipAndUsefulLoadMassGroup), md_code=True)\n",
"glue_variable(get_variable_name(UsefulLoadMassGroup), md_code=True)\n",
"glue_variable(get_variable_name(EquipAndOperatingItemsMassGroup), md_code=True)\n",
"glue_variable(get_variable_name(OperatingItemsMassGroup), md_code=True)\n",
"glue_variable(get_variable_name(BWBACMass), md_code=True)\n",
"glue_variable(get_variable_name(BWBFurnishingMass), md_code=True)\n",
"\n",
Expand All @@ -150,11 +150,11 @@
"id": "8d5ec109",
"metadata": {},
"source": [
"### Equip And Useful Load\n",
"### Equip And Operating Items\n",
"\n",
" - {glue:md}`EquipAndUsefulLoadMassGroup` includes the computations of 19 items. Ideally, each of them should be done in its own component and one group has them all. This is a long time goal. For now, it is separated to two components `EquipMass` and {glue:md}`UsefulLoadMassGroup`. The air conditioning and furnishing masses are already singled out because they need to be modified for BWB.\n",
" - {glue:md}`EquipAndOperatingItemsMassGroup` includes the computations of 19 items. Ideally, each of them should be done in its own component and one group has them all. This is a long time goal. For now, it is separated to two components `EquipMass` and {glue:md}`OperatingItemsMassGroup`. The air conditioning and furnishing masses are already singled out because they need to be modified for BWB.\n",
" - A new variable {glue:md}`Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER` is added which corresponds to `CW(15)` in GASP. Its value is different for conventional aircraft and BWB.\n",
" - Two new components {glue:md}`BWBACMass` and {glue:md}`BWBFurnishingMass` are added to `equipment_and_useful_load.py`.\n",
" - Two new components {glue:md}`BWBACMass` and {glue:md}`BWBFurnishingMass` are added to `equipment_and_operating_items.py`.\n",
" - **Note:** GASP Fortran code has new updates that are not included in Aviary. We've updated Aviary for furnishing mass but other masses need to be checked.\n",
" - **Note:** `EquipMassPartialSum` has implementation errors for the computations of {glue:md}`Aircraft.APU.MASS`, {glue:md}`Aircraft.Avionics.MASS`, {glue:md}`Aircraft.AntiIcing.MASS`, {glue:md}`Aircraft.Furnishings.MASS`, and {glue:md}`Aircraft.Design.EMERGENCY_EQUIPMENT_MASS`. As a result, Aviary always uses user provided masses (not empirical formulas). We should use Aviary's feature of `overriding` to override those variables."
]
Expand Down Expand Up @@ -249,7 +249,7 @@
"\n",
"glue_variable(get_variable_name(Mission.TOTAL_FUEL), md_code=True)\n",
"\n",
"glue_variable(get_variable_name(Mission.USEFUL_LOAD), md_code=True)\n",
"glue_variable(get_variable_name(Mission.OPERATING_ITEMS_MASS), md_code=True)\n",
"glue_variable(get_variable_name(Aircraft.Wing.HIGH_LIFT_MASS), md_code=True)\n",
"glue_variable(get_variable_name(Aircraft.Fuel.FUEL_SYSTEM_MASS), md_code=True)\n",
"glue_variable(get_variable_name(Aircraft.Design.STRUCTURE_MASS), md_code=True)\n",
Expand All @@ -275,7 +275,7 @@
"\n",
"| Aviary |     | GASP |     | Observation |\n",
"| ------- | ------- | ------- | -------- | ------------- |\n",
"| {glue:md}`Mission.USEFUL_LOAD` | 5972 | WFUL | 5775 | different unit weight of pilots and attendents |\n",
"| {glue:md}`Mission.OPERATING_ITEMS_MASS` | 5972 | WFUL | 5775 | different unit weight of pilots and attendents |\n",
"| {glue:md}`Aircraft.Wing.HIGH_LIFT_MASS` | 972 | WHLDEV | 974 | In GASP, wing loading is a variable, but in Aviary, it is a constant |\n",
"| {glue:md}`Aircraft.Fuel.FUEL_SYSTEM_MASS` | 1316 | WFSS | 1281 | the mass in GASP is computed after engine sizing. |\n",
"| {glue:md}`Aircraft.Design.STRUCTURE_MASS` | 44471 | WST | 45623 | the mass in GASP is computed after engine sizing. |\n",
Expand Down
2 changes: 1 addition & 1 deletion aviary/docs/user_guide_unreviewed/subsystems/fuel.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"\n",
"\n",
"## Fuel Mass\n",
"The Fuel Mass breakdown is shown below. Note that UNUSABLE_FUEL_MASS is not accounted for in this mass and is instead book kept under USEFUL_LOAD which contributes to OPERATING_MASS see [mass subsystem for details](mass.ipynb).\n",
"The Fuel Mass breakdown is shown below. Note that UNUSABLE_FUEL_MASS is not accounted for in this mass and is instead book kept under OPERATING_ITEMS_MASS which contributes to OPERATING_MASS see [mass subsystem for details](mass.ipynb).\n",
"\n",
"- TOTAL_FUEL (mass)\n",
" - FUEL (mass)\n",
Expand Down
19 changes: 13 additions & 6 deletions aviary/docs/user_guide_unreviewed/subsystems/mass.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
" ZeroFuelMass,\n",
")\n",
"from aviary.subsystems.mass.gasp_based.design_load import DesignLoadGroup\n",
"from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import EquipAndUsefulLoadMassGroup\n",
"from aviary.subsystems.mass.gasp_based.equipment_and_operating_items import (\n",
" EquipAndOperatingItemsMassGroup,\n",
")\n",
"from aviary.subsystems.mass.gasp_based.fixed import FixedMassGroup\n",
"from aviary.subsystems.mass.gasp_based.wing import WingMassGroup\n",
"from aviary.utils.doctape import get_variable_name, glue_variable\n",
Expand Down Expand Up @@ -74,9 +76,9 @@
"st = split_by_capitals_and_underscores(get_variable_name(FixedMassGroup))\n",
"glue_variable(st, md_code=False)\n",
"glue_variable(get_variable_name(FixedMassGroup), md_code=False)\n",
"st = split_by_capitals_and_underscores(get_variable_name(EquipAndUsefulLoadMassGroup))\n",
"st = split_by_capitals_and_underscores(get_variable_name(EquipAndOperatingItemsMassGroup))\n",
"glue_variable(st, md_code=False)\n",
"glue_variable(get_variable_name(EquipAndUsefulLoadMassGroup), md_code=False)\n",
"glue_variable(get_variable_name(EquipAndOperatingItemsMassGroup), md_code=False)\n",
"st = split_by_capitals_and_underscores(get_variable_name(WingMassGroup))\n",
"glue_variable(st, md_code=False)\n",
"glue_variable(get_variable_name(WingMassGroup), md_code=False)"
Expand Down Expand Up @@ -136,7 +138,7 @@
"\n",
"### Operating Mass\n",
"Empty Mass, plus:\n",
"- **Useful Load**\n",
"- **Operating Items**\n",
" - Flight Crew\n",
" - Cabin Crew\n",
" - Unusable Fuel\n",
Expand All @@ -145,8 +147,10 @@
"\n",
"### Zero-Fuel Mass\n",
"Operating Mass, plus:\n",
"- Passengers\n",
"- Cargo\n",
"- **Payload Mass**\n",
" - Passengers\n",
" - Passenger Bags\n",
" - Cargo\n",
"\n",
"### Fuel Mass\n",
"[Total fuel burned during the mission and fuel reserves are explored here in more detail](fuel.ipynb).\n",
Expand All @@ -155,6 +159,9 @@
"Zero-Fuel Mass, plus:\n",
"- Fuel\n",
"\n",
"### Useful Load Mass\n",
"Gross Mass - Empty Mass\n",
"\n",
"## Using the Mass Subsystem\n",
"\n",
"The choice of which code's methods for mass estimate to use is set using the variable {glue:md}`setting_MASS_METHOD`. This variable can be specified in the Aviary input file or can be manually set when using the Level 2 or 3 interface.\n",
Expand Down
41 changes: 33 additions & 8 deletions aviary/subsystems/mass/flops_based/mass_summation.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ def setup(self):
)

self.add_subsystem(
'useful_load_mass', UsefulLoadMass(), promotes_inputs=['*'], promotes_outputs=['*']
'operating_items_mass',
OperatingItemsMass(),
promotes_inputs=['*'],
promotes_outputs=['*'],
)

self.add_subsystem(
Expand All @@ -71,6 +74,10 @@ def setup(self):
'zero_fuel_mass', ZeroFuelMass(), promotes_inputs=['*'], promotes_outputs=['*']
)

self.add_subsystem(
'useful_load_mass', UsefulLoadMass(), promotes_inputs=['*'], promotes_outputs=['*']
)


class EmpennageMass(om.ExplicitComponent):
def setup(self):
Expand Down Expand Up @@ -361,7 +368,7 @@ def compute(self, inputs, outputs):
)


class UsefulLoadMass(om.ExplicitComponent):
class OperatingItemsMass(om.ExplicitComponent):
def setup(self):
add_aviary_input(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS, units='lbm')
add_aviary_input(self, Aircraft.CrewPayload.CABIN_CREW_MASS, units='lbm')
Expand All @@ -370,10 +377,10 @@ def setup(self):
add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, units='lbm')
add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, units='lbm')

add_aviary_output(self, Mission.USEFUL_LOAD, units='lbm')
add_aviary_output(self, Mission.OPERATING_ITEMS_MASS, units='lbm')

def setup_partials(self):
self.declare_partials(Mission.USEFUL_LOAD, '*', val=1)
self.declare_partials(Mission.OPERATING_ITEMS_MASS, '*', val=1)

def compute(self, inputs, outputs):
cargo_container_mass = inputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS]
Expand All @@ -383,7 +390,7 @@ def compute(self, inputs, outputs):
pass_service_mass = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS]
unusable_fuel_mass = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS]

outputs[Mission.USEFUL_LOAD] = (
outputs[Mission.OPERATING_ITEMS_MASS] = (
cabin_crew_mass
+ flight_crew_mass
+ unusable_fuel_mass
Expand All @@ -396,18 +403,18 @@ def compute(self, inputs, outputs):
class OperatingMass(om.ExplicitComponent):
def setup(self):
add_aviary_input(self, Aircraft.Design.EMPTY_MASS, units='lbm')
add_aviary_input(self, Mission.USEFUL_LOAD, units='lbm')
add_aviary_input(self, Mission.OPERATING_ITEMS_MASS, units='lbm')

add_aviary_output(self, Mission.OPERATING_MASS, units='lbm')

def setup_partials(self):
self.declare_partials(Mission.OPERATING_MASS, '*', val=1)

def compute(self, inputs, outputs):
useful_load = inputs[Mission.USEFUL_LOAD]
operating_items_mass = inputs[Mission.OPERATING_ITEMS_MASS]
empty_mass = inputs[Aircraft.Design.EMPTY_MASS]

outputs[Mission.OPERATING_MASS] = empty_mass + useful_load
outputs[Mission.OPERATING_MASS] = empty_mass + operating_items_mass


class ZeroFuelMass(om.ExplicitComponent):
Expand All @@ -429,3 +436,21 @@ def compute(self, inputs, outputs):
operating_mass = inputs[Mission.OPERATING_MASS]

outputs[Mission.ZERO_FUEL_MASS] = operating_mass + pass_mass + bag_mass + cargo_mass


class UsefulLoadMass(om.ExplicitComponent):
def setup(self):
add_aviary_input(self, Aircraft.Design.GROSS_MASS, units='lbm')
add_aviary_input(self, Aircraft.Design.EMPTY_MASS, units='lbm')

add_aviary_output(self, Aircraft.Design.USEFUL_LOAD_MASS, units='lbm')

def setup_partials(self):
self.declare_partials(Aircraft.Design.USEFUL_LOAD_MASS, Aircraft.Design.GROSS_MASS, val=1)
self.declare_partials(Aircraft.Design.USEFUL_LOAD_MASS, Aircraft.Design.EMPTY_MASS, val=-1)

def compute(self, inputs, outputs):
gross_mass = inputs[Aircraft.Design.GROSS_MASS]
empty_mass = inputs[Aircraft.Design.EMPTY_MASS]

outputs[Aircraft.Design.USEFUL_LOAD_MASS] = gross_mass - empty_mass
58 changes: 32 additions & 26 deletions aviary/subsystems/mass/flops_based/payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
class PayloadGroup(om.Group):
def setup(self):
self.add_subsystem('cargo_mass', CargoMass(), promotes_inputs=['*'], promotes_outputs=['*'])
self.add_subsystem(
'pax_payload_mass', PaxPayloadMass(), promotes_inputs=['*'], promotes_outputs=['*']
)
self.add_subsystem(
'total_payload_mass', TotalPayload(), promotes_inputs=['*'], promotes_outputs=['*']
)
Expand All @@ -24,6 +27,7 @@ class TotalPayload(om.ExplicitComponent):
def setup(self):
add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm')
add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, units='lbm')

add_aviary_output(self, Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, units='lbm')

def setup_partials(self):
Expand All @@ -33,54 +37,56 @@ def setup_partials(self):
val=1.0,
)

def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
def compute(self, inputs, outputs):
cargo_mass = inputs[Aircraft.CrewPayload.CARGO_MASS]
passenger_payload_mass = inputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS]

outputs[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS] = passenger_payload_mass + cargo_mass


class CargoMass(om.ExplicitComponent):
"""Calculate the mass of any passengers, their baggage, and other cargo."""
"""Calculate the total cargo mass."""

def setup(self):
add_aviary_input(self, Aircraft.CrewPayload.WING_CARGO, units='lbm')
add_aviary_input(self, Aircraft.CrewPayload.MISC_CARGO, units='lbm')

add_aviary_output(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm')

def setup_partials(self):
self.declare_partials(Aircraft.CrewPayload.CARGO_MASS, '*', val=1.0)

def compute(self, inputs, outputs):
wing_cargo = inputs[Aircraft.CrewPayload.WING_CARGO]
misc_cargo = inputs[Aircraft.CrewPayload.MISC_CARGO]

outputs[Aircraft.CrewPayload.CARGO_MASS] = wing_cargo + misc_cargo


class PaxPayloadMass(om.ExplicitComponent):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like the PaxPayloadMass component is missing derivatives.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do I need derivatives if the component only uses 'options' which can't change and it doesn't have any 'inputs'? Do I need to declare that all the derivatives are '0'? Not sure on the best practice here...

"""Calculate the mass of passengers and their baggage."""

def initialize(self):
add_aviary_option(self, Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, units='lbm')
add_aviary_option(self, Aircraft.CrewPayload.MASS_PER_PASSENGER, units='lbm')
add_aviary_option(self, Aircraft.CrewPayload.NUM_PASSENGERS)

def setup(self):
add_aviary_input(self, Aircraft.CrewPayload.WING_CARGO, units='lbm')
add_aviary_input(self, Aircraft.CrewPayload.MISC_CARGO, units='lbm')
add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_MASS_TOTAL, units='lbm')
add_aviary_output(self, Aircraft.CrewPayload.BAGGAGE_MASS, units='lbm')
add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, units='lbm')
add_aviary_output(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm')

def setup_partials(self):
self.declare_partials(
Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.WING_CARGO, val=1.0
)

self.declare_partials(
Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.MISC_CARGO, val=1.0
)

def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
def compute(self, inputs, outputs):
passenger_count = self.options[Aircraft.CrewPayload.NUM_PASSENGERS]
mass_per_passenger, _ = self.options[Aircraft.CrewPayload.MASS_PER_PASSENGER]
baggage_mass_per_passenger, _ = self.options[
Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER
]

outputs[Aircraft.CrewPayload.PASSENGER_MASS_TOTAL] = mass_per_passenger * passenger_count

outputs[Aircraft.CrewPayload.BAGGAGE_MASS] = baggage_mass_per_passenger * passenger_count

outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = (
mass_per_passenger * passenger_count + baggage_mass_per_passenger * passenger_count
)

wing_cargo = inputs[Aircraft.CrewPayload.WING_CARGO]
misc_cargo = inputs[Aircraft.CrewPayload.MISC_CARGO]
pax_mass = mass_per_passenger * passenger_count
baggage_mass = baggage_mass_per_passenger * passenger_count
pax_payload = pax_mass + baggage_mass

outputs[Aircraft.CrewPayload.CARGO_MASS] = wing_cargo + misc_cargo
outputs[Aircraft.CrewPayload.PASSENGER_MASS_TOTAL] = pax_mass
outputs[Aircraft.CrewPayload.BAGGAGE_MASS] = baggage_mass
outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = pax_payload
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
from parameterized import parameterized

from aviary.subsystems.mass.flops_based.mass_summation import (
EmptyMass,
MassSummation,
OperatingMass,
PropulsionMass,
StructureMass,
)
from aviary.subsystems.propulsion.engine_deck import EngineDeck
Expand Down Expand Up @@ -92,6 +89,7 @@ def test_case(
Aircraft.Wing.MASS,
Aircraft.Propulsion.TOTAL_ENGINE_MASS,
Aircraft.Propulsion.TOTAL_MISC_MASS,
Aircraft.Design.GROSS_MASS,
],
output_keys=[
Aircraft.Design.EMPTY_MASS_MARGIN,
Expand All @@ -100,9 +98,10 @@ def test_case(
Aircraft.Design.SYSTEMS_AND_EQUIPMENT_MASS,
Aircraft.Design.EMPENNAGE_MASS,
Aircraft.Design.EMPTY_MASS,
Mission.USEFUL_LOAD,
Mission.OPERATING_ITEMS_MASS,
Mission.OPERATING_MASS,
Mission.ZERO_FUEL_MASS,
Aircraft.Design.USEFUL_LOAD_MASS,
],
version=Version.TRANSPORT_and_BWB,
atol=1e-10,
Expand Down Expand Up @@ -185,7 +184,7 @@ def test_case(self, case_name):
Aircraft.Design.SYSTEMS_AND_EQUIPMENT_MASS,
Aircraft.Design.EMPENNAGE_MASS,
Aircraft.Design.EMPTY_MASS,
Mission.USEFUL_LOAD,
Mission.OPERATING_ITEMS_MASS,
Mission.OPERATING_MASS,
Mission.ZERO_FUEL_MASS,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def setup(self):
)


class UsefulLoadMassGroup(om.Group):
class OperatingItemsMassGroup(om.Group):
def setup(self):
self.add_subsystem(
'cargo_containers',
Expand Down Expand Up @@ -182,7 +182,7 @@ def setup(self):
)


class EquipAndUsefulLoadMassGroup(om.Group):
class EquipAndOperatingItemsMassGroup(om.Group):
def initialize(self):
add_aviary_option(self, Aircraft.Design.TYPE)

Expand All @@ -206,7 +206,7 @@ def setup(self):

self.add_subsystem(
'useful',
UsefulLoadMassGroup(),
OperatingItemsMassGroup(),
promotes_inputs=['*'],
promotes_outputs=['*'],
)
Loading
Loading