From c5fc8ff1dc3a16465bf08e991e45e59bf9c76bd4 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 1 Apr 2026 19:44:57 -0400 Subject: [PATCH 01/26] fixed a typo --- aviary/docs/theory_guide/gasp_based_bwb.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/docs/theory_guide/gasp_based_bwb.ipynb b/aviary/docs/theory_guide/gasp_based_bwb.ipynb index 70fb0a2ba0..fede47400e 100644 --- a/aviary/docs/theory_guide/gasp_based_bwb.ipynb +++ b/aviary/docs/theory_guide/gasp_based_bwb.ipynb @@ -439,7 +439,7 @@ "- Aviary does not have winglet geometry.\n", "- In GASP, a pilot weight is 170 lb and in Aviary it is 198 lb. In GASP, each attendant weights 130 lb and in Aviary it is 177 lb.\n", "- GASP has fuselage acoustic treatment.\n", - "- GASP conputes tip tank weight.\n", + "- GASP computes tip tank weight.\n", "- GASP allows canard configurations.\n" ] } From 2d24374c258734641ca1aac718199be38c0ade70 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 1 Apr 2026 19:46:40 -0400 Subject: [PATCH 02/26] remove FormFactorAndSIWB from AeroSetup --- aviary/subsystems/aerodynamics/gasp_based/gaspaero.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index b53abd34b3..c4f81f6bc0 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -1162,7 +1162,6 @@ def setup(self): ], ) - self.add_subsystem('form_factor', FormFactorAndSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) @@ -1221,7 +1220,6 @@ def setup(self): ], ) - self.add_subsystem('form_factor', BWBFormFactorAndSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) From 7d5c06accfd3da159c61c039dd756ddd7c51b420 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 1 Apr 2026 19:48:20 -0400 Subject: [PATCH 03/26] move FormFactorAndSIWB and BWBFormFactorAndSIWB to premissionaero from aerosetup --- .../gasp_based/premission_aero.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index e9275765e1..27f038fef8 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -10,12 +10,17 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import ( BasicFlapsGeometry, ) +from aviary.subsystems.aerodynamics.gasp_based.gaspaero import ( + BWBFormFactorAndSIWB, + FormFactorAndSIWB, +) from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors from aviary.subsystems.aerodynamics.gasp_based.interference import ( WingFuselageInterferencePremission, ) from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.variable_info.enums import SpeedType +from aviary.variable_info.enums import AircraftTypes, SpeedType +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission # TODO: add subsystems to compute CLMXFU, CLMXTO, CLMXLD using dynamic aero components @@ -25,6 +30,9 @@ class PreMissionAero(om.Group): """Takeoff and landing flaps modeling.""" + def initialize(self): + add_aviary_option(self, Aircraft.Design.TYPE) + def setup(self): self.add_subsystem( 'wing_fus_interference_premission', @@ -150,6 +158,22 @@ def setup(self): self.set_input_defaults('slat_defl_up', 0) self.set_input_defaults(Aircraft.Wing.SWEEP, units='deg') + design_type = self.options[Aircraft.Design.TYPE] + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'form_factor', + BWBFormFactorAndSIWB(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'form_factor', + FormFactorAndSIWB(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + def configure(self): # set default trailing edge deflection angle per GASP # TODO: This hidden default behavior needs to be moved to the pre-processor. From 17eb4c30f3886e4c845ac5cbbebaa6676f79389a Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 13:58:58 -0400 Subject: [PATCH 04/26] roll back to main --- .../aerodynamics/gasp_based/gaspaero.py | 2 ++ .../gasp_based/premission_aero.py | 26 +------------------ 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index ed0c5a30dd..5c03c381a8 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -1162,6 +1162,7 @@ def setup(self): ], ) + self.add_subsystem('form_factor', FormFactorAndSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) @@ -1220,6 +1221,7 @@ def setup(self): ], ) + self.add_subsystem('form_factor', BWBFormFactorAndSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index a53eea65db..2023e6407e 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -10,17 +10,12 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import ( BasicFlapsGeometry, ) -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import ( - BWBFormFactorAndSIWB, - FormFactorAndSIWB, -) from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors from aviary.subsystems.aerodynamics.gasp_based.interference import ( WingFuselageInterferencePremission, ) from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.variable_info.enums import AircraftTypes, SpeedType -from aviary.variable_info.functions import add_aviary_option +from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission # TODO: add subsystems to compute CLMXFU, CLMXTO, CLMXLD using dynamic aero components @@ -30,9 +25,6 @@ class PreMissionAero(om.Group): """Takeoff and landing flaps modeling.""" - def initialize(self): - add_aviary_option(self, Aircraft.Design.TYPE) - def setup(self): self.add_subsystem( 'wing_fus_interference_premission', @@ -158,22 +150,6 @@ def setup(self): self.set_input_defaults('slat_defl_up', 0) self.set_input_defaults(Aircraft.Wing.SWEEP, units='deg') - design_type = self.options[Aircraft.Design.TYPE] - if design_type is AircraftTypes.BLENDED_WING_BODY: - self.add_subsystem( - 'form_factor', - BWBFormFactorAndSIWB(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - else: - self.add_subsystem( - 'form_factor', - FormFactorAndSIWB(), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - def configure(self): # set default trailing edge deflection angle per GASP # TODO: This hidden default behavior needs to be moved to the pre-processor. From c7fe268458e49ec1b92679748d830e998e32cc17 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 15:06:57 -0400 Subject: [PATCH 05/26] add use_tempdirs --- .../gasp_based/test/test_gaspaero.py | 80 +++++++++++++++---- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 5efdad72ae..0f16256c09 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -6,25 +6,28 @@ import openmdao.api as om import pandas as pd from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.aerodynamics.gasp_based.gaspaero import ( AeroGeom, CruiseAero, DragCoef, DragCoefClean, - FormFactorAndSIWB, + FormFactor, GroundEffect, LiftCoeff, LiftCoeffClean, LowSpeedAero, + SIWB, UFac, Xlifts, WingTailRatios, BWBBodyLiftCurveSlope, - BWBFormFactorAndSIWB, + BWBFormFactor, BWBLiftCoeff, BWBLiftCoeffClean, BWBAeroSetup, + BWBSIWB, ) from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_model_options @@ -38,6 +41,7 @@ setup_data = json.load(file) +@use_tempdirs class GASPAeroTest(unittest.TestCase): """ Test overall pre-mission and mission aero systems in cruise and near-ground flight. @@ -537,54 +541,100 @@ def test_case3(self): assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) -class FormFactorAndSIWBTest(unittest.TestCase): +class FormFactorTest(unittest.TestCase): """Test fuselage form factor computation and SIWB computation""" def test_case1(self): prob = om.Problem() prob.model.add_subsystem( - 'form_factor', - FormFactorAndSIWB(), + 'formfactor', + FormFactor(), promotes=['*'], ) prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') - prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') prob.setup(check=False, force_alloc_complex=True) prob.run_model() tol = 1e-5 assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class SIWBTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'siwb_comp', + SIWB(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 assert_near_equal(prob['siwb'], 0.964972794, tol) partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) -class BWBFormFactorAndSIWBTest(unittest.TestCase): +class BWBFormFactorTest(unittest.TestCase): """Test fuselage form factor computation and SIWB computation""" def test_case1(self): prob = om.Problem() prob.model.add_subsystem( - 'form_factor', - BWBFormFactorAndSIWB(), + 'formfactor', + BWBFormFactor(), promotes=['*'], ) prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, val=19.365, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') - prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') prob.setup(check=False, force_alloc_complex=True) prob.run_model() tol = 1e-5 assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class BWBSIWBTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'siwb_comp', + BWBSIWB(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 assert_near_equal(prob['siwb'], 0.964972794, tol) partial_data = prob.check_partials(out_stream=None, method='cs') @@ -750,7 +800,7 @@ def test_case1(self): Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' ) - # BWBFormFactorAndSIWB + # BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') @@ -1242,7 +1292,7 @@ def setUp(self): Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' ) - # BWBAeroSetup/BWBFormFactorAndSIWB + # BWBAeroSetup/BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') @@ -1427,7 +1477,7 @@ def setUp(self): Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' ) - # BWBAeroSetup/BWBFormFactorAndSIWB + # BWBAeroSetup/BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') @@ -1567,7 +1617,7 @@ def setUp(self): Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' ) - # BWBAeroSetup/BWBFormFactorAndSIWB + # BWBAeroSetup/BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') @@ -1716,7 +1766,7 @@ def setUp(self): Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' ) - # BWBAeroSetup/BWBFormFactorAndSIWB + # BWBAeroSetup/BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') From ebfdcde97d3936977189193ed5780566ff1b8da3 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 15:07:37 -0400 Subject: [PATCH 06/26] separate FormFactor and SIWB components --- .../aerodynamics/gasp_based/gaspaero.py | 167 ++++++++++++------ 1 file changed, 110 insertions(+), 57 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index 5c03c381a8..482201fedb 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -410,9 +410,9 @@ def compute(self, inputs, outputs): outputs['lift_ratio'] = lift_ratio -class FormFactorAndSIWB(om.ExplicitComponent): +class FormFactor(om.ExplicitComponent): """ - Compute body form factor and SIWB for tube+wing aircraft + Compute body form factor Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. """ @@ -422,7 +422,6 @@ def initialize(self): def setup(self): add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') - add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') add_aviary_output( self, @@ -430,11 +429,6 @@ def setup(self): units='unitless', desc='FFFUS: fuselage form factor', ) - self.add_output( - 'siwb', - units='unitless', - desc='SIWB: curve fitting correction factor for Oswald efficiency', - ) def setup_partials(self): self.declare_partials( @@ -444,41 +438,24 @@ def setup_partials(self): Aircraft.Fuselage.LENGTH, ], ) - self.declare_partials( - 'siwb', - [ - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.SPAN, - ], - ) def compute(self, inputs, outputs): verbosity = self.options[Settings.VERBOSITY] fus_len = inputs[Aircraft.Fuselage.LENGTH] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - wingspan = inputs[Aircraft.Wing.SPAN] if fus_len == 0.0: if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactorAndSIWB.') - if wingspan == 0.0: - if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in FormFactorAndSIWB.') + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactor.') # fuselage form drag factor fffus = 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus - # fuselage width over wing span - wfob = cabin_width / wingspan - siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 - outputs['siwb'] = siwb - def compute_partials(self, inputs, J): fus_len = inputs[Aircraft.Fuselage.LENGTH] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - wingspan = inputs[Aircraft.Wing.SPAN] dfffus_dcabin_width = ( 2.25 * (cabin_width / fus_len) ** 0.5 / fus_len @@ -489,6 +466,56 @@ def compute_partials(self, inputs, J): - 21.0 * (cabin_width / fus_len) ** 2.0 * cabin_width / fus_len**2.0 ) + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.AVG_DIAMETER] = dfffus_dcabin_width + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len + + +class SIWB(om.ExplicitComponent): + """ + Compute SIWB for tube+wing aircraft + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + + self.add_output( + 'siwb', + units='unitless', + desc='SIWB: curve fitting correction factor for Oswald efficiency', + ) + + def setup_partials(self): + self.declare_partials( + 'siwb', + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + if wingspan == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in SIWB.') + + # fuselage width over wing span + wfob = cabin_width / wingspan + siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + outputs['siwb'] = siwb + + def compute_partials(self, inputs, J): + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + wfob = cabin_width / wingspan # siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 @@ -506,13 +533,11 @@ def compute_partials(self, inputs, J): - 4 * 6.0606 * wfob**3 * cabin_width / wingspan**2 ) - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.AVG_DIAMETER] = dfffus_dcabin_width - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len J['siwb', Aircraft.Fuselage.AVG_DIAMETER] = dsiwb_dcabin_width J['siwb', Aircraft.Wing.SPAN] = dsiwb_dwingspan -class BWBFormFactorAndSIWB(om.ExplicitComponent): +class BWBFormFactor(om.ExplicitComponent): """ Compute body form factor and SIWB for BWB aircraft Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. @@ -524,18 +549,12 @@ def initialize(self): def setup(self): add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') - add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') self.add_output( Aircraft.Fuselage.FORM_FACTOR, units='unitless', desc='FFFUS: fuselage form factor', ) - self.add_output( - 'siwb', - units='unitless', - desc='SIWB: curve fitting correction factor for Oswald efficiency', - ) def setup_partials(self): self.declare_partials( @@ -545,41 +564,24 @@ def setup_partials(self): Aircraft.Fuselage.LENGTH, ], ) - self.declare_partials( - 'siwb', - [ - Aircraft.Fuselage.HYDRAULIC_DIAMETER, - Aircraft.Wing.SPAN, - ], - ) def compute(self, inputs, outputs): verbosity = self.options[Settings.VERBOSITY] fus_len = inputs[Aircraft.Fuselage.LENGTH] diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] - wingspan = inputs[Aircraft.Wing.SPAN] if fus_len == 0.0: if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactorAndSIWB.') - if wingspan == 0.0: - if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in FormFactorAndSIWB.') + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in BWBFormFactor.') # fuselage form drag factor fffus = 1 + 1.5 * (diam / fus_len) ** 1.5 + 7 * (diam / fus_len) ** 3 outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus - # hydraulic diameter over wing span - wfob = diam / wingspan - siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 - outputs['siwb'] = siwb - def compute_partials(self, inputs, J): fus_len = inputs[Aircraft.Fuselage.LENGTH] diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] - wingspan = inputs[Aircraft.Wing.SPAN] dfffus_ddiam = ( 2.25 * (diam / fus_len) ** 0.5 / fus_len + 21 * (diam / fus_len) ** 2.0 / fus_len @@ -589,6 +591,57 @@ def compute_partials(self, inputs, J): - 21.0 * (diam / fus_len) ** 2.0 * diam / fus_len**2.0 ) + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dfffus_ddiam + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len + + +class BWBSIWB(om.ExplicitComponent): + """ + Compute body form factor and SIWB for BWB aircraft + Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + + self.add_output( + 'siwb', + units='unitless', + desc='SIWB: curve fitting correction factor for Oswald efficiency', + ) + + def setup_partials(self): + self.declare_partials( + 'siwb', + [ + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Aircraft.Wing.SPAN, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + if wingspan == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in BWBSIWB.') + + # hydraulic diameter over wing span + wfob = diam / wingspan + siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + outputs['siwb'] = siwb + + def compute_partials(self, inputs, J): + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + wfob = diam / wingspan # siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 @@ -606,8 +659,6 @@ def compute_partials(self, inputs, J): - 4 * 6.0606 * wfob**3 * diam / wingspan**2 ) - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dfffus_ddiam - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len J['siwb', Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dsiwb_ddiam J['siwb', Aircraft.Wing.SPAN] = dsiwb_dwingspan @@ -1162,7 +1213,8 @@ def setup(self): ], ) - self.add_subsystem('form_factor', FormFactorAndSIWB(), promotes=['*']) + self.add_subsystem('form_factor', FormFactor(), promotes=['*']) + self.add_subsystem('siwbcomp', SIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) @@ -1221,7 +1273,8 @@ def setup(self): ], ) - self.add_subsystem('form_factor', BWBFormFactorAndSIWB(), promotes=['*']) + self.add_subsystem('form_factor', BWBFormFactor(), promotes=['*']) + self.add_subsystem('siwbcomp', BWBSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) From 118769674cb7a6a7b948ebcc2daf49111bc7456d Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:04:13 -0400 Subject: [PATCH 07/26] remove FormFactor from setup --- aviary/subsystems/aerodynamics/gasp_based/gaspaero.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index 482201fedb..effbb3955a 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -1213,7 +1213,7 @@ def setup(self): ], ) - self.add_subsystem('form_factor', FormFactor(), promotes=['*']) + # self.add_subsystem('form_factor', FormFactor(), promotes=['*']) self.add_subsystem('siwbcomp', SIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) @@ -1273,7 +1273,7 @@ def setup(self): ], ) - self.add_subsystem('form_factor', BWBFormFactor(), promotes=['*']) + # self.add_subsystem('form_factor', BWBFormFactor(), promotes=['*']) self.add_subsystem('siwbcomp', BWBSIWB(), promotes=['*']) self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) From 2e563ba1da2fbc7189c3a64408fc966bcb075f08 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:04:55 -0400 Subject: [PATCH 08/26] add FormFactor to premission --- .../gasp_based/premission_aero.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index 2023e6407e..fcc6a3e3f1 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -11,11 +11,13 @@ BasicFlapsGeometry, ) from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors +from aviary.subsystems.aerodynamics.gasp_based.gaspaero import FormFactor, BWBFormFactor from aviary.subsystems.aerodynamics.gasp_based.interference import ( WingFuselageInterferencePremission, ) from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.variable_info.enums import SpeedType +from aviary.variable_info.enums import AircraftTypes, SpeedType +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission # TODO: add subsystems to compute CLMXFU, CLMXTO, CLMXLD using dynamic aero components @@ -25,6 +27,9 @@ class PreMissionAero(om.Group): """Takeoff and landing flaps modeling.""" + def initialize(self): + add_aviary_option(self, Aircraft.Design.TYPE) + def setup(self): self.add_subsystem( 'wing_fus_interference_premission', @@ -43,6 +48,22 @@ def setup(self): promotes_outputs=['*'], ) + design_type = self.options[Aircraft.Design.TYPE] + if design_type is AircraftTypes.TRANSPORT: + self.add_subsystem( + 'aero_form_factors2', + FormFactor(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'aero_form_factors2', + BWBFormFactor(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + # speeds weren't originally computed here, speedtype of Mach is intended # to avoid multiple sources for computed Mach (gets calculated somewhere upstream) self.add_subsystem( From 28d0d748cb796e38a6fac5df8c1b002cb4b3ba9a Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:05:12 -0400 Subject: [PATCH 09/26] split FormFactorAndSIWB to FormFactor and SIWB --- aviary/docs/theory_guide/gasp_based_bwb.ipynb | 11 +++++++---- .../subsystems/blended_wing_body_GASP.ipynb | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/aviary/docs/theory_guide/gasp_based_bwb.ipynb b/aviary/docs/theory_guide/gasp_based_bwb.ipynb index 2b715a71a5..b0286d7e9f 100644 --- a/aviary/docs/theory_guide/gasp_based_bwb.ipynb +++ b/aviary/docs/theory_guide/gasp_based_bwb.ipynb @@ -319,7 +319,8 @@ " AeroGeom,\n", " BWBAeroSetup,\n", " BWBBodyLiftCurveSlope,\n", - " BWBFormFactorAndSIWB,\n", + " BWBFormFactor,\n", + " BWBSIWB,\n", " BWBLiftCoeff,\n", " BWBLiftCoeffClean,\n", " CruiseAero,\n", @@ -330,7 +331,8 @@ "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", "\n", "glue_variable(get_variable_name(BWBBodyLiftCurveSlope), md_code=True)\n", - "glue_variable(get_variable_name(BWBFormFactorAndSIWB), md_code=True)\n", + "glue_variable(get_variable_name(BWBFormFactor), md_code=True)\n", + "glue_variable(get_variable_name(BWBSIWB), md_code=True)\n", "glue_variable(get_variable_name(BWBAeroSetup), md_code=True)\n", "glue_variable(get_variable_name(BWBLiftCoeff), md_code=True)\n", "glue_variable(get_variable_name(BWBLiftCoeffClean), md_code=True)\n", @@ -366,7 +368,8 @@ "This feature implements GASP aerodynamics subsystems for BWB aircraft. Five new components are added:\n", "\n", "- {glue:md}`BWBBodyLiftCurveSlope`\n", - "- {glue:md}`BWBFormFactorAndSIWB`\n", + "- {glue:md}`BWBFormFactor`\n", + "- {glue:md}`BWBSIWB`\n", "- {glue:md}`BWBAeroSetup`\n", "- {glue:md}`BWBLiftCoeff`\n", "- {glue:md}`BWBLiftCoeffClean`\n", @@ -439,7 +442,7 @@ "- Aviary does not have winglet geometry.\n", "- In GASP, a pilot weight is 170 lb and in Aviary it is 198 lb. In GASP, each attendant weights 130 lb and in Aviary it is 177 lb.\n", "- GASP has fuselage acoustic treatment.\n", - "- GASP computes tip tank weight.\n", + "- GASP conputes tip tank weight.\n", "- GASP allows canard configurations.\n" ] } 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 5142a209f0..81a141a2ec 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 @@ -223,7 +223,7 @@ " BWBBodyLiftCurveSlope,\n", " AeroGeom,\n", " AeroSetup,\n", - " FormFactorAndSIWB,\n", + " SIWB,\n", " UFac,\n", " BWBBodyLiftCurveSlope,\n", ")\n", @@ -240,7 +240,7 @@ "[cl, cd] = get_all_non_aviary_names(AeroForces, include_in_out='in')\n", "glue_variable('CL', cl, md_code=True)\n", "glue_variable('CD', cd, md_code=True)\n", - "siwb = get_all_non_aviary_names(FormFactorAndSIWB)[0]\n", + "siwb = get_all_non_aviary_names(SIWB)[0]\n", "glue_variable('siwb', siwb, md_code=True)\n", "ufac = get_all_non_aviary_names(UFac, include_in_out='out')[0]\n", "glue_variable('ufac', ufac, md_code=True)\n", From 465b4a73743897d643abb65bf073ad88c0996723 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:06:12 -0400 Subject: [PATCH 10/26] work in progress --- .../aerodynamics/gasp_based/test/test_gaspaero.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 0f16256c09..75b9f67033 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -811,6 +811,9 @@ def test_case1(self): prob.model.set_input_defaults( Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' ) + + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') @@ -867,7 +870,7 @@ def test_case1(self): assert_near_equal(prob['SA6'], [2.09276756, 2.09276756], tol) assert_near_equal(prob['SA7'], [0.03978045, 0.03978045], tol) - assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024721, tol) + # assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024721, tol) assert_near_equal(prob['siwb'], 0.96497277, tol) @@ -1878,4 +1881,7 @@ def test_case1(self): if __name__ == '__main__': - unittest.main() + # unittest.main() + test = BWBCruiseAeroTest() + test.setUp() + test.test_case1() From dbd2ab77ef45ffbc283df2c17e2400af5e4a7b37 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:27:51 -0400 Subject: [PATCH 11/26] work in progress --- .../aerodynamics/gasp_based/test/test_gaspaero.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 75b9f67033..a28d921d6c 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -1389,6 +1389,7 @@ def test_case1(self): prob.model.set_input_defaults( Dynamic.Vehicle.ANGLE_OF_ATTACK, [3.611767, 3.611767], units='deg' ) + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') setup_model_options(prob, options) @@ -1423,6 +1424,7 @@ def test_case2(self): # CLFromLift prob.model.set_input_defaults('lift_req', [817.74, 817.74], units='lbf') + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') setup_model_options(prob, options) @@ -1558,6 +1560,8 @@ def test_case1(self): promotes=['*'], ) + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') + setup_model_options(prob, options) prob.setup(check=False, force_alloc_complex=True) @@ -1684,6 +1688,7 @@ def setUp(self): # AeroForces prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') options = self.options setup_model_options(prob, options) @@ -1833,6 +1838,7 @@ def setUp(self): # AeroForces prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') options = self.options setup_model_options(prob, options) @@ -1881,7 +1887,7 @@ def test_case1(self): if __name__ == '__main__': - # unittest.main() - test = BWBCruiseAeroTest() + unittest.main() + test = BWBLowSpeedAeroTest3() test.setUp() - test.test_case1() + # test.test_case1() From 7f1d79ae08bc528e5ebe1eaf242722b29b0b4636 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 17:41:06 -0400 Subject: [PATCH 12/26] work in progress --- .../aerodynamics/gasp_based/test/test_gaspaero.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index a28d921d6c..de4f9582af 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -85,6 +85,11 @@ def test_cruise(self): prob.run_model() + import pdb + + x = prob[Aircraft.Fuselage.FORM_FACTOR] + print(f'x = {x}') + pdb.set_trace() assert_near_equal(prob['CL'][0], row['cl'], tolerance=self.cruise_tol) assert_near_equal(prob['CD'][0], row['cd'], tolerance=self.cruise_tol) @@ -1887,7 +1892,7 @@ def test_case1(self): if __name__ == '__main__': - unittest.main() - test = BWBLowSpeedAeroTest3() + # unittest.main() + test = GASPAeroTest() test.setUp() - # test.test_case1() + test.test_cruise() From 3bce50a59717b5641ba292b3d9467061a380bdf9 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 18:14:40 -0400 Subject: [PATCH 13/26] add Aircraft.Fuselage.FORM_FACTOR to premission --- .../gasp_based/test/test_gaspaero.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index de4f9582af..53f4553a01 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -70,6 +70,8 @@ def test_cruise(self): # extra params needed for cruise aero prob.set_val(Aircraft.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, setup_data['clmwfu']) prob.set_val(Aircraft.Design.DRAG_DIVERGENCE_SHIFT, setup_data['scfac']) + # FormFactor + prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) for i, row in cruise_data.iterrows(): alt = row['alt'] @@ -85,11 +87,6 @@ def test_cruise(self): prob.run_model() - import pdb - - x = prob[Aircraft.Fuselage.FORM_FACTOR] - print(f'x = {x}') - pdb.set_trace() assert_near_equal(prob['CL'][0], row['cl'], tolerance=self.cruise_tol) assert_near_equal(prob['CD'][0], row['cd'], tolerance=self.cruise_tol) @@ -120,6 +117,8 @@ def test_ground(self): prob.set_val('airport_alt', 0.0) # not defined in standalone aero prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, setup_data['cfoc']) prob.set_val(Aircraft.Design.GROSS_MASS, setup_data['wgto']) + # FormFactor + prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) for i, row in ground_data.iterrows(): ilift = row['ilift'] # 2: takeoff, 3: landing @@ -195,6 +194,8 @@ def test_ground_alpha_out(self): setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) prob.setup(check=False, force_alloc_complex=True) + # FormFactor + prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) _init_geom(prob) @@ -762,6 +763,7 @@ def test_case1(self): assert_near_equal(prob['SA7'], [0.03978045, 0.03978045], tol) +@use_tempdirs class BWBAeroSetupTest(unittest.TestCase): def test_case1(self): options = get_option_defaults() @@ -816,7 +818,7 @@ def test_case1(self): prob.model.set_input_defaults( Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' ) - + # FormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') @@ -875,7 +877,6 @@ def test_case1(self): assert_near_equal(prob['SA6'], [2.09276756, 2.09276756], tol) assert_near_equal(prob['SA7'], [0.03978045, 0.03978045], tol) - # assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024721, tol) assert_near_equal(prob['siwb'], 0.96497277, tol) @@ -1262,6 +1263,7 @@ def test_case2(self): assert_near_equal(prob['CD'], [0.01465816, 0.0156808], tol) +@use_tempdirs class BWBCruiseAeroTest(unittest.TestCase): def setUp(self): self.options = options = get_option_defaults() @@ -1394,6 +1396,7 @@ def test_case1(self): prob.model.set_input_defaults( Dynamic.Vehicle.ANGLE_OF_ATTACK, [3.611767, 3.611767], units='deg' ) + # BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') setup_model_options(prob, options) @@ -1429,6 +1432,7 @@ def test_case2(self): # CLFromLift prob.model.set_input_defaults('lift_req', [817.74, 817.74], units='lbf') + # BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') setup_model_options(prob, options) @@ -1449,6 +1453,7 @@ def test_case2(self): assert_near_equal(prob[Dynamic.Vehicle.DRAG], [41.8535328, 41.8535328], tol) +@use_tempdirs class BWBLowSpeedAeroTest1(unittest.TestCase): def setUp(self): self.options = options = get_option_defaults() @@ -1565,6 +1570,7 @@ def test_case1(self): promotes=['*'], ) + # BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') setup_model_options(prob, options) @@ -1590,6 +1596,7 @@ def test_case1(self): assert_near_equal(prob[Dynamic.Vehicle.DRAG], [37.73329763, 37.73329763], tol) +@use_tempdirs class BWBLowSpeedAeroTest2(unittest.TestCase): def setUp(self): self.options = options = get_option_defaults() @@ -1693,6 +1700,7 @@ def setUp(self): # AeroForces prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + # BWBFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') options = self.options @@ -1740,6 +1748,7 @@ def test_case1(self): assert_near_equal(CL_over_CD, [CL_Over_CDs[i], CL_Over_CDs[i]], tol) +@use_tempdirs class BWBLowSpeedAeroTest3(unittest.TestCase): def setUp(self): self.options = options = get_option_defaults() @@ -1843,6 +1852,7 @@ def setUp(self): # AeroForces prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + # bwbFormFactor prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') options = self.options @@ -1892,7 +1902,4 @@ def test_case1(self): if __name__ == '__main__': - # unittest.main() - test = GASPAeroTest() - test.setUp() - test.test_cruise() + unittest.main() From 9e4fba118ad449c426f63ee585eb9303b7e9c976 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 18:28:22 -0400 Subject: [PATCH 14/26] add Aircraft.Fuselage.FORM_FACTOR to aero builder --- aviary/subsystems/aerodynamics/aerodynamics_builder.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aviary/subsystems/aerodynamics/aerodynamics_builder.py b/aviary/subsystems/aerodynamics/aerodynamics_builder.py index 7177dcdcb5..be20b5d078 100644 --- a/aviary/subsystems/aerodynamics/aerodynamics_builder.py +++ b/aviary/subsystems/aerodynamics/aerodynamics_builder.py @@ -786,6 +786,7 @@ def report(self, prob, reports_folder, **kwargs): Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.WETTED_AREA, + Aircraft.Fuselage.FORM_FACTOR, Aircraft.HorizontalTail.AREA, Aircraft.HorizontalTail.AVERAGE_CHORD, Aircraft.HorizontalTail.FORM_FACTOR, From 410cb775f2ccd6cde0d1fd2b7146f150ceb11644 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 20:04:31 -0400 Subject: [PATCH 15/26] add Aircraft.Fuselage.FORM_FACTOR --- aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py | 1 + aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py | 2 ++ aviary/mission/two_dof/ode/test/test_flight_ode.py | 4 ++++ aviary/mission/two_dof/ode/test/test_flight_path_ode.py | 2 ++ aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py | 1 + aviary/mission/two_dof/ode/test/test_takeoff_ode.py | 3 +++ 6 files changed, 13 insertions(+) diff --git a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py index 7e39ea452b..031a76e53e 100644 --- a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py +++ b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py @@ -47,6 +47,7 @@ def test_groundroll_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py index f8009a9745..8cbb1afa2d 100644 --- a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py @@ -48,6 +48,7 @@ def test_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) @@ -112,6 +113,7 @@ def test_electric_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) diff --git a/aviary/mission/two_dof/ode/test/test_flight_ode.py b/aviary/mission/two_dof/ode/test/test_flight_ode.py index a5d76aa23a..2dbb0b2775 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_ode.py +++ b/aviary/mission/two_dof/ode/test/test_flight_ode.py @@ -59,6 +59,7 @@ def test_start_of_climb(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) @@ -105,6 +106,7 @@ def test_end_of_climb(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) @@ -170,6 +172,7 @@ def test_high_alt(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) @@ -215,6 +218,7 @@ def test_low_alt(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) diff --git a/aviary/mission/two_dof/ode/test/test_flight_path_ode.py b/aviary/mission/two_dof/ode/test/test_flight_path_ode.py index 53b7021251..ae25b14f2c 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_path_ode.py +++ b/aviary/mission/two_dof/ode/test/test_flight_path_ode.py @@ -49,6 +49,7 @@ def test_case1(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() testvals = { @@ -88,6 +89,7 @@ def test_case2(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() testvals = { diff --git a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py index c1fb6ea9fc..cc98a66b12 100644 --- a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py @@ -45,6 +45,7 @@ def test_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.set_val('time', np.array([0, 8280.30660691]), units='s') set_params_for_unit_tests(self.prob) diff --git a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py index f54c4e9d76..69a88804a9 100644 --- a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py +++ b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py @@ -49,6 +49,7 @@ def test_groundroll_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.set_val(Dynamic.Mission.VELOCITY, [75, 150], units='kn') self.prob.set_val(Dynamic.Vehicle.MASS, [100000, 100000], units='lbm') @@ -105,6 +106,7 @@ def test_rotation_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) @@ -166,6 +168,7 @@ def test_ascent_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) From 2071c4d2bc24817014d957b61ea80147ef59f756 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 20:54:19 -0400 Subject: [PATCH 16/26] set Aircraft.Fuselage.FORM_FACTOR --- aviary/mission/two_dof/ode/params.py | 2 +- aviary/mission/two_dof/ode/test/test_flight_ode.py | 8 ++++---- aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py | 2 +- aviary/mission/two_dof/ode/test/test_takeoff_ode.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/aviary/mission/two_dof/ode/params.py b/aviary/mission/two_dof/ode/params.py index 4fdd61ebb8..cebf9eb0b8 100644 --- a/aviary/mission/two_dof/ode/params.py +++ b/aviary/mission/two_dof/ode/params.py @@ -124,7 +124,7 @@ def promote_params(sys, trajs=None, phases=None): Aircraft.Wing.VERTICAL_MOUNT_LOCATION: dict(units='unitless', val=0), Aircraft.Design.STATIC_MARGIN: dict(units='unitless', val=0.03), Aircraft.Design.CG_DELTA: dict(units='unitless', val=0.25), - Aircraft.Fuselage.FORM_FACTOR: dict(units='unitless', val=1.25), + Aircraft.Fuselage.FORM_FACTOR: dict(units='unitless', val=1.05557953), Aircraft.Nacelle.FORM_FACTOR: dict(units='unitless', val=1.5), Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units='unitless', val=1.1), Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units='unitless', val=0.00175), diff --git a/aviary/mission/two_dof/ode/test/test_flight_ode.py b/aviary/mission/two_dof/ode/test/test_flight_ode.py index 2dbb0b2775..e497ced028 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_ode.py +++ b/aviary/mission/two_dof/ode/test/test_flight_ode.py @@ -59,9 +59,9 @@ def test_start_of_climb(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() @@ -106,9 +106,9 @@ def test_end_of_climb(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() @@ -172,9 +172,9 @@ def test_high_alt(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() @@ -218,9 +218,9 @@ def test_low_alt(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py index cc98a66b12..995380f598 100644 --- a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py @@ -45,10 +45,10 @@ def test_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.set_val('time', np.array([0, 8280.30660691]), units='s') set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py index 69a88804a9..776df428c3 100644 --- a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py +++ b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py @@ -168,9 +168,9 @@ def test_ascent_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) + self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() From d6a41ea5cb5ec39d320e65fde74c0add7554e51c Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 21:25:34 -0400 Subject: [PATCH 17/26] remove Aircraft.Fuselage.FORM_FACTOR from individual unit tests because it is set by set_params_for_unit_tests() already. --- aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py | 1 - aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py | 1 - aviary/mission/two_dof/ode/test/test_flight_ode.py | 1 - aviary/mission/two_dof/ode/test/test_flight_path_ode.py | 1 - aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py | 1 - aviary/mission/two_dof/ode/test/test_takeoff_ode.py | 1 - 6 files changed, 6 deletions(-) diff --git a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py index 031a76e53e..7e39ea452b 100644 --- a/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py +++ b/aviary/mission/solved_two_dof/ode/test/test_groundroll_ode.py @@ -47,7 +47,6 @@ def test_groundroll_partials(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py index 8cbb1afa2d..047e535a5d 100644 --- a/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_breguet_cruise_ode.py @@ -113,7 +113,6 @@ def test_electric_cruise(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) set_params_for_unit_tests(self.prob) diff --git a/aviary/mission/two_dof/ode/test/test_flight_ode.py b/aviary/mission/two_dof/ode/test/test_flight_ode.py index e497ced028..791b5c9764 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_ode.py +++ b/aviary/mission/two_dof/ode/test/test_flight_ode.py @@ -174,7 +174,6 @@ def test_high_alt(self): self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_flight_path_ode.py b/aviary/mission/two_dof/ode/test/test_flight_path_ode.py index ae25b14f2c..fddc910098 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_path_ode.py +++ b/aviary/mission/two_dof/ode/test/test_flight_path_ode.py @@ -89,7 +89,6 @@ def test_case2(self): self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() testvals = { diff --git a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py index 995380f598..c1fb6ea9fc 100644 --- a/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py +++ b/aviary/mission/two_dof/ode/test/test_simple_cruise_ode.py @@ -48,7 +48,6 @@ def test_cruise(self): self.prob.set_val('time', np.array([0, 8280.30660691]), units='s') set_params_for_unit_tests(self.prob) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() diff --git a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py index 776df428c3..c108b9e4ee 100644 --- a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py +++ b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py @@ -170,7 +170,6 @@ def test_ascent_partials(self): self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) - self.prob.set_val(Aircraft.Fuselage.FORM_FACTOR, 1.05557953) self.prob.run_model() From 68aa42362c37a8913bb5650b9b1384639e74d6ef Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 3 Apr 2026 22:52:59 -0400 Subject: [PATCH 18/26] set aircraft:fuselage:form_factor --- .../benchmark_tests/test_problem_types_GwGm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py b/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py index 00df256fa0..ee791fbd23 100644 --- a/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py @@ -39,6 +39,9 @@ def test_off_design_IPOPT(self): 'aircraft:design:gross_mass', self.sized_mass, units='lbm' ) prob_fallout.aviary_inputs.set_val('mission:gross_mass', self.sized_mass, units='lbm') + prob_fallout.aviary_inputs.set_val( + 'aircraft:fuselage:form_factor', 1.05557953, units='unitless' + ) prob_fallout.check_and_preprocess_inputs() From 24fe162feffe33b8b55452e224a1eed44a4b8fb9 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 6 Apr 2026 14:58:10 -0400 Subject: [PATCH 19/26] update fuselage form factor --- .../models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv | 2 +- .../models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv index d9c6bcde77..ae9d3f0510 100644 --- a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv @@ -52,7 +52,7 @@ aircraft:fuel:wing_fuel_fraction,0.6,unitless aircraft:fuselage:aisle_width,24,inch aircraft:fuselage:delta_diameter,4.5,ft aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 -aircraft:fuselage:form_factor,1.25,unitless +aircraft:fuselage:form_factor,1.05557953,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless diff --git a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv index 1514e3c9fd..9682c230d1 100644 --- a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv @@ -54,7 +54,7 @@ aircraft:furnishings:mass,11192,lbm aircraft:fuselage:aisle_width,24,inch aircraft:fuselage:delta_diameter,4.5,ft aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 -aircraft:fuselage:form_factor,1.25,unitless +aircraft:fuselage:form_factor,1.05557953,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless From fe44f64bf8dfc9c1423dde7be5a5d9168ed9d0f2 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 6 Apr 2026 15:57:11 -0400 Subject: [PATCH 20/26] move FormFactor and BWBFormFactor to gasp_aero_coeffs.py --- .../gasp_based/gasp_aero_coeffs.py | 124 +++++++++++++++++- .../aerodynamics/gasp_based/gaspaero.py | 120 +---------------- .../gasp_based/premission_aero.py | 7 +- .../gasp_based/test/test_gasp_aero_coeffs.py | 58 +++++++- .../gasp_based/test/test_gaspaero.py | 53 +------- 5 files changed, 185 insertions(+), 177 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py b/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py index ecfc55445e..7d6532afb2 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py @@ -1,8 +1,10 @@ +import warnings import numpy as np import openmdao.api as om -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission +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, Settings SWETFCT = 1.02 @@ -181,3 +183,121 @@ def compute_partials(self, inputs, J): J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_DIAMETER] = 1.5 * 0.35 / xln J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_LENGTH] = -1.5 * 0.35 * dbarn / xln**2 + + +class FormFactor(om.ExplicitComponent): + """ + Compute body form factor + Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + + add_aviary_output( + self, + Aircraft.Fuselage.FORM_FACTOR, + units='unitless', + desc='FFFUS: fuselage form factor', + ) + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.FORM_FACTOR, + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.LENGTH, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + + if fus_len == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactor.') + + # fuselage form drag factor + fffus = 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 + outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus + + def compute_partials(self, inputs, J): + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + + dfffus_dcabin_width = ( + 2.25 * (cabin_width / fus_len) ** 0.5 / fus_len + + 21 * (cabin_width / fus_len) ** 2.0 / fus_len + ) + dfffus_dfus_len = ( + -2.25 * (cabin_width / fus_len) ** 0.5 * cabin_width / fus_len**2.0 + - 21.0 * (cabin_width / fus_len) ** 2.0 * cabin_width / fus_len**2.0 + ) + + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.AVG_DIAMETER] = dfffus_dcabin_width + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len + + +class BWBFormFactor(om.ExplicitComponent): + """ + Compute body form factor and SIWB for BWB aircraft + Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + + self.add_output( + Aircraft.Fuselage.FORM_FACTOR, + units='unitless', + desc='FFFUS: fuselage form factor', + ) + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.FORM_FACTOR, + [ + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Aircraft.Fuselage.LENGTH, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + fus_len = inputs[Aircraft.Fuselage.LENGTH] + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + + if fus_len == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in BWBFormFactor.') + + # fuselage form drag factor + fffus = 1 + 1.5 * (diam / fus_len) ** 1.5 + 7 * (diam / fus_len) ** 3 + outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus + + def compute_partials(self, inputs, J): + fus_len = inputs[Aircraft.Fuselage.LENGTH] + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + + dfffus_ddiam = ( + 2.25 * (diam / fus_len) ** 0.5 / fus_len + 21 * (diam / fus_len) ** 2.0 / fus_len + ) + dfffus_dfus_len = ( + -2.25 * (diam / fus_len) ** 0.5 * diam / fus_len**2.0 + - 21.0 * (diam / fus_len) ** 2.0 * diam / fus_len**2.0 + ) + + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dfffus_ddiam + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index effbb3955a..4c707d3355 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -8,7 +8,7 @@ from aviary.utils.math import sigmoidX, smooth_min, d_smooth_min from aviary.variable_info.enums import AircraftTypes, Verbosity from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output -from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings +from aviary.variable_info.variables import Aircraft, Dynamic, Settings # # data from EAERO @@ -410,66 +410,6 @@ def compute(self, inputs, outputs): outputs['lift_ratio'] = lift_ratio -class FormFactor(om.ExplicitComponent): - """ - Compute body form factor - Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. - """ - - def initialize(self): - add_aviary_option(self, Settings.VERBOSITY) - - def setup(self): - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') - add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') - - add_aviary_output( - self, - Aircraft.Fuselage.FORM_FACTOR, - units='unitless', - desc='FFFUS: fuselage form factor', - ) - - def setup_partials(self): - self.declare_partials( - Aircraft.Fuselage.FORM_FACTOR, - [ - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.LENGTH, - ], - ) - - def compute(self, inputs, outputs): - verbosity = self.options[Settings.VERBOSITY] - - fus_len = inputs[Aircraft.Fuselage.LENGTH] - cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - - if fus_len == 0.0: - if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactor.') - - # fuselage form drag factor - fffus = 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 - outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus - - def compute_partials(self, inputs, J): - fus_len = inputs[Aircraft.Fuselage.LENGTH] - cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - - dfffus_dcabin_width = ( - 2.25 * (cabin_width / fus_len) ** 0.5 / fus_len - + 21 * (cabin_width / fus_len) ** 2.0 / fus_len - ) - dfffus_dfus_len = ( - -2.25 * (cabin_width / fus_len) ** 0.5 * cabin_width / fus_len**2.0 - - 21.0 * (cabin_width / fus_len) ** 2.0 * cabin_width / fus_len**2.0 - ) - - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.AVG_DIAMETER] = dfffus_dcabin_width - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len - - class SIWB(om.ExplicitComponent): """ Compute SIWB for tube+wing aircraft @@ -537,64 +477,6 @@ def compute_partials(self, inputs, J): J['siwb', Aircraft.Wing.SPAN] = dsiwb_dwingspan -class BWBFormFactor(om.ExplicitComponent): - """ - Compute body form factor and SIWB for BWB aircraft - Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. - """ - - def initialize(self): - add_aviary_option(self, Settings.VERBOSITY) - - def setup(self): - add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') - add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') - - self.add_output( - Aircraft.Fuselage.FORM_FACTOR, - units='unitless', - desc='FFFUS: fuselage form factor', - ) - - def setup_partials(self): - self.declare_partials( - Aircraft.Fuselage.FORM_FACTOR, - [ - Aircraft.Fuselage.HYDRAULIC_DIAMETER, - Aircraft.Fuselage.LENGTH, - ], - ) - - def compute(self, inputs, outputs): - verbosity = self.options[Settings.VERBOSITY] - - fus_len = inputs[Aircraft.Fuselage.LENGTH] - diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] - - if fus_len == 0.0: - if verbosity > Verbosity.BRIEF: - warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in BWBFormFactor.') - - # fuselage form drag factor - fffus = 1 + 1.5 * (diam / fus_len) ** 1.5 + 7 * (diam / fus_len) ** 3 - outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus - - def compute_partials(self, inputs, J): - fus_len = inputs[Aircraft.Fuselage.LENGTH] - diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] - - dfffus_ddiam = ( - 2.25 * (diam / fus_len) ** 0.5 / fus_len + 21 * (diam / fus_len) ** 2.0 / fus_len - ) - dfffus_dfus_len = ( - -2.25 * (diam / fus_len) ** 0.5 * diam / fus_len**2.0 - - 21.0 * (diam / fus_len) ** 2.0 * diam / fus_len**2.0 - ) - - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dfffus_ddiam - J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len - - class BWBSIWB(om.ExplicitComponent): """ Compute body form factor and SIWB for BWB aircraft diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index fcc6a3e3f1..bb5ca45f00 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -10,8 +10,11 @@ from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import ( BasicFlapsGeometry, ) -from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import FormFactor, BWBFormFactor +from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import ( + AeroFormfactors, + FormFactor, + BWBFormFactor, +) from aviary.subsystems.aerodynamics.gasp_based.interference import ( WingFuselageInterferencePremission, ) diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py index 3df99be879..84e7bb5b9e 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py @@ -3,8 +3,12 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors -from aviary.variable_info.variables import Aircraft, Mission +from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import ( + AeroFormfactors, + FormFactor, + BWBFormFactor, +) +from aviary.variable_info.variables import Aircraft tol = 1e-8 @@ -40,5 +44,55 @@ def test_aero_coeffs(self): assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) +class FormFactorTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'formfactor', + FormFactor(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class BWBFormFactorTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'formfactor', + BWBFormFactor(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 53f4553a01..57d0ce6492 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -13,7 +13,6 @@ CruiseAero, DragCoef, DragCoefClean, - FormFactor, GroundEffect, LiftCoeff, LiftCoeffClean, @@ -23,12 +22,12 @@ Xlifts, WingTailRatios, BWBBodyLiftCurveSlope, - BWBFormFactor, BWBLiftCoeff, BWBLiftCoeffClean, BWBAeroSetup, BWBSIWB, ) +from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import FormFactor, BWBFormFactor from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults @@ -547,31 +546,6 @@ def test_case3(self): assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) -class FormFactorTest(unittest.TestCase): - """Test fuselage form factor computation and SIWB computation""" - - def test_case1(self): - prob = om.Problem() - - prob.model.add_subsystem( - 'formfactor', - FormFactor(), - promotes=['*'], - ) - - prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') - prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') - - prob.setup(check=False, force_alloc_complex=True) - prob.run_model() - - tol = 1e-5 - assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) - - partial_data = prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) - - class SIWBTest(unittest.TestCase): """Test fuselage form factor computation and SIWB computation""" @@ -597,31 +571,6 @@ def test_case1(self): assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) -class BWBFormFactorTest(unittest.TestCase): - """Test fuselage form factor computation and SIWB computation""" - - def test_case1(self): - prob = om.Problem() - - prob.model.add_subsystem( - 'formfactor', - BWBFormFactor(), - promotes=['*'], - ) - - prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, val=19.365, units='ft') - prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') - - prob.setup(check=False, force_alloc_complex=True) - prob.run_model() - - tol = 1e-5 - assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) - - partial_data = prob.check_partials(out_stream=None, method='cs') - assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) - - class BWBSIWBTest(unittest.TestCase): """Test fuselage form factor computation and SIWB computation""" From bc8e3416acc38b6b60f40fbaed1a9e110afedf9b Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Mon, 6 Apr 2026 16:25:34 -0400 Subject: [PATCH 21/26] move BWBFormFactor --- aviary/docs/theory_guide/gasp_based_bwb.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/docs/theory_guide/gasp_based_bwb.ipynb b/aviary/docs/theory_guide/gasp_based_bwb.ipynb index b0286d7e9f..cb0a284d93 100644 --- a/aviary/docs/theory_guide/gasp_based_bwb.ipynb +++ b/aviary/docs/theory_guide/gasp_based_bwb.ipynb @@ -319,7 +319,6 @@ " AeroGeom,\n", " BWBAeroSetup,\n", " BWBBodyLiftCurveSlope,\n", - " BWBFormFactor,\n", " BWBSIWB,\n", " BWBLiftCoeff,\n", " BWBLiftCoeffClean,\n", @@ -327,6 +326,7 @@ " LowSpeedAero,\n", " Xlifts,\n", ")\n", + "from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import BWBFormFactor\n", "from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero\n", "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", "\n", From 2b4704533fd767802b5c3faa54bb787ffd7854fe Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Fri, 10 Apr 2026 18:06:08 -0400 Subject: [PATCH 22/26] removed aircraft:fuselage:form_factor,1.05557953,unitless --- aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv index 9682c230d1..ab2684460d 100644 --- a/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv @@ -54,7 +54,6 @@ aircraft:furnishings:mass,11192,lbm aircraft:fuselage:aisle_width,24,inch aircraft:fuselage:delta_diameter,4.5,ft aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 -aircraft:fuselage:form_factor,1.05557953,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless From 264a40011f37fb2080d7d929051f2f51ce76d6a5 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 15 Apr 2026 13:41:12 -0400 Subject: [PATCH 23/26] testing: removed a default setting because it has been set in PreMissionAero --- .../aerodynamics/gasp_based/flaps_model/flaps_model.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py index 66076d9e40..e3e42e9a4a 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py @@ -136,11 +136,3 @@ def setup(self): self.nonlinear_solver.options['maxiter'] = 25 self.nonlinear_solver.options['atol'] = 1e-8 self.nonlinear_solver.options['rtol'] = 1e-8 - - # set default trailing edge deflection angle per GASP - # TODO: This hidden default behavior needs to be moved to the pre-processor. - self.set_input_defaults( - Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, - self.optimum_flap_defls[self.options[Aircraft.Wing.FLAP_TYPE]], - units='deg', - ) From 5c12ee5d83e6a9744e736cc6f30842640664a979 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 15 Apr 2026 14:17:34 -0400 Subject: [PATCH 24/26] removed a TODO comment because it is done here already. --- aviary/subsystems/aerodynamics/gasp_based/premission_aero.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index bb5ca45f00..a5759eea87 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -176,7 +176,6 @@ def setup(self): def configure(self): # set default trailing edge deflection angle per GASP - # TODO: This hidden default behavior needs to be moved to the pre-processor. flap = self.flaps_up self.set_input_defaults( Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, From f85681906c2bde15bb61a6a0315636e17c8b4086 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 15 Apr 2026 14:43:58 -0400 Subject: [PATCH 25/26] opened a new issue #1086 and removed TODO in source code. --- aviary/subsystems/aerodynamics/gasp_based/premission_aero.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index a5759eea87..6ef517c619 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -23,9 +23,6 @@ from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission -# TODO: add subsystems to compute CLMXFU, CLMXTO, CLMXLD using dynamic aero components -# with alpha > alpha_stall - class PreMissionAero(om.Group): """Takeoff and landing flaps modeling.""" @@ -94,7 +91,7 @@ def setup(self): ) # Flaps geometry - # TODO: maybe this should move to geometry. + # should this be moved to geometry? See issue #1086 self.add_subsystem( 'BasicFlapsGeometry', BasicFlapsGeometry(), From 52112f71457a13785ee77e2d83249f6b4c568314 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Wed, 15 Apr 2026 15:48:00 -0400 Subject: [PATCH 26/26] modified a TODO comment. Created a new issue #1087. --- aviary/subsystems/aerodynamics/gasp_based/table_based.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aviary/subsystems/aerodynamics/gasp_based/table_based.py b/aviary/subsystems/aerodynamics/gasp_based/table_based.py index 05b65ab887..8b586449de 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/table_based.py +++ b/aviary/subsystems/aerodynamics/gasp_based/table_based.py @@ -355,7 +355,7 @@ def setup(self): # takeoff defaults self.set_input_defaults('dt_gear', 7) else: - # TODO default gear duration for landing? + # should set default gear duration for landing? See issue # 1087 pass if self.options['retract_flaps']: @@ -365,7 +365,7 @@ def setup(self): else: # landing defaults self.set_input_defaults('flap_defl', 40 * np.ones(nn)) - # TODO default flap duration for landing? + # should set default flap duration for landing? See issue # 1087 self.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn)) self.set_input_defaults(Dynamic.Atmosphere.MACH, np.zeros(nn))