diff --git a/aviary/docs/user_guide_unreviewed/subsystems/blended_wing_body_GASP.ipynb b/aviary/docs/user_guide_unreviewed/subsystems/blended_wing_body_GASP.ipynb index a175d75377..bd7e38d460 100644 --- a/aviary/docs/user_guide_unreviewed/subsystems/blended_wing_body_GASP.ipynb +++ b/aviary/docs/user_guide_unreviewed/subsystems/blended_wing_body_GASP.ipynb @@ -38,10 +38,12 @@ "from aviary.utils.doctape import get_variable_name, glue_variable\n", "\n", "glue_variable(get_variable_name(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.Fuselage.SEAT_WIDTH), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.Fuselage.NUM_AISLES), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.Fuselage.AISLE_WIDTH), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.SEAT_WIDTH_FIRST), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_PASSENGERS), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS), md_code=False)\n", "glue_variable(get_variable_name(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP), md_code=False)\n", @@ -71,8 +73,6 @@ "| Parameters | Values | Units |\n", "| ---------- | ------ | ----- |\n", "| length of first class lav, galley & closet | 8.0 | ft |\n", - "| first class seat width | 28.0 | inch |\n", - "| first class seat pitch | 36.0 | inch |\n", "| Number of aisles in first class | 2 | unitless |\n", "| First class aisle width | 24.0 | inch |\n", "| Length of first class/economy class aisle | 5.0 | ft |\n", @@ -85,10 +85,12 @@ "\n", "| Parameters | Units |\n", "| ---------- | ----- |\n", - "| {glue:md}`Aircraft.Fuselage.SEAT_WIDTH` | inch |\n", + "| {glue:md}`Aircraft.Fuselage.SEAT_WIDTH_ECONOMY` | inch |\n", "| {glue:md}`Aircraft.Fuselage.NUM_AISLES` | unitless |\n", "| {glue:md}`Aircraft.Fuselage.AISLE_WIDTH` | inch |\n", + "| {glue:md}`Aircraft.Fuselage.SEAT_WIDTH_FIRST` | inch |\n", "| {glue:md}`Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY` | inch |\n", + "| {glue:md}`Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST` | inch |\n", "| {glue:md}`Aircraft.CrewPayload.Design.NUM_PASSENGERS` | unitless |\n", "| {glue:md}`Aircraft.CrewPayload.Design.NUM_FIRST_CLASS` | unitless |\n", "| {glue:md}`Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP` | deg |\n", @@ -104,6 +106,10 @@ "\n", "![Fuselage size](./images/BWB_GASP_Fuselage_Geometry.png)\n", "\n", + "Different from GASP, we allow business class between first class and economy class.\n", + "\n", + "The layout algorithm is just an estimate. The output layout may not obey all the constraints (e.g. the number of first class passengers) but should not be too far away.\n", + "\n", "### Wing Fuel Volume Computation\n", "\n", "For the wing fuel volume, we first compute its value assuming no wing fold structure. In\n", @@ -217,7 +223,8 @@ "\n", "from aviary.api import Aircraft, Dynamic\n", "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", - "from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces\n", + "\n", + "# from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces\n", "from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero\n", "from aviary.subsystems.aerodynamics.gasp_based.gaspaero import (\n", " BWBBodyLiftCurveSlope,\n", @@ -347,7 +354,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "base", "language": "python", "name": "python3" }, @@ -361,7 +368,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide_unreviewed/subsystems/images/BWB_GASP_Fuselage_Geometry.png b/aviary/docs/user_guide_unreviewed/subsystems/images/BWB_GASP_Fuselage_Geometry.png index 717e7a7b63..6a158ec38d 100644 Binary files a/aviary/docs/user_guide_unreviewed/subsystems/images/BWB_GASP_Fuselage_Geometry.png and b/aviary/docs/user_guide_unreviewed/subsystems/images/BWB_GASP_Fuselage_Geometry.png differ diff --git a/aviary/interface/test/sizing_results_for_test.json b/aviary/interface/test/sizing_results_for_test.json index 760aa600f8..061da7c55b 100644 --- a/aviary/interface/test/sizing_results_for_test.json +++ b/aviary/interface/test/sizing_results_for_test.json @@ -1124,6 +1124,18 @@ "unitless", "" ], + [ + "aircraft:fuselage:seat_width_economy", + 20.0, + "inch", + "" + ], + [ + "aircraft:fuselage:seat_width_first", + 25.0, + "inch", + "" + ], [ "mission:gross_mass", 175400.0, diff --git a/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv index 63544bdfd8..473ff7612a 100644 --- a/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv +++ b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv @@ -1,5 +1,6 @@ # created unknown date # FLOPS-derived aircraft input deck converted from N3CC_generic_low_speed_polars_FLOPSinp.txt +# business class seats are included. Fuselage layout will be different from FLOPS. # Input Values aircraft:air_conditioning:mass_scaler,0.98094,unitless diff --git a/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv index 8ad3688b2e..87d14a05b2 100644 --- a/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv +++ b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv @@ -71,7 +71,7 @@ aircraft:fuselage:num_aisles,3,unitless aircraft:fuselage:pilot_compartment_length,7.5,ft aircraft:fuselage:pressure_differential,10,psi aircraft:fuselage:pressurized_width_additional,0,ft -aircraft:fuselage:seat_width,21,inch +aircraft:fuselage:seat_width_economy,21,inch aircraft:fuselage:tail_fineness,1.75,unitless aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.2,unitless aircraft:fuselage:wetted_area_scaler,1.0001,unitless diff --git a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv index dc7697ca88..dd070e1497 100644 --- a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv @@ -56,7 +56,7 @@ aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless diff --git a/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv b/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv index ce731fc60f..1802b3aa4f 100644 --- a/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv +++ b/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv @@ -96,7 +96,7 @@ aircraft:fuselage:nose_fineness, 1, unitless aircraft:fuselage:num_aisles, 1, unitless aircraft:fuselage:pilot_compartment_length, 10.6, ft aircraft:fuselage:pressure_differential, 6.55, psi -aircraft:fuselage:seat_width, 18, inch +aircraft:fuselage:seat_width_economy, 18, inch aircraft:fuselage:tail_fineness, 2.9, unitless aircraft:fuselage:wetted_area_scaler, 1, unitless diff --git a/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv index 270cb826e2..da2b662cb0 100644 --- a/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv +++ b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv @@ -56,7 +56,7 @@ aircraft:fuselage:nose_fineness,0.845,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,11.7,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,24,inch +aircraft:fuselage:seat_width_economy,24,inch aircraft:fuselage:tail_fineness,3.368,unitless aircraft:fuselage:wetted_area_scaler,1,unitless aircraft:horizontal_tail:aspect_ratio,4.26,unitless diff --git a/aviary/subsystems/geometry/flops_based/fuselage.py b/aviary/subsystems/geometry/flops_based/fuselage.py index efc0aa749d..a88448d1ac 100644 --- a/aviary/subsystems/geometry/flops_based/fuselage.py +++ b/aviary/subsystems/geometry/flops_based/fuselage.py @@ -7,7 +7,7 @@ from aviary.utils.math import smooth_int_tanh, d_smooth_int_tanh from aviary.variable_info.enums import Verbosity from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission, Settings +from aviary.variable_info.variables import Aircraft, Settings class FuselagePrelim(om.ExplicitComponent): @@ -191,13 +191,20 @@ class DetailedCabinLayout(om.ExplicitComponent): """ def initialize(self): + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_BUSINESS) + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_FIRST) + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_ECONOMY) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_ECONOMY_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS) add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST) add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY) add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) def setup(self): add_aviary_input(self, Aircraft.Design.RANGE, units='NM') @@ -210,36 +217,80 @@ def setup(self): self.declare_partials('*', '*', method='fd', form='forward') def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + num_first_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + num_business_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] num_economy_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_ECONOMY_CLASS] fuselage_multiplier = 1.0 num_seat_abreast_first = self.options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST] + num_seat_abreast_business = self.options[ + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS + ] num_seat_abreast_economy = self.options[ Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY ] + # The 200 was derived from B757 - the largest single aisle western desig. if num_economy_class_pax > 200: if num_seat_abreast_economy <= 0: num_seat_abreast_economy = 8 - if num_seat_abreast_first > 0 and num_seat_abreast_first <= 0: + if verbosity > Verbosity.BRIEF: + print('Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY = 8') + if num_first_class_pax > 0 and num_seat_abreast_first <= 0: num_seat_abreast_first = num_seat_abreast_economy - 2 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST = ' + f'{num_seat_abreast_first}' + ) + if num_business_class_pax > 0 and num_seat_abreast_business <= 0: + num_seat_abreast_business = num_seat_abreast_economy - 2 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BASINESS = ' + f'{num_seat_abreast_business}' + ) if num_seat_abreast_first <= 0 and num_first_class_pax > 0: num_seat_abreast_first = 4 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST = ' + f'{num_seat_abreast_first}' + ) if num_seat_abreast_economy <= 0 and num_economy_class_pax > 0: num_seat_abreast_economy = 6 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY = ' + f'{num_seat_abreast_economy}' + ) + if num_seat_abreast_business <= 0 and num_business_class_pax > 0: + num_seat_abreast_business = 5 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS = ' + f'{num_seat_abreast_business}' + ) # Though these are not user definable, the values here are typical for most transport aisle_width_first_class = 20.0 # inch + aisle_width_business_class = 19.0 # inch aisle_width_economy_class = 18.0 # inch # If there are less than 60 passengers on board, then the aisle should be slightly narrow. - # Also, if the number of passengers abreast was not specified, then set it to 5 as 6 is too much - # for a typical short range transport. + # Also, if the number of passengers abreast was not specified, then set it to 5 because 6 + # is too much for a typical short range transport. if num_economy_class_pax < 60: if num_seat_abreast_economy <= 0: num_seat_abreast_economy = 5 + if verbosity > Verbosity.BRIEF: + print( + 'Set Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY = ' + f'{num_seat_abreast_economy}' + ) aisle_width_economy_class = 15.0 if num_seat_abreast_economy > 6: @@ -252,18 +303,29 @@ def compute(self, inputs, outputs): # 4 or 6 as shown below that we are working with a widebody aircraft. if num_seat_abreast_first > 4: aisle_width_first_class = 18.0 + if num_seat_abreast_business > 5: + aisle_width_first_class = 17.0 if num_seat_abreast_economy > 6: aisle_width_economy_class = 15.0 seat_pitch_first = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST][0] if seat_pitch_first <= 0 and num_first_class_pax > 0: seat_pitch_first = 38.0 # inch + if verbosity > Verbosity.BRIEF: + print('Set Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST = 38.0 inches') + seat_pitch_business = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS][0] + if seat_pitch_business <= 0 and num_business_class_pax > 0: + seat_pitch_business = 36.0 # inch + if verbosity > Verbosity.BRIEF: + print('Set Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS = 36.0 inches') seat_pitch_economy = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY][0] if seat_pitch_economy <= 0 and num_economy_class_pax > 0: seat_pitch_economy = 34.0 # inch + if verbosity > Verbosity.BRIEF: + print('Set Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY = 34.0 inches') # set maximum number of galleys based on statistics (this block is not from FLOPS) - num_pax = num_first_class_pax + num_economy_class_pax + num_pax = num_first_class_pax + num_business_class_pax + num_economy_class_pax if num_pax < 80: max_galleys = 1 max_lav = 1 @@ -311,10 +373,12 @@ def compute(self, inputs, outputs): # The above settings are necessary because FLOPS didn't cover all the scenarios. # They will be over written if FLOPS covered a particular scenario as we see below. + num_first_business_pax = num_first_class_pax + num_business_class_pax + # Set constraints on the maximum number of galleys and other items so that we don't have # a flying kitchen or closet or whatever. # Note: Some of these may need relaxing for larger aircraft. - if num_first_class_pax == 0: + if num_first_business_pax == 0: design_range = inputs[Aircraft.Design.RANGE] if design_range < 1250.0: max_lav = 2 @@ -325,7 +389,7 @@ def compute(self, inputs, outputs): max_galleys = 2 max_closets = 2 - if num_first_class_pax == 0 and num_economy_class_pax < 110: + if num_first_business_pax == 0 and num_economy_class_pax < 110: max_lav = 1 max_galleys = 1 max_closets = 1 @@ -339,17 +403,17 @@ def compute(self, inputs, outputs): max_galleys = 8 max_closets = 8 - if num_first_class_pax > 0 and num_seat_abreast_economy < 8: + if num_first_business_pax > 0 and num_seat_abreast_economy < 8: fuselage_multiplier = 0.95 # Calculate the number of galleys, lavatories and closets - num_galleys = int(1 + ((num_first_class_pax + num_economy_class_pax) / 100)) + num_galleys = int(1 + (num_pax / 100)) if num_galleys > max_galleys: num_galleys = max_galleys - num_lavas = int(1 + (num_economy_class_pax / 60)) + int(1 + (num_first_class_pax / 100)) + num_lavas = int(1 + (num_economy_class_pax / 60)) + int(1 + (num_first_business_pax / 100)) if num_lavas > max_lav: num_lavas = max_lav - num_closets = int(1 + (num_first_class_pax / 30)) + int(1 + (num_economy_class_pax / 60)) + num_closets = int(1 + (num_first_business_pax / 30)) + int(1 + (num_economy_class_pax / 60)) if num_closets > max_closets: num_closets = max_closets @@ -358,9 +422,13 @@ def compute(self, inputs, outputs): num_engines = self.options[Aircraft.Engine.NUM_ENGINES][0] eng_flag = num_engines - 2 * int(num_engines / 2) # a center mounted engine if 1. first_class_len = num_first_class_pax * seat_pitch_first / num_seat_abreast_first + business_class_len = ( + num_business_class_pax * seat_pitch_business / num_seat_abreast_business + ) economy_class_len = num_economy_class_pax * seat_pitch_economy / num_seat_abreast_economy pax_compart_length = ( first_class_len + + business_class_len + (num_galleys + num_lavas) * 36.0 + economy_class_len + num_closets * 12.0 @@ -378,17 +446,32 @@ def compute(self, inputs, outputs): # Calculate the number of rows of each class of passenger (not needed) if num_first_class_pax > 0: num_rows_first = int(np.ceil(num_first_class_pax / num_seat_abreast_first)) + if num_business_class_pax > 0: + num_rows_business = int(np.ceil(num_business_class_pax / num_seat_abreast_business)) if num_economy_class_pax > 0: num_rows_economy = int(np.ceil(num_economy_class_pax / num_seat_abreast_economy)) # Calculate the fuselage width of the passenger seats - width_first_class = ( - num_aisles * aisle_width_first_class + num_seat_abreast_first * 20.0 - ) / 12.0 + seat_width_first = self.options[Aircraft.Fuselage.SEAT_WIDTH_FIRST][0] + seat_width_business = self.options[Aircraft.Fuselage.SEAT_WIDTH_BUSINESS][0] + seat_width_economy = self.options[Aircraft.Fuselage.SEAT_WIDTH_ECONOMY][0] + if num_first_class_pax > 0: + width_first_class = ( + num_aisles * aisle_width_first_class + num_seat_abreast_first * seat_width_first + ) / 12.0 + else: + width_first_class = 0.0 + if num_business_class_pax > 0: + width_business_class = ( + num_aisles * aisle_width_business_class + + num_seat_abreast_business * seat_width_business + ) / 12.0 + else: + width_business_class = 0.0 width_economy_class = ( - num_aisles * aisle_width_economy_class + num_seat_abreast_economy * 25.0 + num_aisles * aisle_width_economy_class + num_seat_abreast_economy * seat_width_economy ) / 12.0 - width_fuselage = np.maximum(width_first_class, width_economy_class) * 1.06 + width_fuselage = max(width_first_class, width_economy_class, width_business_class) * 1.06 outputs[Aircraft.Fuselage.MAX_WIDTH] = width_fuselage outputs[Aircraft.Fuselage.MAX_HEIGHT] = width_fuselage + 0.9 @@ -460,7 +543,7 @@ def compute(self, inputs, outputs): if length <= 0.0: raise ValueError( - f'Aircraft.Fuselage.LENGTH must be positive to use simple cabin layout.' + 'Aircraft.Fuselage.LENGTH must be positive to use simple cabin layout.' ) if max_width <= 0.0: raise ValueError( diff --git a/aviary/subsystems/geometry/flops_based/test/test_fuselage.py b/aviary/subsystems/geometry/flops_based/test/test_fuselage.py index 3983328a91..a0c56b9b9c 100644 --- a/aviary/subsystems/geometry/flops_based/test/test_fuselage.py +++ b/aviary/subsystems/geometry/flops_based/test/test_fuselage.py @@ -57,6 +57,8 @@ def test_case1(self): # options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, units='unitless') # options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, units='unitless') options.set_val(Aircraft.Engine.NUM_ENGINES, [2], units='unitless') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 25, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20, units='inch') prob.model.add_subsystem( 'layout', DetailedCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] @@ -71,10 +73,50 @@ def test_case1(self): assert_near_equal(fuselage_length, 148.37731944, tolerance=1e-9) fuselage_width = prob.get_val(Aircraft.Fuselage.MAX_WIDTH) - assert_near_equal(fuselage_width, 14.84, tolerance=1e-9) + assert_near_equal(fuselage_width, 12.19, tolerance=1e-9) fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) - assert_near_equal(fuselage_height, 15.74, tolerance=1e-9) + assert_near_equal(fuselage_height, 13.09, tolerance=1e-9) + + def test_case2(self): + """with business class (modeled from Boeing 777-300ER)""" + prob = self.prob + options = self.aviary_options = AviaryValues() + options.set_val(Settings.VERBOSITY, 1, units='unitless') + + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 56) + options.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, 78) + options.set_val(Aircraft.CrewPayload.Design.NUM_ECONOMY_CLASS, 330) + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, 4) + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, 6) + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 10) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 83, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 62, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 32, units='inch') + options.set_val(Aircraft.Engine.NUM_ENGINES, [2], units='unitless') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 22, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_BUSINESS, 21, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 18, units='inch') + + prob.model.add_subsystem( + 'layout', DetailedCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Design.RANGE, val=7370.0, units='NM') + prob.run_model() + + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 254.26333333, tolerance=1e-9) + + fuselage_length = prob.get_val(Aircraft.Fuselage.LENGTH) + assert_near_equal(fuselage_length, 294.26333333, tolerance=1e-9) + + fuselage_width = prob.get_val(Aircraft.Fuselage.MAX_WIDTH) + assert_near_equal(fuselage_width, 18.55, tolerance=1e-9) + + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 19.45, tolerance=1e-9) class BWBSimpleCabinLayoutTest(unittest.TestCase): @@ -302,4 +344,7 @@ def test_case1(self): if __name__ == '__main__': - unittest.main() + # unittest.main() + test = DetailedCabinLayoutTest() + test.setUp() + test.test_case2() diff --git a/aviary/subsystems/geometry/gasp_based/fuselage.py b/aviary/subsystems/geometry/gasp_based/fuselage.py index 08d592f2df..94b2fd71d7 100644 --- a/aviary/subsystems/geometry/gasp_based/fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/fuselage.py @@ -16,7 +16,7 @@ def initialize(self): add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY) add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, units='inch') - add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch') + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, units='inch') add_aviary_option(self, Settings.VERBOSITY) def setup(self): @@ -44,7 +44,7 @@ def compute(self, inputs, outputs): options = self.options verbosity = options[Settings.VERBOSITY] seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY] - seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_ECONOMY] num_aisle = options[Aircraft.Fuselage.NUM_AISLES] aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] PAX = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] @@ -262,7 +262,7 @@ def initialize(self): add_aviary_option(self, Aircraft.Fuselage.AISLE_WIDTH, units='inch') add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES) add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY) - add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch') + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, units='inch') add_aviary_option(self, Settings.VERBOSITY) def setup(self): @@ -318,7 +318,7 @@ def compute(self, inputs, outputs): verbosity = options[Settings.VERBOSITY] seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY] - seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_ECONOMY] num_aisle = options[Aircraft.Fuselage.NUM_AISLES] aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] PAX = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] @@ -347,7 +347,7 @@ def compute_partials(self, inputs, J): options = self.options seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY] - seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_ECONOMY] num_aisle = options[Aircraft.Fuselage.NUM_AISLES] aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] @@ -384,24 +384,23 @@ class BWBCabinLayout(om.ExplicitComponent): """layout of passenger cabin for BWB.""" def initialize(self): - add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch', desc='INGASP.WS') + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_FIRST, units='inch', desc='WS_FC') + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH_BUSINESS, units='inch') + add_aviary_option( + self, Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, units='inch', desc='INGASP.WS' + ) add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES, units='unitless', desc='INGASP.AS') add_aviary_option(self, Aircraft.Fuselage.AISLE_WIDTH, units='inch', desc='INGASP.WAS') add_aviary_option( self, Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, units='inch', desc='PS_FC' ) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS, units='inch') add_aviary_option( self, Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, units='inch', desc='INGASP.PS' ) - add_aviary_option( - self, Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless', desc='INGASP.PAX' - ) - add_aviary_option( - self, - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, - units='unitless', - desc='equiv INGASP.PCT_FC', - ) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS, desc='INGASP.PAX') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, desc='INGASP.PCT_FC') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) add_aviary_option(self, Settings.VERBOSITY) def setup(self): @@ -425,20 +424,24 @@ def compute(self, inputs, outputs): rad2deg = 180.0 / np.pi # Hard code variables in GASP: - FC_lav_galley_length = 8.0 # EL_FLGC: length of first class lav, galley & closet, ft - FC_seat_width = 28.0 # WS_FC: first class seat width, inch - FC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST] + FC_lav_galley_length = 8.0 # EL_FLGC: length of first class lavatory, galley & closet, ft FC_num_aisles = 2 # AS_FC: num of aisles in first class FC_aisle_width = 24.0 # WAS_FC: First class aisle width, inch - length_FC_to_TC = 5.0 # Length of first class/economy class aisle, ft - TC_num_pax_per_lav = 78 # NLAVTC: economy class passengers per lav - TC_lav_width = 42.0 # WIDLAV: Lav width, inches, in FLOPS, WIDTHL + FC_seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_FIRST] + FC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST] + + BC_lav_galley_length = 8.0 + BC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS] + BC_seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_BUSINESS] + + TC_num_pax_per_lav = 78 # NLAVTC: economy class passengers per lavatory + TC_lav_width = 42.0 # WIDLAV: lavatory width, inches, in FLOPS, WIDTHL TC_galley_area_per_pax = 0.15 # AGAL_TC: economy class galley area per passenger, ft**2 # If there is no first class cabin, please set NUM_FIRST_CLASS = 0. TC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY] - seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] - if seat_width <= 0.0: + TC_seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH_ECONOMY] + if TC_seat_width <= 0.0: raise ValueError('fuselage seat width must be positive.') aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] num_aisles = options[Aircraft.Fuselage.NUM_AISLES] @@ -450,21 +453,28 @@ def compute(self, inputs, outputs): sweep_FB = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP][0] pax = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] pax_FC = options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + pax_BC = options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] if pax_FC <= 0: - if verbosity > Verbosity.BRIEF: + if verbosity >= Verbosity.DEBUG: print('Warning: No first class passengers or cabins are included.') - if pax_FC > pax: + if pax_BC <= 0: + if verbosity >= Verbosity.DEBUG: + print('Warning: No business class passengers or cabins are included.') + if (pax_FC + pax_BC) > pax: raise ValueError( 'Number of first class passengers must not exceed the total number of passengers.' ) - pax_TC = pax - pax_FC + pax_TC = pax - pax_FC - pax_BC nose_length = inputs['nose_length'][0] pilot_com_length = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH][0] if pax_FC > 0: fwd_pax_fuselage_station = nose_length + pilot_com_length + FC_lav_galley_length else: - fwd_pax_fuselage_station = nose_length + pilot_com_length + if pax_BC > 0: + fwd_pax_fuselage_station = nose_length + pilot_com_length + BC_lav_galley_length + else: + fwd_pax_fuselage_station = nose_length + pilot_com_length # First Class length_FC_by_row = [] # length in first class, ft @@ -498,22 +508,90 @@ def compute(self, inputs, outputs): EL_FC_last_row = length_FC_by_row[Idx_row_FC - 1] EL_FC_ptr = length_FC_by_row[Idx_row_FC - 1] - sum_num_seats_FC = pax_FC + # sum_num_seats_FC = pax_FC + if sum_num_seats_FC > pax_FC: + if verbosity >= Verbosity.DEBUG: + print( + f'Number of seats in first class {sum_num_seats_FC} ' + f'is above the design limit {pax_FC}.' + ) else: - # If not first class - EL_FC_last_row = 0 + # If no first class + # EL_FC_last_row = 0 + pass - # First Class/Economy Class Aisle + # First Class/Business Class Aisle if pax_FC > 0: - EL_TC_ptr = EL_FC_last_row + FC_seat_pitch / 12.0 + EL_BC_ptr = EL_FC_last_row + FC_seat_pitch / 12.0 else: - EL_TC_ptr = fwd_pax_fuselage_station + EL_BC_ptr = fwd_pax_fuselage_station - # Economy Class - if pax_FC > 0: - EL_TC_ptr = EL_TC_ptr + length_FC_to_TC - TC_seat_pitch / 12.0 + # Business Class + length_FC_to_BC = 5.0 # Length of first class/business class aisle, ft + + if pax_BC > 0: + EL_BC_ptr = EL_BC_ptr + length_FC_to_BC - BC_seat_pitch / 12.0 + else: + # EL_BC_ptr = EL_BC_ptr - BC_seat_pitch / 12.0 + pass + + if pax_BC > 0: + length_BC_by_row = [] # length in business class, ft + width_BC_by_row = [] # width in business class, ft + num_seats_BC_by_row = [] # num of seats in business class + sum_num_seats_BC = 0 + Idx_row_BC = -1 + while sum_num_seats_BC < pax_BC: + Idx_row_BC = Idx_row_BC + 1 + len = EL_BC_ptr + BC_seat_pitch / 12.0 + length_BC_by_row.append(len) + wid = 2.0 * length_BC_by_row[Idx_row_BC] / np.tan(sweep_FB / rad2deg) + wid = np.minimum(wid, cabin_width) + width_BC_by_row.append(wid) + width_aisle = num_aisles * aisle_width / 12.0 + num = int((width_BC_by_row[Idx_row_BC] - width_aisle) / (BC_seat_width / 12.0)) + num_seats_BC_by_row.append(num) + prev_sum_num_seats_BC = sum_num_seats_BC + sum_num_seats_BC = sum_num_seats_BC + num_seats_BC_by_row[Idx_row_BC] + EL_BC_ptr = length_BC_by_row[Idx_row_BC] + + # Last row of business class + EL_BC_last_row = length_BC_by_row[Idx_row_BC] + num_seats_last_row = pax_BC - prev_sum_num_seats_BC + # If only one seat in last row, delete last row & assume seat located forward + if num_seats_last_row < 2: + EL_BC_last_row = length_BC_by_row[Idx_row_BC - 1] + EL_BC_ptr = length_BC_by_row[Idx_row_BC - 1] + + # sum_num_seats_BC = pax_BC + if sum_num_seats_BC > pax_BC: + if verbosity >= Verbosity.DEBUG: + print( + f'Number of seats in business class {sum_num_seats_BC} ' + f'is above the design limit {pax_BC}.' + ) + else: + # If no business class + # EL_BC_last_row = 0 + pass + + # Business Class/economy Class Aisle + if pax_BC > 0: + EL_TC_ptr = EL_BC_last_row + BC_seat_pitch / 12.0 else: - EL_TC_ptr = EL_TC_ptr - TC_seat_pitch / 12.0 + EL_TC_ptr = EL_BC_ptr + + length_BC_to_TC = 5.0 # Length of business class/economy class aisle, ft + + if pax_BC > 0: + EL_TC_ptr = EL_BC_ptr + length_BC_to_TC - TC_seat_pitch / 12.0 + else: + if pax_FC > 0: + EL_TC_ptr = EL_TC_ptr + length_FC_to_BC - TC_seat_pitch / 12.0 + else: + EL_TC_ptr = EL_TC_ptr - TC_seat_pitch / 12.0 + + # Economy Class length_TC_by_row = [] # length in economy class, ft width_TC_by_row = [] # width in economy class, ft num_seats_TC_by_row = [] # num of seats in economy class @@ -527,7 +605,7 @@ def compute(self, inputs, outputs): wid = np.minimum(wid, cabin_width) width_TC_by_row.append(wid) width_aisle = num_aisles * aisle_width / 12.0 - num = int((width_TC_by_row[Idx_row_TC] - width_aisle) / (seat_width / 12.0)) + num = int((width_TC_by_row[Idx_row_TC] - width_aisle) / (TC_seat_width / 12.0)) num_seats_TC_by_row.append(num) prev_num_seats_TC = sum_num_seats_TC sum_num_seats_TC = sum_num_seats_TC + num_seats_TC_by_row[Idx_row_TC] @@ -537,7 +615,7 @@ def compute(self, inputs, outputs): # last row in economy class: find number of seats in last row num_seats_last_row = sum_num_seats_TC - prev_num_seats_TC # find width available for last row for lavs/galleys (Assumes Steward's seat in TC aisle) - width_last_row = num_seats_last_row * seat_width / 12.0 + width_last_row = num_seats_last_row * TC_seat_width / 12.0 width_aisle = num_aisles * aisle_width / 12.0 wid_last_row_avail = cabin_width - width_last_row - width_aisle # find number of economy class lavs and aft galley (galley width = lav width) @@ -552,6 +630,13 @@ def compute(self, inputs, outputs): # add additional row for lavs & galleys to last row EL_AFT = length_TC_by_row[Idx_row_TC] + TC_seat_pitch / 12.0 + TC_lav_width / 12.0 + if sum_num_seats_TC > pax_TC: + if verbosity >= Verbosity.DEBUG: + print( + f'Number of seats in economy class {sum_num_seats_TC} ' + f'is above the design limit {pax_TC}.' + ) + outputs['fuselage_station_aft'] = EL_AFT diff --git a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py index efae73adb8..0a34708be1 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py @@ -30,7 +30,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 6) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( @@ -66,7 +66,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( @@ -179,7 +179,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 6) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( @@ -230,7 +230,9 @@ def setUp(self): options.set_val( Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch' ) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value + options.set_val( + Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch' + ) # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( @@ -287,7 +289,9 @@ def setUp(self): options.set_val( Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch' ) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value + options.set_val( + Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch' + ) # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( @@ -344,7 +348,9 @@ def setUp(self): options.set_val( Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch' ) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value + options.set_val( + Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch' + ) # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( @@ -395,7 +401,7 @@ def setUp(self): self.aviary_options = AviaryValues() self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 18) - self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 21, units='inch') self.aviary_options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) self.aviary_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') self.aviary_options.set_val( @@ -437,14 +443,15 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) +@use_tempdirs class BWBLayoutTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() self.aviary_options = AviaryValues() - self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 18) - self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 21.0, units='inch') + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 28.0, units='inch') self.aviary_options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) self.aviary_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') self.aviary_options.set_val( @@ -453,7 +460,7 @@ def setUp(self): self.aviary_options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 150) self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) - self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + self.aviary_options.set_val(Settings.VERBOSITY, 3, units='unitless') self.prob.model.add_subsystem('bwb_cabin_layout', BWBCabinLayout(), promotes=['*']) @@ -474,7 +481,7 @@ def setUp(self): self.prob.setup() def test_case1(self): - """Testing GASP data case.""" + """Testing GASP data case: first class + economy class""" self.prob.run_model() tol = 1e-7 @@ -493,7 +500,7 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) def test_case2(self): - """Testing 0 First Class case.""" + """Testing case: economy class only""" self.aviary_options.set_val( Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, val=0, @@ -507,17 +514,19 @@ def test_case2(self): tol = 1e-7 assert_near_equal(self.prob['fuselage_station_aft'], 51.25449, tol) - partial_data = self.prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method='fd', - minimum_step=1e-12, - abs_err_tol=5.0e-4, - rel_err_tol=5.0e-5, + def test_case3(self): + """Testing case: first class + business class + economy class""" + self.aviary_options.set_val( + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, val=20, units='unitless' ) - assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_BUSINESS, val=25.0, units='inch') + setup_model_options(self.prob, self.aviary_options) + self.prob.setup() + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['fuselage_station_aft'], 59.83782665, tol) class BWBFuselageParameters2TestCase(unittest.TestCase): @@ -611,7 +620,8 @@ class BWBFuselageGroupTestCase(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 18) - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 28, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 21, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 32, units='inch') diff --git a/aviary/subsystems/geometry/gasp_based/test/test_size_group.py b/aviary/subsystems/geometry/gasp_based/test/test_size_group.py index 598b11b3d4..00197cfacb 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_size_group.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_size_group.py @@ -22,7 +22,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 6) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, val=0.0003097, units='unitless') self.prob = om.Problem() @@ -144,7 +144,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 6) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, val=0.00030975, units='unitless') self.prob = om.Problem() @@ -279,7 +279,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, val=0.00030975, units='unitless') @@ -412,7 +412,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, val=0.00030975, units='unitless') self.prob = om.Problem() @@ -543,12 +543,13 @@ def setUp(self): ) options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 28, units='inch') options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 18) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 32, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 21, units='inch') options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) self.prob = om.Problem() diff --git a/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py b/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py index d13f6df46a..a588307759 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py +++ b/aviary/subsystems/mass/gasp_based/test/test_mass_premission.py @@ -146,7 +146,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.00030975, units='unitless') @@ -498,7 +498,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.00030975, units='unitless') @@ -841,7 +841,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.00030975, units='unitless') @@ -1192,7 +1192,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.00030975, units='unitless') @@ -1538,7 +1538,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.00030975, units='unitless') @@ -1885,7 +1885,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 29, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.165, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.0003482075, units='unitless') @@ -2257,7 +2257,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 44.2, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.163, units='unitless') options.set_val(Aircraft.Engine.INLET_AREA_COEFFICIENT, 0.000474, units='unitless') @@ -2625,7 +2625,7 @@ def setUp(self): options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 44.2, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.163, units='unitless') options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') @@ -3006,12 +3006,13 @@ def setUp(self): options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 28, units='inch') options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_ECONOMY, 18) options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_ECONOMY, 32, units='inch') - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 21, units='inch') options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) # options from MassPremission options.set_val(Aircraft.Design.CRUISE_ALTITUDE, val=41000, units='ft') diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 706a982d4f..3fb42fb7db 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -210,6 +210,55 @@ def test_mass_aero_only(self): flops_outputs=flops_outputs, ) + def test_detailed_layout(self): + """Test DetailedCabinLayout component.""" + case_name = 'LargeSingleAisle1FLOPS' + flops_inputs = get_flops_inputs(case_name) + flops_inputs.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, False) + flops_inputs.set_val(Settings.VERBOSITY, 0) + + # do not override these variables which are outputs from DetailedCabinLayout + flops_inputs.delete(Aircraft.Fuselage.LENGTH) + flops_inputs.delete(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + flops_inputs.delete(Aircraft.Fuselage.MAX_WIDTH) + flops_inputs.delete(Aircraft.Fuselage.MAX_HEIGHT) + + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) + # get geom subsystem only + default_premission_subsystems = [get_default_premission_subsystems('FLOPS', engines)[1]] + + prob = self.prob + + prob.model.add_subsystem( + 'pre_mission', + CorePreMission( + aviary_options=flops_inputs, + subsystems=default_premission_subsystems, + subsystem_options={}, + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, flops_inputs) + prob.setup(check=False, force_alloc_complex=True) + set_aviary_initial_values(prob, flops_inputs) + prob.run_model() + + expected_values = { + # geometry subsystem, DetailedCabinLayout component + Aircraft.Fuselage.LENGTH: 148.37731944, + Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH: 108.37731944, + Aircraft.Fuselage.MAX_WIDTH: 12.19, + Aircraft.Fuselage.MAX_HEIGHT: 13.09, + } + + tol = 1e-5 + for var_name, expected in expected_values.items(): + with self.subTest(var=var_name): + assert_near_equal(prob[var_name], expected, tol) + @use_tempdirs class BWBPreMissionGroupTest(unittest.TestCase): @@ -1233,4 +1282,7 @@ def test_case_all_subsystems(self): if __name__ == '__main__': - unittest.main() + # unittest.main() + test = PreMissionGroupTest() + test.setUp() + test.test_detailed_layout() diff --git a/aviary/utils/fortran_to_aviary.py b/aviary/utils/fortran_to_aviary.py index 6767f56b4c..38e6a22747 100644 --- a/aviary/utils/fortran_to_aviary.py +++ b/aviary/utils/fortran_to_aviary.py @@ -125,7 +125,7 @@ def fortran_to_aviary( if legacy_code is GASP: vehicle_data = update_gasp_options(vehicle_data, verbosity) elif legacy_code is FLOPS: - vehicle_data = update_flops_options(vehicle_data, verbosity) + vehicle_data = update_flops_options(vehicle_data, comments, verbosity) vehicle_data = update_aviary_options(vehicle_data) # Add settings and engine data file @@ -965,7 +965,7 @@ def update_gasp_options(vehicle_data, verbosity=Verbosity.BRIEF): missing_vars.append('VMLFSL') if Aircraft.Fuselage.AISLE_WIDTH not in input_values: missing_vars.append('WAS') - if Aircraft.Fuselage.SEAT_WIDTH not in input_values: + if Aircraft.Fuselage.SEAT_WIDTH_ECONOMY not in input_values: missing_vars.append('WS') if Aircraft.LandingGear.MAIN_GEAR_LOCATION not in input_values: missing_vars.append('YMG') @@ -982,7 +982,7 @@ def update_gasp_options(vehicle_data, verbosity=Verbosity.BRIEF): return vehicle_data -def update_flops_options(vehicle_data, verbosity=Verbosity.BRIEF): +def update_flops_options(vehicle_data, cmts, verbosity=Verbosity.BRIEF): """Handles variables that are affected by the values of others.""" input_values: NamedValues = vehicle_data['input_values'] @@ -1267,6 +1267,12 @@ def update_flops_options(vehicle_data, verbosity=Verbosity.BRIEF): ARHT = input_values.get_val(Aircraft.HorizontalTail.ASPECT_RATIO)[0] input_values.set_val(Aircraft.VerticalTail.ASPECT_RATIO, [ARHT / 2.0], 'unitless') + if Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS in input_values and design_type[0] != 3: + if input_values.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS)[0] > 0: + cmts.append( + '# business class seats are included. Fuselage layout may be different from FLOPS.' + ) + # if mission-wide fuel flow factor provided, combine into sub and supersonic fuel flow factors if 'MISSIN.fact' in vehicle_data['unused_values']: FACT = vehicle_data['unused_values'].get_item('MISSIN.fact')[0][0] diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index cc4fefbe36..0ca9a9781e 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -92,6 +92,34 @@ def preprocess_options( ): aviary_options.set_val(Aircraft.Design.PERCENT_EXCRESCENCE_DRAG, 0.06) + if Settings.MASS_METHOD in aviary_options: + mass_method = aviary_options.get_val(Settings.MASS_METHOD) + else: + raise UserWarning('MASS_METHOD not specified. Cannot preprocess inputs.') + + if Aircraft.Design.TYPE in aviary_options: + design_type = aviary_options.get_val(Aircraft.Design.TYPE) + else: + design_type = AircraftTypes.TRANSPORT + + if Aircraft.Fuselage.SEAT_WIDTH_ECONOMY not in aviary_options: + if mass_method == LegacyCode.FLOPS: + if design_type == AircraftTypes.TRANSPORT: + aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.0, 'inch') + else: + if design_type == AircraftTypes.BLENDED_WING_BODY: + if verbosity >= Verbosity.BRIEF: + raise UserWarning('Aircraft.Fuselage.SEAT_WIDTH_ECONOMY is not set.') + + if Aircraft.Fuselage.SEAT_WIDTH_FIRST not in aviary_options: + if mass_method == LegacyCode.FLOPS: + if design_type == AircraftTypes.TRANSPORT: + aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 25.0, 'inch') + else: + if design_type == AircraftTypes.BLENDED_WING_BODY: + if verbosity >= Verbosity.BRIEF: + aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_FIRST, 28.0, 'inch') + def preprocess_crewpayload(aviary_options: AviaryValues, meta_data=CoreMetaData, verbosity=None): """ diff --git a/aviary/utils/test/data/converter_test_BWB_GASP.csv b/aviary/utils/test/data/converter_test_BWB_GASP.csv index d6b387eb68..1caa7b1eed 100644 --- a/aviary/utils/test/data/converter_test_BWB_GASP.csv +++ b/aviary/utils/test/data/converter_test_BWB_GASP.csv @@ -82,7 +82,7 @@ aircraft:fuselage:num_aisles,3,unitless aircraft:fuselage:pilot_compartment_length,7.5,ft aircraft:fuselage:pressure_differential,10.0,psi aircraft:fuselage:pressurized_width_additional,0.0,ft -aircraft:fuselage:seat_width,21.0,inch +aircraft:fuselage:seat_width_economy,21.0,inch aircraft:fuselage:tail_fineness,1.75,unitless aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.2,unitless aircraft:fuselage:wetted_area_scaler,1.0001,unitless diff --git a/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv b/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv index e7df6bc290..3f4ece7fd8 100644 --- a/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv +++ b/aviary/utils/test/data/converter_test_advanced_single_aisle_FLOPS.csv @@ -1,4 +1,5 @@ # FLOPS-derived aircraft input deck converted from N3CC_generic_low_speed_polars_FLOPS.txt +# business class seats are included. Fuselage layout may be different from FLOPS. # Input Values aircraft:air_conditioning:mass_scaler,0.98094,unitless diff --git a/aviary/utils/test/data/converter_test_configuration_GASP.csv b/aviary/utils/test/data/converter_test_configuration_GASP.csv index 9821a869e8..c67f0f3af1 100644 --- a/aviary/utils/test/data/converter_test_configuration_GASP.csv +++ b/aviary/utils/test/data/converter_test_configuration_GASP.csv @@ -73,7 +73,7 @@ aircraft:fuselage:nose_fineness,1.0,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,6.85,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,1.18,unitless aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.25,unitless aircraft:fuselage:wetted_area_scaler,1.0,unitless diff --git a/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv b/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv index bcf1c620aa..1d7f12145a 100644 --- a/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv +++ b/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv @@ -73,7 +73,7 @@ aircraft:fuselage:nose_fineness,1.0,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,3.0,unitless aircraft:fuselage:wetted_area,4000.0,ft**2 aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.25,unitless diff --git a/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv b/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv index 76d7ab5a33..246e565471 100644 --- a/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv +++ b/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv @@ -73,7 +73,7 @@ aircraft:fuselage:nose_fineness,0.845,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,11.7,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,24.0,inch +aircraft:fuselage:seat_width_economy,24.0,inch aircraft:fuselage:tail_fineness,3.368,unitless aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.25,unitless aircraft:fuselage:wetted_area_scaler,1.0,unitless diff --git a/aviary/validation_cases/validation_data/test_data/V3_bug_fixed_IO.py b/aviary/validation_cases/validation_data/test_data/V3_bug_fixed_IO.py index 963a8deea3..5b73720872 100644 --- a/aviary/validation_cases/validation_data/test_data/V3_bug_fixed_IO.py +++ b/aviary/validation_cases/validation_data/test_data/V3_bug_fixed_IO.py @@ -58,7 +58,7 @@ Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) V3_bug_fixed_options.set_val(Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless') -V3_bug_fixed_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, 20.2, units='inch') V3_bug_fixed_options.set_val(Aircraft.Fuselage.NUM_AISLES, 1, units='unitless') V3_bug_fixed_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') V3_bug_fixed_options.set_val( diff --git a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_FwGm.csv b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_FwGm.csv index 8211a3eed2..9ee4d7ecfc 100644 --- a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_FwGm.csv +++ b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_FwGm.csv @@ -55,7 +55,7 @@ aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:aspect_ratio,6.0,unitless diff --git a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwFm.csv b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwFm.csv index bd32de2b00..26a08427b7 100644 --- a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwFm.csv +++ b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwFm.csv @@ -59,7 +59,7 @@ aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless diff --git a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwGm.csv b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwGm.csv index c5058d0fea..457e43ca4b 100644 --- a/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwGm.csv +++ b/aviary/validation_cases/validation_data/test_models/aircraft_for_bench_GwGm.csv @@ -59,7 +59,7 @@ aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless diff --git a/aviary/validation_cases/validation_data/test_models/configuration_test_GASP.csv b/aviary/validation_cases/validation_data/test_models/configuration_test_GASP.csv index 9009449456..c5d1f04446 100644 --- a/aviary/validation_cases/validation_data/test_models/configuration_test_GASP.csv +++ b/aviary/validation_cases/validation_data/test_models/configuration_test_GASP.csv @@ -56,7 +56,7 @@ aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless aircraft:fuselage:pilot_compartment_length,6.85,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:seat_width_economy,20.2,inch aircraft:fuselage:tail_fineness,1.18,unitless aircraft:fuselage:wetted_area_scaler,1,unitless aircraft:horizontal_tail:aspect_ratio,4.025,unitless diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 7f6133e50d..e8b61e90e7 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -332,11 +332,7 @@ add_meta_data( Aircraft.BWB.MAX_BAY_WIDTH, meta_data=_MetaData, - historical_name={ - 'GASP': None, - 'FLOPS': 'FUSEIN.BAYWMX', - 'LEAPS1': None, - }, + historical_name={'GASP': None, 'FLOPS': 'FUSEIN.BAYWMX'}, units='ft', desc='maximum bay width', types=float, @@ -2153,7 +2149,7 @@ add_meta_data( Aircraft.Engine.INLET_AREA_COEFFICIENT, meta_data=_MetaData, - historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + historical_name={'GASP': None, 'FLOPS': None}, units='unitless', option=True, default_value=0.0002, # default in GASP @@ -3578,7 +3574,17 @@ ) add_meta_data( - Aircraft.Fuselage.SEAT_WIDTH, + Aircraft.Fuselage.SEAT_WIDTH_BUSINESS, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None}, + units='inch', + desc='width of the business class seats', + option=True, + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.SEAT_WIDTH_ECONOMY, meta_data=_MetaData, historical_name={'GASP': 'INGASP.WS', 'FLOPS': None}, units='inch', @@ -3587,10 +3593,20 @@ default_value=0.0, ) +add_meta_data( + Aircraft.Fuselage.SEAT_WIDTH_FIRST, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None}, + units='inch', + desc='width of the first class seats', + option=True, + default_value=0.0, +) + add_meta_data( Aircraft.Fuselage.SIDEBODY_THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={'GASP': None, 'FLOPS': 'WTIN.TCSOB', 'LEAPS1': None}, + historical_name={'GASP': None, 'FLOPS': 'WTIN.TCSOB'}, units='unitless', desc='fuselage thickness/chord ratio at side of body', default_value=0.0, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 8ebb486e91..b22787a47b 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -335,7 +335,9 @@ class Fuselage: PRESSURE_DIFFERENTIAL = 'aircraft:fuselage:pressure_differential' PRESSURIZED_WIDTH_ADDITIONAL = 'aircraft:fuselage:pressurized_width_additional' REF_DIAMETER = 'aircraft:fuselage:ref_diameter' - SEAT_WIDTH = 'aircraft:fuselage:seat_width' + SEAT_WIDTH_BUSINESS = 'aircraft:fuselage:seat_width_business' + SEAT_WIDTH_ECONOMY = 'aircraft:fuselage:seat_width_economy' + SEAT_WIDTH_FIRST = 'aircraft:fuselage:seat_width_first' SIDEBODY_THICKNESS_TO_CHORD = 'aircraft:fuselage:sidebody_thickness_to_chord' SIMPLE_LAYOUT = 'aircraft:fuselage:simple_layout' TAIL_FINENESS = 'aircraft:fuselage:tail_fineness'