diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv index eb5a3f644..e48a34fdc 100644 --- a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv +++ b/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv @@ -69,8 +69,7 @@ aircraft:fuselage:max_width,12.3,ft aircraft:fuselage:military_cargo_floor,False,unitless aircraft:fuselage:num_fuselages,1,unitless aircraft:fuselage:passenger_compartment_length,97.5,ft -aircraft:fuselage:wetted_area,4235.082096,lbm -aircraft:fuselage:wetted_area_scaler,1.0,unitless +aircraft:fuselage:wetted_area,4235.082096,ft**2 aircraft:horizontal_tail:area,349.522730527158,ft**2 aircraft:horizontal_tail:aspect_ratio,5.22699386503068,unitless aircraft:horizontal_tail:laminar_flow_lower,0,unitless @@ -80,8 +79,7 @@ aircraft:horizontal_tail:sweep,30.5853213018973,deg aircraft:horizontal_tail:taper_ratio,0.2734375,unitless aircraft:horizontal_tail:thickness_to_chord,0.115,unitless aircraft:horizontal_tail:vertical_tail_fraction,0,unitless -aircraft:horizontal_tail:wetted_area,576.571192,lbm -aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless +aircraft:horizontal_tail:wetted_area,576.571192,ft**2 aircraft:hydraulics:mass_scaler,0.95543,unitless aircraft:hydraulics:system_pressure,5000,psi aircraft:instruments:mass_scaler,1.66955,unitless @@ -95,7 +93,7 @@ aircraft:nacelle:avg_diameter,7.2,ft aircraft:nacelle:avg_length,35,ft aircraft:nacelle:laminar_flow_lower,0,unitless aircraft:nacelle:laminar_flow_upper,0,unitless -aircraft:nacelle:wetted_area_scaler,244.468282,unitless +aircraft:nacelle:wetted_area,244.468282,ft**2 aircraft:paint:mass_per_unit_area,0,lbm/ft**2 aircraft:propulsion:engine_oil_mass_scaler,1,unitless aircraft:propulsion:misc_mass_scaler,0,unitless @@ -108,7 +106,7 @@ aircraft:vertical_tail:num_tails,1,unitless aircraft:vertical_tail:sweep,39.735053245438,deg aircraft:vertical_tail:taper_ratio,0.25,unitless aircraft:vertical_tail:thickness_to_chord,0.1,unitless -aircraft:vertical_tail:wetted_area_scaler,445.645658,unitless +aircraft:vertical_tail:wetted_area,445.645658,ft**2 aircraft:wing:aeroelastic_tailoring_factor,0.33333,unitless aircraft:wing:airfoil_technology,1.6,unitless aircraft:wing:area,1220,1,0,0,0,0,ft**2 @@ -144,8 +142,7 @@ aircraft:wing:thickness_to_chord_dist,0.14233,0.12233,0.1108,0.1058,unitless aircraft:wing:thickness_to_chord_reference,0.116565,unitless aircraft:wing:ultimate_load_factor,3.75,unitless aircraft:wing:var_sweep_mass_penalty,0,unitless -aircraft:wing:wetted_area,2210.280228,lbm -aircraft:wing:wetted_area_scaler,1.0,unitless +aircraft:wing:wetted_area,2210.280228,ft**2 mission:constraints:max_mach,0.785,unitless mission:design:gross_mass,1,lbm mission:design:lift_coefficient,-1,unitless diff --git a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py index 895451497..5686a33a0 100644 --- a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py +++ b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py @@ -117,7 +117,7 @@ Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) V3_bug_fixed_options.set_val( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" + Aircraft.Fuselage.WETTED_AREA, 4000, units="ft**2" ) V3_bug_fixed_options.set_val( Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv index fba8c5963..c56c27006 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv @@ -56,7 +56,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless +aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv index 4bcb42fac..8bcf61611 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv @@ -56,7 +56,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,31,inch aircraft:fuselage:seat_width,24,inch aircraft:fuselage:tail_fineness,3.368,unitless -aircraft:fuselage:wetted_area_factor,1,unitless +aircraft:fuselage:wetted_area_scaler,1,unitless aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.26,unitless aircraft:horizontal_tail:form_factor,1.55,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv index 5e04bd9ab..d4c64818d 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv @@ -61,7 +61,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless +aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:area,355.0,ft**2 aircraft:horizontal_tail:aspect_ratio,6.0,unitless aircraft:horizontal_tail:form_factor,1.25,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv index 88adc9307..d27a939e6 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv @@ -129,12 +129,9 @@ aircraft:fuselage:passenger_compartment_length,85.5,ft aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:planform_area,1578.24,ft**2 aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:provide_surface_area,True,unitless aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless -aircraft:fuselage:wetted_area_scaler,1.0,unitless aircraft:fuselage:wetted_area,4158.62,ft**2 aircraft:horizontal_tail:area,355.0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv index 814a2d20c..ca9d5bc40 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv @@ -56,7 +56,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless +aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv index dcefd2c07..ef82a6cda 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv +++ b/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv @@ -57,7 +57,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area_factor,4000,unitless +aircraft:fuselage:wetted_area,4000,ft**2 aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv index 51b3d5279..2dcba0a50 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv @@ -56,7 +56,7 @@ aircraft:fuselage:pressure_differential,7.5,psi aircraft:fuselage:seat_pitch,44.2,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,1.18,unitless -aircraft:fuselage:wetted_area_factor,1,unitless +aircraft:fuselage:wetted_area_scaler,1,unitless aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.025,unitless aircraft:horizontal_tail:form_factor,1.7,unitless diff --git a/aviary/subsystems/geometry/gasp_based/fuselage.py b/aviary/subsystems/geometry/gasp_based/fuselage.py index d9d80e0f9..8fcb23859 100644 --- a/aviary/subsystems/geometry/gasp_based/fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/fuselage.py @@ -114,12 +114,8 @@ def setup(self): self.add_input("cabin_len", val=0, units="ft", desc="LC: length of cabin") add_aviary_input(self, Aircraft.Fuselage.TAIL_FINENESS, val=3) self.add_input("cabin_height", val=0, units="ft", desc="HC: height of cabin") - if self.options['aviary_options'].get_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, units='unitless'): - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_FACTOR, - val=4000, units="unitless") - else: - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_FACTOR, - val=1, units="unitless") + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, + val=1, units="unitless") add_aviary_output(self, Aircraft.Fuselage.LENGTH, val=0) add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, val=0) @@ -136,9 +132,11 @@ def setup(self): "cabin_height", ], ) + self.declare_partials( Aircraft.Fuselage.WETTED_AREA, [ + Aircraft.Fuselage.WETTED_AREA_SCALER, "cabin_height", Aircraft.Fuselage.NOSE_FINENESS, "nose_height", @@ -148,24 +146,6 @@ def setup(self): ], ) - if self.options['aviary_options'].get_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, units='unitless'): - self.declare_partials(Aircraft.Fuselage.WETTED_AREA, - Aircraft.Fuselage.WETTED_AREA_FACTOR) - - else: - self.declare_partials( - Aircraft.Fuselage.WETTED_AREA, - [ - Aircraft.Fuselage.WETTED_AREA_FACTOR, - "cabin_height", - Aircraft.Fuselage.NOSE_FINENESS, - "nose_height", - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, - "cabin_len", - Aircraft.Fuselage.TAIL_FINENESS, - ], - ) - self.declare_partials( Aircraft.TailBoom.LENGTH, [ @@ -182,7 +162,7 @@ def compute(self, inputs, outputs): LoverD_nose = inputs[Aircraft.Fuselage.NOSE_FINENESS] LoverD_tail = inputs[Aircraft.Fuselage.TAIL_FINENESS] cockpit_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] - fus_SA_factor = inputs[Aircraft.Fuselage.WETTED_AREA_FACTOR] + fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] nose_height = inputs["nose_height"] cabin_len = inputs["cabin_len"] cabin_height = inputs["cabin_height"] @@ -200,11 +180,7 @@ def compute(self, inputs, outputs): + 2.1 * LoverD_tail * cabin_height ) - if self.options["aviary_options"].get_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, units='unitless'): - fus_SA = fus_SA_factor - - else: - fus_SA = fus_SA * fus_SA_factor + fus_SA = fus_SA * fus_SA_scaler cabin_len_tailboom = fus_len @@ -217,7 +193,7 @@ def compute_partials(self, inputs, J): LoverD_tail = inputs[Aircraft.Fuselage.TAIL_FINENESS] nose_height = inputs["nose_height"] cabin_height = inputs["cabin_height"] - fus_SA_factor = inputs[Aircraft.Fuselage.WETTED_AREA_FACTOR] + fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] cockpit_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] cabin_len = inputs["cabin_len"] @@ -228,36 +204,32 @@ def compute_partials(self, inputs, J): J[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.TAIL_FINENESS] = cabin_height J[Aircraft.Fuselage.LENGTH, "cabin_height"] = LoverD_tail - if self.options["aviary_options"].get_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, units='unitless'): - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_FACTOR] = 1 - - else: - J[Aircraft.Fuselage.WETTED_AREA, "cabin_height"] = fus_SA_factor * ( - 2.5 * (LoverD_nose * nose_height + cockpit_len) - + 3.14 * cabin_len - + 2.1 * LoverD_tail * cabin_height - + cabin_height * 2.1 * LoverD_tail - ) - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.NOSE_FINENESS] = ( - fus_SA_factor * cabin_height * 2.5 * nose_height - ) - J[Aircraft.Fuselage.WETTED_AREA, "nose_height"] = ( - fus_SA_factor * cabin_height * 2.5 * LoverD_nose - ) - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = ( - fus_SA_factor * cabin_height * 2.5 - ) - J[Aircraft.Fuselage.WETTED_AREA, "cabin_len"] = ( - fus_SA_factor * 3.14 * cabin_height - ) - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.TAIL_FINENESS] = ( - fus_SA_factor * 2.1 * cabin_height**2 - ) - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_FACTOR] = cabin_height * ( - 2.5 * (LoverD_nose * nose_height + cockpit_len) - + 3.14 * cabin_len - + 2.1 * LoverD_tail * cabin_height - ) + J[Aircraft.Fuselage.WETTED_AREA, "cabin_height"] = fus_SA_scaler * ( + 2.5 * (LoverD_nose * nose_height + cockpit_len) + + 3.14 * cabin_len + + 2.1 * LoverD_tail * cabin_height + + cabin_height * 2.1 * LoverD_tail + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.NOSE_FINENESS] = ( + fus_SA_scaler * cabin_height * 2.5 * nose_height + ) + J[Aircraft.Fuselage.WETTED_AREA, "nose_height"] = ( + fus_SA_scaler * cabin_height * 2.5 * LoverD_nose + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = ( + fus_SA_scaler * cabin_height * 2.5 + ) + J[Aircraft.Fuselage.WETTED_AREA, "cabin_len"] = ( + fus_SA_scaler * 3.14 * cabin_height + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.TAIL_FINENESS] = ( + fus_SA_scaler * 2.1 * cabin_height**2 + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_SCALER] = cabin_height * ( + 2.5 * (LoverD_nose * nose_height + cockpit_len) + + 3.14 * cabin_len + + 2.1 * LoverD_tail * cabin_height + ) J[Aircraft.TailBoom.LENGTH, Aircraft.Fuselage.NOSE_FINENESS] = nose_height J[Aircraft.TailBoom.LENGTH, "nose_height"] = LoverD_nose diff --git a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py index d6176684e..b40f34f9d 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py @@ -10,9 +10,11 @@ from aviary.variable_info.variables import Aircraft -class FuselageParametersTestCase1( - unittest.TestCase -): # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix +class FuselageParametersTestCase1(unittest.TestCase): + """ + this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix + """ + def setUp(self): options = get_option_defaults() @@ -90,9 +92,11 @@ def test_case2(self): assert_check_partials(partial_data2, atol=1e-8, rtol=1e-8) -class FuselageSizeTestCase1( - unittest.TestCase -): # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix +class FuselageSizeTestCase1(unittest.TestCase): + """ + this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix + """ + def setUp(self): self.prob = om.Problem() @@ -109,8 +113,6 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") self.prob.model.set_input_defaults("cabin_height", 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless") self.prob.setup(check=False, force_alloc_complex=True) @@ -122,7 +124,7 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 - assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.68, tol) assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 @@ -131,14 +133,14 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -class FuselageSizeTestCase2( - unittest.TestCase -): # this is the GASP test case for V3.6 advanced tube and wing +class FuselageSizeTestCase2(unittest.TestCase): + """ + this is the GASP test case for V3.6 advanced tube and wing + """ + def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( @@ -155,7 +157,7 @@ def setUp(self): Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") self.prob.model.set_input_defaults("cabin_height", 13.1, units="ft") self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 1, units="unitless") + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless") self.prob.setup(check=False, force_alloc_complex=True) @@ -205,8 +207,6 @@ def setUp(self): Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") @@ -222,7 +222,7 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 - assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.57, tol) assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 @@ -235,8 +235,6 @@ class FuselageGroupTestCase2(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") # not actual GASP value @@ -264,9 +262,6 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) # not actual GASP value - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) # not actual GASP value self.prob.model.set_input_defaults( Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" @@ -286,7 +281,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 18558260.55555555, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.565, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol @@ -300,8 +295,6 @@ class FuselageGroupTestCase3(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=30, units='unitless') options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") # not actual GASP value @@ -329,9 +322,6 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) # not actual GASP value - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) # not actual GASP value self.prob.model.set_input_defaults( Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" @@ -351,7 +341,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 1.1790053e7, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 2947.51, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol @@ -392,9 +382,6 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) # not actual GASP value - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) # not actual GASP value self.prob.model.set_input_defaults( Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" @@ -414,7 +401,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 2947.51, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol diff --git a/aviary/subsystems/geometry/gasp_based/test/test_override.py b/aviary/subsystems/geometry/gasp_based/test/test_override.py new file mode 100644 index 000000000..c6f77cee7 --- /dev/null +++ b/aviary/subsystems/geometry/gasp_based/test/test_override.py @@ -0,0 +1,111 @@ +import openmdao.api as om +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.interface.methods_for_level2 import AviaryGroup +from aviary.subsystems.premission import CorePreMission +from aviary.variable_info.variables import Aircraft + +from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.process_input_decks import create_vehicle +from aviary.utils.preprocessors import preprocess_propulsion +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData + +import warnings +import unittest + + +class GASPOverrideTestCase(unittest.TestCase): + def setUp(self): + aviary_inputs, initial_guesses = create_vehicle( + 'models/test_aircraft/converter_configuration_test_data_GwGm.csv') + + engines = build_engine_deck(aviary_inputs) + + core_subsystems = get_default_premission_subsystems('GASP', engines) + preprocess_propulsion(aviary_inputs, engines) + + self.aviary_inputs = aviary_inputs + + prob = om.Problem() + + aviary_options = aviary_inputs + subsystems = core_subsystems + + prob.model = AviaryGroup(aviary_options=aviary_options, + aviary_metadata=BaseMetaData) + prob.model.add_subsystem( + 'pre_mission', + CorePreMission(aviary_options=aviary_options, + subsystems=subsystems), + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['aircraft:*', 'mission:*'] + ) + + self.prob = prob + + def test_case1(self): + """Test override: expect the given value""" + prob = self.prob + + self.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA, val=4000.0, units="ft**2") + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", om.PromotionWarning) + prob.setup() + + prob.run_model() + + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, 1e-6) + + def test_case2(self): + """Test override: expect the computed value""" + prob = self.prob + + # self.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", om.PromotionWarning) + prob.setup() + + prob.run_model() + + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4794.748, 1e-6) + + def test_case3(self): + """Test WETTED_AREA_SCALER: expected half of the computed value """ + prob = self.prob + + # self.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") + self.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units="unitless") + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", om.PromotionWarning) + prob.setup() + + prob.run_model() + + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 2397.374, 1e-6) + + def test_case4(self): + """Test WETTED_AREA_SCALER: expect no effect""" + prob = self.prob + + self.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") + self.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units="unitless") + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", om.PromotionWarning) + prob.setup() + + prob.run_model() + + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, 1e-6) + + +if __name__ == '__main__': + unittest.main() 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 9549599df..0a9530218 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_size_group.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_size_group.py @@ -80,9 +80,6 @@ def setUp(self): Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -116,7 +113,7 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol ) - assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.57, tol) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol @@ -163,8 +160,6 @@ class SizeGroupTestCase2(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, @@ -240,9 +235,6 @@ def setUp(self): Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -284,7 +276,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 18558260.55555555, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.57, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol @@ -387,8 +379,6 @@ class SizeGroupTestCase3(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=True, units='unitless') @@ -468,9 +458,6 @@ def setUp(self): Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -512,7 +499,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 476.7333, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 53601769, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 13400.44, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 476.7333, tol @@ -692,9 +679,6 @@ def setUp(self): Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -736,7 +720,7 @@ def test_case1(self): self.prob[Aircraft.Fuselage.LENGTH], 476.7333, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Fuselage.WETTED_AREA], 4000, tol + self.prob[Aircraft.Fuselage.WETTED_AREA], 13400.44, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 476.7333, tol diff --git a/aviary/subsystems/mass/flops_based/canard.py b/aviary/subsystems/mass/flops_based/canard.py index 5447e2a3d..9223872f1 100644 --- a/aviary/subsystems/mass/flops_based/canard.py +++ b/aviary/subsystems/mass/flops_based/canard.py @@ -40,19 +40,19 @@ def compute(self, inputs, outputs): def compute_partials(self, inputs, J): area = inputs[Aircraft.Canard.AREA] taper_ratio = inputs[Aircraft.Canard.TAPER_RATIO] - scalar = inputs[Aircraft.Canard.MASS_SCALER] + scaler = inputs[Aircraft.Canard.MASS_SCALER] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM gross_weight_exp = gross_weight**0.2 J[Aircraft.Canard.MASS, Aircraft.Canard.AREA] = 0.53 * \ - scalar * (taper_ratio+0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + scaler * (taper_ratio+0.5) * gross_weight_exp / GRAV_ENGLISH_LBM J[Aircraft.Canard.MASS, Aircraft.Canard.TAPER_RATIO] = \ - 0.53*area * scalar * gross_weight_exp / GRAV_ENGLISH_LBM + 0.53*area * scaler * gross_weight_exp / GRAV_ENGLISH_LBM J[Aircraft.Canard.MASS, Aircraft.Canard.MASS_SCALER] = \ 0.53*area * (taper_ratio+0.5) * gross_weight_exp / GRAV_ENGLISH_LBM J[Aircraft.Canard.MASS, Mission.Design.GROSS_MASS] = \ - (0.106*area * scalar * (taper_ratio+0.5)) / gross_weight**0.8 + (0.106*area * scaler * (taper_ratio+0.5)) / gross_weight**0.8 diff --git a/aviary/subsystems/mass/flops_based/engine.py b/aviary/subsystems/mass/flops_based/engine.py index 5fac649a0..5edf1511b 100644 --- a/aviary/subsystems/mass/flops_based/engine.py +++ b/aviary/subsystems/mass/flops_based/engine.py @@ -56,7 +56,7 @@ def compute(self, inputs, outputs): # use dtype to make complex safe calc_mass = np.array(ref_engine_mass, dtype=scaled_thrust.dtype) - # scale engine mass using equation chosen by value of user-provided mass scalar + # scale engine mass using equation chosen by value of user-provided mass scaler thrust_ratio = scaled_thrust / ref_thrust calc_mass[scale_idx] = ref_engine_mass[scale_idx] + ( diff --git a/aviary/subsystems/mass/flops_based/fin.py b/aviary/subsystems/mass/flops_based/fin.py index d7e1affdf..989ee1ee2 100644 --- a/aviary/subsystems/mass/flops_based/fin.py +++ b/aviary/subsystems/mass/flops_based/fin.py @@ -46,20 +46,20 @@ def compute_partials(self, inputs, J): if num_fins > 0: area = inputs[Aircraft.Fins.AREA] taper_ratio = inputs[Aircraft.Fins.TAPER_RATIO] - scalar = inputs[Aircraft.Fins.MASS_SCALER] + scaler = inputs[Aircraft.Fins.MASS_SCALER] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM area_exp = area**0.85 gross_weight_exp = gross_weight**0.3 J[Aircraft.Fins.MASS, Aircraft.Fins.AREA] = ( - (0.272 * num_fins * scalar * (taper_ratio + 0.5) * gross_weight_exp) + (0.272 * num_fins * scaler * (taper_ratio + 0.5) * gross_weight_exp) / area**0.15) / GRAV_ENGLISH_LBM J[Aircraft.Fins.MASS, Aircraft.Fins.TAPER_RATIO] = \ - 0.32 * area_exp * num_fins * scalar * gross_weight_exp / GRAV_ENGLISH_LBM + 0.32 * area_exp * num_fins * scaler * gross_weight_exp / GRAV_ENGLISH_LBM J[Aircraft.Fins.MASS, Aircraft.Fins.MASS_SCALER] = \ 0.32 * area_exp * num_fins * \ (taper_ratio + 0.5) * gross_weight_exp / GRAV_ENGLISH_LBM J[Aircraft.Fins.MASS, Mission.Design.GROSS_MASS] = ( - (0.096 * area_exp * num_fins * scalar * (taper_ratio + 0.5)) + (0.096 * area_exp * num_fins * scaler * (taper_ratio + 0.5)) / gross_weight**0.7) diff --git a/aviary/subsystems/mass/flops_based/wing_common.py b/aviary/subsystems/mass/flops_based/wing_common.py index 20098e0a5..2d8be698f 100644 --- a/aviary/subsystems/mass/flops_based/wing_common.py +++ b/aviary/subsystems/mass/flops_based/wing_common.py @@ -353,9 +353,9 @@ def compute(self, inputs, outputs): m2 = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS] m3 = inputs[Aircraft.Wing.MISC_MASS] m4 = inputs[Aircraft.Wing.BWB_AFTBODY_MASS] - m_scalar = inputs[Aircraft.Wing.MASS_SCALER] + m_scaler = inputs[Aircraft.Wing.MASS_SCALER] - outputs[Aircraft.Wing.MASS] = (m1 + m2 + m3 + m4) * m_scalar + outputs[Aircraft.Wing.MASS] = (m1 + m2 + m3 + m4) * m_scaler def compute_partials(self, inputs, J): m1 = inputs[Aircraft.Wing.BENDING_MASS] diff --git a/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py b/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py index 5ddc566f0..4101e5325 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py +++ b/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py @@ -52,6 +52,9 @@ def setUp(self): Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" ) self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 + self.prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.setup(check=False, force_alloc_complex=True) @@ -59,6 +62,8 @@ def test_case1(self): self.prob.run_model() + # print(f"wetted_area: {self.prob[Aircraft.Fuselage.WETTED_AREA]}") + tol = 5e-4 # size values: assert_near_equal(self.prob["gasp_based_geom.fuselage.cabin_height"], 13.1, tol) @@ -262,9 +267,9 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -651,9 +656,9 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -1031,9 +1036,9 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -1412,9 +1417,9 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -1792,9 +1797,9 @@ def setUp(self): self.prob.model.set_input_defaults( Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" ) @@ -2078,8 +2083,6 @@ class MassSummationTestCase7(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') @@ -2176,7 +2179,7 @@ def setUp(self): Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 1, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless" ) self.prob.model.set_input_defaults( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units="unitless" @@ -2467,8 +2470,6 @@ class MassSummationTestCase8(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, @@ -2551,7 +2552,7 @@ def setUp(self): Aircraft.Fuselage.TAIL_FINENESS, 1.18, units="unitless" ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 1.0, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units="unitless" ) self.prob.model.set_input_defaults( Aircraft.Wing.LOADING, val=87.5, units="lbf/ft**2" @@ -2865,8 +2866,6 @@ class MassSummationTestCase9(unittest.TestCase): def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - val=False, units='unitless') options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=154, units='unitless') @@ -2947,7 +2946,7 @@ def setUp(self): Aircraft.Fuselage.TAIL_FINENESS, 1.18, units="unitless" ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 1, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless" ) self.prob.model.set_input_defaults( Aircraft.Wing.LOADING, val=96.10, units="lbf/ft**2" diff --git a/aviary/subsystems/test/test_premission.py b/aviary/subsystems/test/test_premission.py index 51724e96a..cd139f072 100644 --- a/aviary/subsystems/test/test_premission.py +++ b/aviary/subsystems/test/test_premission.py @@ -115,6 +115,10 @@ def setUp(self): # Set inital values for all variables. set_aviary_initial_values(self.prob, input_options) + # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 + self.prob.set_val( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") + def test_GASP_mass_FLOPS_everything_else(self): self.prob.run_model() diff --git a/aviary/utils/conflict_checks.py b/aviary/utils/conflict_checks.py index 40d1cbcf6..fd79461ed 100644 --- a/aviary/utils/conflict_checks.py +++ b/aviary/utils/conflict_checks.py @@ -4,6 +4,9 @@ def check_fold_location_definition(inputs, options: AviaryValues): + """ + If there is no strut, then CHOOSE_FOLD_LOCATION must be true. + """ choose_fold_location = options.get_val( Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless') has_strut = options.get_val(Aircraft.Wing.HAS_STRUT, units='unitless') @@ -19,7 +22,6 @@ def check_fold_location_definition(inputs, options: AviaryValues): # Aircraft.Engine.TYPE - Aircraft.Engine.HAS_PROPELLERS # Aircraft.Design.COMPUTE_TAIL_VOLUME_COEFFS # Aircraft.Engine.REFERENCE_WEIGHT -# Aircraft.Fuselage.PROVIDE_SURFACE_AREA - Aircraft.Fuselage.WETTED_AREA_FACTOR # Mission.Taxi.MACH - pycycle # Aircraft.HorizontalTail.AREA # Aircraft.VerticalTail.AREA diff --git a/aviary/utils/fortran_to_aviary.py b/aviary/utils/fortran_to_aviary.py index 426e98ca2..575dc24ce 100644 --- a/aviary/utils/fortran_to_aviary.py +++ b/aviary/utils/fortran_to_aviary.py @@ -390,6 +390,9 @@ def update_gasp_options(vehicle_data): """ input_values: NamedValues = vehicle_data['input_values'] + for var_name in gasp_scaler_variables: + update_gasp_scaler_variables(var_name, input_values) + flap_types = ["plain", "split", "single_slotted", "double_slotted", "triple_slotted", "fowler", "double_slotted_fowler"] @@ -502,8 +505,8 @@ def update_flops_options(vehicle_data): """ input_values: NamedValues = vehicle_data['input_values'] - for var_name in flops_scalar_variables: - update_flops_scalar_variables(var_name, input_values) + for var_name in flops_scaler_variables: + update_flops_scaler_variables(var_name, input_values) # TWR <= 0 is not valid in Aviary (parametric variation) if Aircraft.Design.THRUST_TO_WEIGHT_RATIO in input_values: @@ -512,7 +515,7 @@ def update_flops_options(vehicle_data): # WSR - # Additional mass fraction scalar set to zero to not add mass twice + # Additional mass fraction scaler set to zero to not add mass twice if Aircraft.Engine.ADDITIONAL_MASS_FRACTION in input_values: if input_values.get_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION)[0] >= 1: input_values.set_val(Aircraft.Engine.ADDITIONAL_MASS, @@ -534,33 +537,63 @@ def update_flops_options(vehicle_data): return vehicle_data -def update_flops_scalar_variables(var_name, input_values: NamedValues): - # The following parameters are used to modify or override - # internally computed weights for various components as follows: - # < 0., negative of starting weight which will be modified - # as appropriate during optimization or parametric - # variation, lb - # = 0., no weight for that component - # > 0. but < 5., scale factor applied to internally - # computed weight - # > 5., actual fixed weight for component, lb - # Same rules also applied to various other FLOPS scalar parameters - scalar_name = var_name + '_scaler' - if scalar_name not in input_values: +def update_flops_scaler_variables(var_name, input_values: NamedValues): + """ + The following parameters are used to modify or override + internally computed weights and areas for various components as follows: + < 0., negative of starting weight which will be modified + as appropriate during optimization or parametric variation, lb or ft**2 + = 0., no weight for that component + > 0. but < 5., scale factor applied to internally computed weight or area + > 5., actual fixed weight for component, lb or ft**2 + Same rules also applied to various other FLOPS scaler parameters + """ + scaler_name = var_name + '_scaler' + if scaler_name not in input_values: + return + scaler_value = input_values.get_val(scaler_name)[0] + if scaler_value <= 0: + input_values.delete(scaler_name) + elif scaler_value < 5: + return + elif scaler_value > 5: + if "area" in var_name.lower(): + input_values.set_val(var_name, [scaler_value], 'ft**2') + else: + input_values.set_val(var_name, [scaler_value], 'lbm') + input_values.delete(scaler_name) + + +def update_gasp_scaler_variables(var_name, input_values: NamedValues): + """ + The following parameters are used to modify or override + internally computed weights and areas for various components as follows: + < 0., negative of starting weight which will be modified + as appropriate during optimization or parametric variation, lb or ft**2 + = 0., no weight/area for that component + > 0. but < 10., scale factor applied to internally computed weight + > 10., actual fixed weight for component, lb or ft**2 + Same rules also applied to various other FLOPS scaler parameters + """ + scaler_name = var_name + '_scaler' + if scaler_name not in input_values: return - scalar_value = input_values.get_val(scalar_name)[0] - if scalar_value <= 0: - input_values.delete(scalar_name) - elif scalar_value < 5: + scaler_value = input_values.get_val(scaler_name)[0] + if scaler_value <= 0: + input_values.delete(scaler_name) + elif scaler_value < 10: return - elif scalar_value > 5: - input_values.set_val(var_name, [scalar_value], 'lbm') - input_values.set_val(scalar_name, [1.0]) + elif scaler_value > 10: + if "area" in var_name.lower(): + input_values.set_val(var_name, [scaler_value], 'ft**2') + else: + input_values.set_val(var_name, [scaler_value], 'lbm') + input_values.delete(scaler_name) # list storing information on Aviary variables that are split from single # FLOPS variables that use the same value-based branching behavior -flops_scalar_variables = [ +flops_scaler_variables = [ Aircraft.AirConditioning.MASS, Aircraft.AntiIcing.MASS, Aircraft.APU.MASS, @@ -587,15 +620,21 @@ def update_flops_scalar_variables(var_name, input_values: NamedValues): Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.Nacelle.MASS, + Aircraft.Nacelle.WETTED_AREA, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, Aircraft.VerticalTail.MASS_SCALER, - Aircraft.VerticalTail.WETTED_AREA_SCALER, + Aircraft.VerticalTail.WETTED_AREA, Aircraft.Wing.MASS, Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.WETTED_AREA, ] +# GASP variables that use the same value-based branching behavior +gasp_scaler_variables = [ + Aircraft.Fuselage.WETTED_AREA, +] + initial_guesses = { # initial_guesses is a dictionary that contains values used to initialize the trajectory 'actual_takeoff_mass': 0, diff --git a/aviary/utils/legacy_code_data/flops_default_values.txt b/aviary/utils/legacy_code_data/flops_default_values.txt index 1a604f04f..a2ce69a57 100644 --- a/aviary/utils/legacy_code_data/flops_default_values.txt +++ b/aviary/utils/legacy_code_data/flops_default_values.txt @@ -13,4 +13,6 @@ Default Values from FLOPS \ &AERIN MIKE=False,unitless + SWETF=1,unitless + SWETV=1,unitless \ \ No newline at end of file diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 080112200..c943e64bc 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -428,8 +428,6 @@ def initial_guessing(aircraft_values: AviaryValues, initial_guesses, engine_buil # [Aircraft.Engine.WING_LOCATIONS, { # 'val': 0, 'relation': '==', 'target': Aircraft.Engine.FUSELAGE_MOUNTED, 'result': True, 'alternate': False}], - [Aircraft.Fuselage.WETTED_AREA_FACTOR, { - 'val': 10, 'relation': '>', 'target': Aircraft.Fuselage.PROVIDE_SURFACE_AREA, 'result': True, 'alternate': False}], [Aircraft.Wing.LOADING, {'val': 20, 'relation': '>', 'target': Aircraft.Wing.LOADING_ABOVE_20, 'result': True, 'alternate': False}], [Aircraft.Strut.ATTACHMENT_LOCATION, { diff --git a/aviary/utils/set_mass_defaults.py b/aviary/utils/set_mass_defaults.py deleted file mode 100644 index 910128acd..000000000 --- a/aviary/utils/set_mass_defaults.py +++ /dev/null @@ -1,297 +0,0 @@ -from aviary.variable_info.variables import Aircraft - - -def mass_defaults(prob): - prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=0, units='unitless') - prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless") - prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi" - ) - prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless") - prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" - ) - - prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_FACTOR, 4000, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" - ) - prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") - - prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, - val=402.5, - units="mi/h", - ) - prob.model.set_input_defaults( - Aircraft.Design.LIFT_CURVE_SLOPE, - val=7.1765, - units="unitless", - ) - - prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" - ) - prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, - val=0.232, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, - val=0.289, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - val=0.12, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, - val=0.12, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, - val=2.66, - units="lbm/ft**2", - ) - prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, - val=0.95, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, - val=16.5, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" - ) - prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, - val=0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, - val=0.2, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, - val=0.21366, - units="lbm/lbf", - ) - prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, - val=3, - units="lbm/ft**2", - ) - prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, - val=0.15, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, - val=0.0736, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, - val=0.112, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, - val=0.14, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Avionics.MASS, - val=1959.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, - val=1.65, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, - val=551.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, - val=11192.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, - val=5.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, - val=3.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, - val=50.0, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, - val=7.6, - units="lbm", - ) - prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, - val=12.0, - units="unitless", - ) - - prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, - val=102.5, - units="unitless", - ) - - prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, - val=128, - units="unitless", - ) - prob.model.set_input_defaults( - "static_analysis.total_mass.fuel_mass.fus_and_struct.pylon_len", - val=0, - units='ft', - ) - prob.model.set_input_defaults( - "static_analysis.total_mass.fuel_mass.fus_and_struct.MAT", val=0, - units='lbm' - ) - prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, - units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, - val=0, - units='lbm', - ) - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, - val=0.041, - units="unitless", - ) - prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" - ) - prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, - val=25.0, - units="deg", - ) - - return prob diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 45cbd12d5..df7ebe700 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1175,7 +1175,7 @@ "LEAPS1": 'aircraft.inputs.L0_overrides.weight_empty_margin' }, units='unitless', - desc='empty mass margin scalar', + desc='empty mass margin scaler', default_value=0.0, ) @@ -3308,21 +3308,6 @@ default_value=7.5, ) -add_meta_data( - # TODO get rid of this in favor of overriding. In GASP this depended on fus_SA_factor - Aircraft.Fuselage.PROVIDE_SURFACE_AREA, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - option=True, - default_value=True, - types=bool, - desc='if true the fuselage surface area is set to be fus_SA_factor, otherwise ' - 'it is calculated.') - add_meta_data( Aircraft.Fuselage.SEAT_PITCH, meta_data=_MetaData, @@ -3380,23 +3365,10 @@ default_value=None, ) -# TODO add preprocessing step to handle variable split then combine with WETTED_AREA_SCALER -add_meta_data( - Aircraft.Fuselage.WETTED_AREA_FACTOR, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SF_FAC', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - desc='fuselage wetted area adjustment factor, if this is >10, it is interpreted as the wetted area in ft**2', - default_value=1, -) - add_meta_data( Aircraft.Fuselage.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, + historical_name={"GASP": 'INGASP.SF_FAC', "FLOPS": 'AERIN.SWETF', # ['&DEFINE.AERIN.SWETF', 'AWETO.SWETF', ], "LEAPS1": 'aircraft.inputs.L0_aerodynamics.fuselage_wetted_area' }, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index b0498199f..b2c49ea6a 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -4,10 +4,8 @@ ''' -# --------------------------- -# Aircraft data hierarchy -# --------------------------- class Aircraft: + """Aircraft data hierarchy""" class AirConditioning: MASS = 'aircraft:air_conditioning:mass' @@ -339,12 +337,10 @@ class Fuselage: PILOT_COMPARTMENT_LENGTH = 'aircraft:fuselage:pilot_compartment_length' PLANFORM_AREA = 'aircraft:fuselage:planform_area' PRESSURE_DIFFERENTIAL = 'aircraft:fuselage:pressure_differential' - PROVIDE_SURFACE_AREA = 'aircraft:fuselage:provide_surface_area' SEAT_PITCH = 'aircraft:fuselage:seat_pitch' SEAT_WIDTH = 'aircraft:fuselage:seat_width' TAIL_FINENESS = 'aircraft:fuselage:tail_fineness' WETTED_AREA = 'aircraft:fuselage:wetted_area' - WETTED_AREA_FACTOR = 'aircraft:fuselage:wetted_area_factor' WETTED_AREA_SCALER = 'aircraft:fuselage:wetted_area_scaler' class HorizontalTail: @@ -608,6 +604,7 @@ class Wing: class Dynamic: + """Dynamic mission data hierarchy""" class Mission: # all time-dependent variables used during mission analysis @@ -665,6 +662,7 @@ class Mission: class Mission: + """mission data hierarchy""" class Constraints: # these can be residuals (for equality constraints), @@ -786,6 +784,7 @@ class Taxi: class Settings: + """Setting data hierarchy""" EQUATIONS_OF_MOTION = 'settings:equations_of_motion' MASS_METHOD = 'settings:mass_method' PROBLEM_TYPE = 'settings:problem_type'