diff --git a/aviary/api.py b/aviary/api.py index cfb80e3b2..4da82b656 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -55,9 +55,7 @@ ) from aviary.utils.options import list_options from aviary.constants import ( - GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM, - GRAV_METRIC_GASP, PSLS_PSF, RHO_SEA_LEVEL_ENGLISH, RHO_SEA_LEVEL_METRIC, diff --git a/aviary/constants.py b/aviary/constants.py index a5024aa5f..ef377bf25 100644 --- a/aviary/constants.py +++ b/aviary/constants.py @@ -5,31 +5,40 @@ GRAV_EARTH = ( 9.80665, 'm/s**2', -) # NIST https://physics.nist.gov/cgi-bin/cuu/Value?gn|search_for=gravity +) +# NIST https://physics.nist.gov/cgi-bin/cuu/Value?gn|search_for=gravity +# convert_geopotential_altitude() is a python utility function for engine decs that require GRAV_EARTH to be specified in m/s**2! + GRAV_MARS = ( 3.712, 'm/s**2', -) # Mars Global Reference Atmospheric Model (Mars-GRAM) 2024: User Guide, NASA/TM-20240012934 +) +# Mars Global Reference Atmospheric Model (Mars-GRAM) 2024: User Guide, NASA/TM-20240012934 + GRAV_VENUS = ( 8.870, 'm/s**2', -) # Venus Global Reference Atmospheric Model (Venus-GRAM): User Guide, NASA/TM-20210022168 +) +# Venus Global Reference Atmospheric Model (Venus-GRAM): User Guide, NASA/TM-20210022168 -RADIUS_EARTH = (6371009, 'm') # Source: GRS80, mean earth radius (rounded to nearest meter) -# convert_geopotential_altitude() is a python utility function that require RADIUS_EARTH to be specified in meters! +RADIUS_EARTH = ( + 6371009.0, + 'm', +) # Source: GRS80, mean earth radius (rounded to nearest meter) +# convert_geopotential_altitude() is a python utility function for engine decs that require RADIUS_EARTH to be specified in meters! RADIUS_MARS = ( - 3386200, + 3386200.0, 'm', -) # Mars Global Reference Atmospheric Model (Mars-GRAM) 2024: User Guide, NASA/TM-20240012934, avg of equatorial and polar radius +) +# Mars Global Reference Atmospheric Model (Mars-GRAM) 2024: User Guide, NASA/TM-20240012934, avg of equatorial and polar radius + RADIUS_VENUS = ( - 6051800, + 6051800.0, 'm', -) # Venus Global Reference Atmospheric Model (Venus-GRAM): User Guide, NASA/TM-20210022168, avg of equatorial and polar radius +) +# Venus Global Reference Atmospheric Model (Venus-GRAM): User Guide, NASA/TM-20210022168, avg of equatorial and polar radius -# GNS = 9.8236930 # grav_accel_at_surface_earth # TODO: Remove this from other parts of Aviary -GRAV_METRIC_GASP = 9.81 # m/s^2 -GRAV_ENGLISH_GASP = 32.2 # ft/s^2 GRAV_ENGLISH_LBM = 1.0 # lbf/lbm # See issue 1169 for the value of RHO_SEA_LEVEL_ENGLISH RHO_SEA_LEVEL_ENGLISH = 0.0023769 # slug/ft^3 diff --git a/aviary/mission/energy_state/ode/landing_eom.py b/aviary/mission/energy_state/ode/landing_eom.py index 305b04b9f..97a037c9c 100644 --- a/aviary/mission/energy_state/ode/landing_eom.py +++ b/aviary/mission/energy_state/ode/landing_eom.py @@ -9,7 +9,6 @@ FlightPathAngleRate, VelocityRate, ) -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Dynamic, Mission diff --git a/aviary/mission/solved_two_dof/ode/groundroll_eom.py b/aviary/mission/solved_two_dof/ode/groundroll_eom.py index ff2474706..3611101c6 100644 --- a/aviary/mission/solved_two_dof/ode/groundroll_eom.py +++ b/aviary/mission/solved_two_dof/ode/groundroll_eom.py @@ -1,8 +1,8 @@ import numpy as np import openmdao.api as om -from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -12,6 +12,8 @@ class GroundrollEOM(om.ExplicitComponent): def initialize(self): self.options.declare('num_nodes', types=int) + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): nn = self.options['num_nodes'] @@ -133,8 +135,9 @@ def setup_partials(self): self.declare_partials('angle_of_attack_rate', ['*']) def compute(self, inputs, outputs): - mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] + grav_english = self.options[Mission.GRAVITY][0] + mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] incremented_lift = inputs[Dynamic.Vehicle.LIFT] @@ -158,7 +161,7 @@ def compute(self, inputs, outputs): - weight * np.sin(gamma) - mu * normal_force ) - * GRAV_ENGLISH_GASP + * grav_english / weight ) outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = np.zeros(nn) @@ -171,8 +174,9 @@ def compute(self, inputs, outputs): outputs['angle_of_attack_rate'] = np.zeros(nn) def compute_partials(self, inputs, J): - mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] + grav_english = self.options[Mission.GRAVITY][0] + mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] incremented_lift = inputs[Dynamic.Vehicle.LIFT] @@ -214,17 +218,17 @@ def compute_partials(self, inputs, J): dNF_dIwing[normal_force1 < 0] = 0 J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( - (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight + (dTAlF_dThrust - mu * dNF_dThrust) * grav_english / weight ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( - (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight + (dTAlF_dAlpha - mu * dNF_dAlpha) * grav_english / weight ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( - (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight + (dTAlF_dIwing - mu * dNF_dIwing) * grav_english / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -grav_english / weight J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( - GRAV_ENGLISH_GASP + grav_english * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) @@ -238,13 +242,13 @@ def compute_partials(self, inputs, J): / weight**2 ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( - -np.cos(gamma) * GRAV_ENGLISH_GASP + -np.cos(gamma) * grav_english ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( - GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + grav_english * (-mu * dNF_dLift) / weight ) J[Dynamic.Mission.VELOCITY_RATE, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] = ( - (-normal_force) * GRAV_ENGLISH_GASP / weight + (-normal_force) * grav_english / weight ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) diff --git a/aviary/mission/solved_two_dof/ode/test/test_groundroll_eom.py b/aviary/mission/solved_two_dof/ode/test/test_groundroll_eom.py index 813aa911d..8d0041ab3 100644 --- a/aviary/mission/solved_two_dof/ode/test/test_groundroll_eom.py +++ b/aviary/mission/solved_two_dof/ode/test/test_groundroll_eom.py @@ -13,7 +13,10 @@ class GroundrollEOMTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', GroundrollEOM(num_nodes=2), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem( + 'group', GroundrollEOM(num_nodes=2, **options), promotes=['*'] + ) self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' ) 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 798ae2c14..a6bbdb159 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 @@ -11,7 +11,7 @@ from aviary.utils.test_utils.IO_test_util import check_prob_outputs from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic, Mission @use_tempdirs @@ -23,6 +23,7 @@ def setUp(self): aviary_options = get_option_defaults() aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + aviary_options.set_val(Mission.GRAVITY, val=32.2, units='ft/s**2') default_mission_subsystems = get_default_mission_subsystems( 'GASP', [build_engine_deck(aviary_options)] ) diff --git a/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py b/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py index a6c879744..23e24c9bd 100644 --- a/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py +++ b/aviary/mission/solved_two_dof/ode/unsteady_solved_eom.py @@ -2,8 +2,8 @@ import openmdao.api as om from openmdao.utils.units import convert_units -from aviary.constants import GRAV_ENGLISH_LBM, GRAV_METRIC_GASP -from aviary.variable_info.functions import add_aviary_input +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission LBF_TO_N = convert_units(1.0, 'lbf', 'N') @@ -31,6 +31,8 @@ def initialize(self): 'the TAS rate equation.', ) + add_aviary_option(self, Mission.GRAVITY, units='m/s**2') + def setup(self): nn = self.options['num_nodes'] @@ -214,6 +216,8 @@ def setup_partials(self): self.declare_partials(of=['dgam_dt_approx', 'dgam_dt'], wrt=[Aircraft.Wing.INCIDENCE]) def compute(self, inputs, outputs): + grav_metric = self.options[Mission.GRAVITY][0] + tas = inputs[Dynamic.Mission.VELOCITY] thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] # convert to newtons # TODO: change this to use the units conversion @@ -224,7 +228,7 @@ def compute(self, inputs, outputs): i_wing = inputs[Aircraft.Wing.INCIDENCE] - g = GRAV_METRIC_GASP + g = grav_metric m = weight / g if self.options['ground_roll']: @@ -269,6 +273,7 @@ def compute(self, inputs, outputs): outputs['dgam_dt_approx'] = dgam_dr * dr_dt def compute_partials(self, inputs, partials): + grav_metric = self.options[Mission.GRAVITY][0] ground_roll = self.options['ground_roll'] thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] @@ -291,7 +296,7 @@ def compute_partials(self, inputs, partials): alpha_i = alpha - i_wing - g = GRAV_METRIC_GASP + g = grav_metric m = weight / g mtas = m * tas diff --git a/aviary/mission/two_dof/ode/accel_eom.py b/aviary/mission/two_dof/ode/accel_eom.py index 41db2185e..db495ebe0 100644 --- a/aviary/mission/two_dof/ode/accel_eom.py +++ b/aviary/mission/two_dof/ode/accel_eom.py @@ -1,9 +1,9 @@ import numpy as np import openmdao.api as om -from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Dynamic +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option +from aviary.variable_info.variables import Dynamic, Mission class AccelerationRates(om.ExplicitComponent): @@ -16,6 +16,8 @@ class AccelerationRates(om.ExplicitComponent): def initialize(self): self.options.declare('num_nodes', types=int) + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): nn = self.options['num_nodes'] @@ -79,23 +81,26 @@ def setup_partials(self): ) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM drag = inputs[Dynamic.Vehicle.DRAG] thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] TAS = inputs[Dynamic.Mission.VELOCITY] - outputs[Dynamic.Mission.VELOCITY_RATE] = (GRAV_ENGLISH_GASP / weight) * (thrust - drag) + outputs[Dynamic.Mission.VELOCITY_RATE] = (grav_english / weight) * (thrust - drag) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM drag = inputs[Dynamic.Vehicle.DRAG] thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( - -(GRAV_ENGLISH_GASP / weight**2) * (thrust - drag) * GRAV_ENGLISH_LBM + -(grav_english / weight**2) * (thrust - drag) * GRAV_ENGLISH_LBM ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -(GRAV_ENGLISH_GASP / weight) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -(grav_english / weight) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( - GRAV_ENGLISH_GASP / weight + grav_english / weight ) diff --git a/aviary/mission/two_dof/ode/flight_path_eom.py b/aviary/mission/two_dof/ode/flight_path_eom.py index e48696810..5299e3b1d 100644 --- a/aviary/mission/two_dof/ode/flight_path_eom.py +++ b/aviary/mission/two_dof/ode/flight_path_eom.py @@ -1,8 +1,8 @@ import numpy as np import openmdao.api as om -from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -22,6 +22,8 @@ def initialize(self): 'output and adjust the TAS rate equation.', ) + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): nn = self.options['num_nodes'] ground_roll = self.options['ground_roll'] @@ -188,6 +190,7 @@ def setup_partials(self): self.declare_partials('fuselage_pitch', [Aircraft.Wing.INCIDENCE]) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] if self.options['ground_roll']: mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] else: @@ -216,14 +219,14 @@ def compute(self, inputs, outputs): - weight * np.sin(gamma) - mu * normal_force ) - * GRAV_ENGLISH_GASP + * grav_english / weight ) if not self.options['ground_roll']: outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = ( (thrust_across_flightpath + incremented_lift - weight * np.cos(gamma)) - * GRAV_ENGLISH_GASP + * grav_english / (TAS * weight) ) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) @@ -239,6 +242,7 @@ def compute(self, inputs, outputs): outputs['load_factor'] = load_factor def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] if self.options['ground_roll']: mu = inputs[Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] else: @@ -300,12 +304,12 @@ def compute_partials(self, inputs, J): # dNF_dIwing[normal_force1 < 0] = 0 J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( - (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight + (dTAlF_dThrust - mu * dNF_dThrust) * grav_english / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -grav_english / weight J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( - GRAV_ENGLISH_GASP + grav_english * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) @@ -319,14 +323,14 @@ def compute_partials(self, inputs, J): / weight**2 ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( - -np.cos(gamma) * GRAV_ENGLISH_GASP + -np.cos(gamma) * grav_english ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( - GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + grav_english * (-mu * dNF_dLift) / weight ) if self.options['ground_roll']: J[Dynamic.Mission.VELOCITY_RATE, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] = ( - -normal_force * GRAV_ENGLISH_GASP / weight + -normal_force * grav_english / weight ) # TODO: check partials, esp. for alphas @@ -339,35 +343,35 @@ def compute_partials(self, inputs, J): J[ Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - ] = dTAcF_dThrust * GRAV_ENGLISH_GASP / (TAS * weight) + ] = dTAcF_dThrust * grav_english / (TAS * weight) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( - dTAcF_dAlpha * GRAV_ENGLISH_GASP / (TAS * weight) + dTAcF_dAlpha * grav_english / (TAS * weight) ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Aircraft.Wing.INCIDENCE] = ( - dTAcF_dIwing * GRAV_ENGLISH_GASP / (TAS * weight) + dTAcF_dIwing * grav_english / (TAS * weight) ) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = GRAV_ENGLISH_GASP / ( + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = grav_english / ( TAS * weight ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.MASS] = ( - (GRAV_ENGLISH_GASP / TAS) + (grav_english / TAS) * GRAV_ENGLISH_LBM * (-thrust_across_flightpath / weight**2 - incremented_lift / weight**2) ) J[ Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE, - ] = weight * np.sin(gamma) * GRAV_ENGLISH_GASP / (TAS * weight) + ] = weight * np.sin(gamma) * grav_english / (TAS * weight) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.VELOCITY] = -( (thrust_across_flightpath + incremented_lift - weight * np.cos(gamma)) - * GRAV_ENGLISH_GASP + * grav_english / (TAS**2 * weight) ) dNF_dAlpha = -np.ones(nn) * dTAcF_dAlpha # dNF_dAlpha[normal_force1 < 0] = 0 J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( - (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight + (dTAlF_dAlpha - mu * dNF_dAlpha) * grav_english / weight ) J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha J['fuselage_pitch', Dynamic.Vehicle.ANGLE_OF_ATTACK] = 1 @@ -375,7 +379,7 @@ def compute_partials(self, inputs, J): weight * np.cos(gamma) ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( - (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight + (dTAlF_dIwing - mu * dNF_dIwing) * grav_english / weight ) J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing J['fuselage_pitch', Aircraft.Wing.INCIDENCE] = -1 diff --git a/aviary/mission/two_dof/ode/landing_eom.py b/aviary/mission/two_dof/ode/landing_eom.py index c1ddd11dd..94c03f75a 100644 --- a/aviary/mission/two_dof/ode/landing_eom.py +++ b/aviary/mission/two_dof/ode/landing_eom.py @@ -1,8 +1,8 @@ import numpy as np import openmdao.api as om -from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -31,6 +31,9 @@ def compute_partials(self, inputs, J): class GlideConditionComponent(om.ExplicitComponent): """Compute the initial conditions of the 2DOF glide phase.""" + def initialize(self): + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): add_aviary_input(self, Dynamic.Atmosphere.DENSITY, units='slug/ft**3') add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE) @@ -178,6 +181,7 @@ def setup(self): ) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] ( rho_app, rate_of_sink_max, @@ -191,7 +195,7 @@ def compute(self, inputs, outputs): time_delay, ) = inputs.values() weight = mass * GRAV_ENGLISH_LBM - G = GRAV_ENGLISH_GASP + G = grav_english wing_loading_land = weight / wing_area TAS_stall = np.sqrt(2 * wing_loading_land / (CL_max * rho_app)) @@ -226,6 +230,7 @@ def compute(self, inputs, outputs): outputs['theta'] = theta def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] ( rho_app, rate_of_sink_max, @@ -239,7 +244,7 @@ def compute_partials(self, inputs, J): time_delay, ) = inputs.values() weight = mass * GRAV_ENGLISH_LBM - G = GRAV_ENGLISH_GASP + G = grav_english wing_loading_land = weight / wing_area TAS_stall = np.sqrt(2 * wing_loading_land / (CL_max * rho_app)) @@ -529,6 +534,9 @@ def compute_partials(self, inputs, J): class LandingGroundRollComponent(om.ExplicitComponent): """Compute the groundroll distance and average acceleration/deceleration.""" + def initialize(self): + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): self.add_input('touchdown_CD', val=0.0, units='unitless', desc='CDRL: CD at touchdown') self.add_input('touchdown_CL', val=0.0, units='unitless', desc='CLRL: CL at touchdown') @@ -643,6 +651,7 @@ def setup_partials(self): ) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] ( touchdown_CD, touchdown_CL, @@ -660,7 +669,7 @@ def compute(self, inputs, outputs): ) = inputs.values() weight = mass * GRAV_ENGLISH_LBM - G = GRAV_ENGLISH_GASP + G = grav_english MUB = mu_landing DLRL = touchdown_CD - (MUB * touchdown_CL) @@ -678,6 +687,7 @@ def compute(self, inputs, outputs): outputs['average_acceleration'] = average_acceleration def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] ( touchdown_CD, touchdown_CL, @@ -694,7 +704,7 @@ def compute_partials(self, inputs, J): mu_landing, ) = inputs.values() weight = mass * GRAV_ENGLISH_LBM - G = GRAV_ENGLISH_GASP + G = grav_english MUB = mu_landing DLRL = touchdown_CD - (MUB * touchdown_CL) diff --git a/aviary/mission/two_dof/ode/takeoff_eom.py b/aviary/mission/two_dof/ode/takeoff_eom.py index b8f9fe361..0bc684f85 100644 --- a/aviary/mission/two_dof/ode/takeoff_eom.py +++ b/aviary/mission/two_dof/ode/takeoff_eom.py @@ -1,8 +1,8 @@ import numpy as np import openmdao.api as om -from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission DEG2RAD = np.pi / 180.0 @@ -50,6 +50,8 @@ def initialize(self): desc='Pitch rate during rotation in degrees/second.', ) + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): nn = self.options['num_nodes'] ground_roll = self.options['ground_roll'] @@ -213,6 +215,7 @@ def setup_partials(self): self.declare_partials('angle_of_attack_rate', ['*'], 0.0) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] ground_roll = self.options['ground_roll'] rotation = self.options['rotation'] @@ -248,7 +251,7 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.VELOCITY_RATE] = ( (thrust_along_flightpath - incremented_drag - weight * sin_gamma - mu * normal_force) - * GRAV_ENGLISH_GASP + * grav_english / weight ) @@ -257,7 +260,7 @@ def compute(self, inputs, outputs): else: outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] = ( (thrust_across_flightpath + incremented_lift - weight * cos_gamma) - * GRAV_ENGLISH_GASP + * grav_english / (TAS * weight) ) @@ -275,6 +278,7 @@ def compute(self, inputs, outputs): outputs['angle_of_attack_rate'][:] = 0.0 def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] ground_roll = self.options['ground_roll'] rotation = self.options['rotation'] nn = self.options['num_nodes'] @@ -349,12 +353,12 @@ def compute_partials(self, inputs, J): dNF_dIwing[idx] = 0 J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( - (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight + (dTAlF_dThrust - mu * dNF_dThrust) * grav_english / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -grav_english / weight J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( - GRAV_ENGLISH_GASP + grav_english * GRAV_ENGLISH_LBM * ( weight * (-sin_gamma - mu * dNF_dWeight) @@ -368,13 +372,13 @@ def compute_partials(self, inputs, J): / weight**2 ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( - -cos_gamma * GRAV_ENGLISH_GASP + -cos_gamma * grav_english ) J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( - GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + grav_english * (-mu * dNF_dLift) / weight ) J[Dynamic.Mission.VELOCITY_RATE, Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT] = ( - -normal_force * GRAV_ENGLISH_GASP / weight + -normal_force * grav_english / weight ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = sin_gamma @@ -385,35 +389,35 @@ def compute_partials(self, inputs, J): J[ Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, - ] = dTAcF_dThrust * GRAV_ENGLISH_GASP / (TAS * weight) + ] = dTAcF_dThrust * grav_english / (TAS * weight) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( - dTAcF_dAlpha * GRAV_ENGLISH_GASP / (TAS * weight) + dTAcF_dAlpha * grav_english / (TAS * weight) ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Aircraft.Wing.INCIDENCE] = ( - dTAcF_dIwing * GRAV_ENGLISH_GASP / (TAS * weight) + dTAcF_dIwing * grav_english / (TAS * weight) ) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = GRAV_ENGLISH_GASP / ( + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = grav_english / ( TAS * weight ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.MASS] = ( - (GRAV_ENGLISH_GASP / TAS) + (grav_english / TAS) * GRAV_ENGLISH_LBM * (-thrust_across_flightpath / weight**2 - incremented_lift / weight**2) ) J[ Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE, - ] = weight * sin_gamma * GRAV_ENGLISH_GASP / (TAS * weight) + ] = weight * sin_gamma * grav_english / (TAS * weight) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.VELOCITY] = -( (thrust_across_flightpath + incremented_lift - weight * cos_gamma) - * GRAV_ENGLISH_GASP + * grav_english / (TAS**2 * weight) ) if not ground_roll: # WRT incidence angle J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( - (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight + (dTAlF_dIwing - mu * dNF_dIwing) * grav_english / weight ) if rotation: J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing @@ -425,7 +429,7 @@ def compute_partials(self, inputs, J): dNF_dAlpha[idx] = 0 J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( - (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight + (dTAlF_dAlpha - mu * dNF_dAlpha) * grav_english / weight ) if rotation: J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha diff --git a/aviary/mission/two_dof/ode/test/test_accel_eom.py b/aviary/mission/two_dof/ode/test/test_accel_eom.py index 7c2827628..7b1c301a9 100644 --- a/aviary/mission/two_dof/ode/test/test_accel_eom.py +++ b/aviary/mission/two_dof/ode/test/test_accel_eom.py @@ -6,7 +6,7 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.mission.two_dof.ode.accel_eom import AccelerationRates -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Dynamic, Mission @use_tempdirs @@ -19,7 +19,10 @@ class AccelerationTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', AccelerationRates(num_nodes=2), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem( + 'group', AccelerationRates(num_nodes=2, **options), promotes=['*'] + ) self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, np.array([174878, 174878]), units='lbm' diff --git a/aviary/mission/two_dof/ode/test/test_flight_path_eom.py b/aviary/mission/two_dof/ode/test/test_flight_path_eom.py index f6fd36259..a4d3e8802 100644 --- a/aviary/mission/two_dof/ode/test/test_flight_path_eom.py +++ b/aviary/mission/two_dof/ode/test/test_flight_path_eom.py @@ -14,8 +14,11 @@ class FlightPathEOMTestCase(unittest.TestCase): def setUp(self): self.ground_roll = False self.prob = om.Problem() + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} self.fp = self.prob.model.add_subsystem( - 'group', FlightPathEOM(num_nodes=2, ground_roll=self.ground_roll), promotes=['*'] + 'group', + FlightPathEOM(num_nodes=2, ground_roll=self.ground_roll, **options), + promotes=['*'], ) self.prob.model.set_input_defaults(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.02) self.prob.setup(check=False, force_alloc_complex=True) 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 bf4d0cf05..e89f8a98c 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 @@ -13,6 +13,7 @@ from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.utils.preprocessors import preprocess_options @use_tempdirs @@ -23,6 +24,7 @@ def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Mission.GRAVITY, val=32.2, units='ft/s**2') aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( 'GASP', [build_engine_deck(aviary_options)] @@ -30,7 +32,7 @@ def setUp(self): self.fp = self.prob.model = FlightPathODE( num_nodes=2, - aviary_options=get_option_defaults(), + aviary_options=aviary_options, subsystems=default_mission_subsystems, ) @@ -63,7 +65,7 @@ def test_case1(self): 'fuselage_pitch': [0.0, 0.0], 'load_factor': [0.25086942, 0.25086942], Dynamic.Mission.ALTITUDE_RATE: [0.0, 0.0], - Dynamic.Mission.ALTITUDE_RATE_MAX: [-0.01815763, -0.01815763], + Dynamic.Mission.ALTITUDE_RATE_MAX: [-0.018143, -0.018143], } check_prob_outputs(self.prob, testvals, rtol=1e-6) @@ -99,7 +101,7 @@ def test_case2(self): 'normal_force': [74913.05769336, 74913.05769336], 'fuselage_pitch': [0.0, 0.0], 'load_factor': [0.25086942, 0.25086942], - Dynamic.Mission.ALTITUDE_RATE_MAX: [0.75323619, 0.75323619], + Dynamic.Mission.ALTITUDE_RATE_MAX: [0.75262913, 0.75262913], } check_prob_outputs(self.prob, testvals, rtol=1e-6) diff --git a/aviary/mission/two_dof/ode/test/test_landing_eom.py b/aviary/mission/two_dof/ode/test/test_landing_eom.py index 719f02b82..9f67ecef3 100644 --- a/aviary/mission/two_dof/ode/test/test_landing_eom.py +++ b/aviary/mission/two_dof/ode/test/test_landing_eom.py @@ -44,7 +44,8 @@ class GlideTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', GlideConditionComponent(), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem('group', GlideConditionComponent(**options), promotes=['*']) self.prob.model.set_input_defaults( Dynamic.Atmosphere.DENSITY, RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3' @@ -111,7 +112,8 @@ def tearDown(self): def test_case1(self): prob = om.Problem() - prob.model.add_subsystem('group', GlideConditionComponent(), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + prob.model.add_subsystem('group', GlideConditionComponent(**options), promotes=['*']) prob.model.set_input_defaults( Dynamic.Atmosphere.DENSITY, RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3' ) @@ -140,7 +142,10 @@ class GroundRollTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', LandingGroundRollComponent(), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem( + 'group', LandingGroundRollComponent(**options), promotes=['*'] + ) self.prob.model.set_input_defaults('touchdown_CD', val=0.07344) self.prob.model.set_input_defaults('touchdown_CL', val=1.18694) @@ -197,7 +202,10 @@ def tearDown(self): def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', LandingGroundRollComponent(), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem( + 'group', LandingGroundRollComponent(**options), promotes=['*'] + ) self.prob.model.set_input_defaults('touchdown_CD', val=0.07344) self.prob.model.set_input_defaults('touchdown_CL', val=1.18694) diff --git a/aviary/mission/two_dof/ode/test/test_takeoff_eom.py b/aviary/mission/two_dof/ode/test/test_takeoff_eom.py index 07e083e78..8e3da8266 100644 --- a/aviary/mission/two_dof/ode/test/test_takeoff_eom.py +++ b/aviary/mission/two_dof/ode/test/test_takeoff_eom.py @@ -13,8 +13,9 @@ class GroundrollEOMTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} self.prob.model.add_subsystem( - 'group', TakeoffEOM(num_nodes=2, ground_roll=True), promotes=['*'] + 'group', TakeoffEOM(num_nodes=2, ground_roll=True, **options), promotes=['*'] ) self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' @@ -72,7 +73,10 @@ def tearDown(self): def test_case1(self): prob = om.Problem() - prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2, ground_roll=True), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + prob.model.add_subsystem( + 'group', TakeoffEOM(num_nodes=2, ground_roll=True, **options), promotes=['*'] + ) prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' @@ -95,8 +99,9 @@ def test_case1(self): class RotationEOMTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} self.prob.model.add_subsystem( - 'group', TakeoffEOM(num_nodes=2, rotation=True), promotes=['*'] + 'group', TakeoffEOM(num_nodes=2, rotation=True, **options), promotes=['*'] ) self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' @@ -158,7 +163,10 @@ def tearDown(self): def test_case1(self): prob = om.Problem() - prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2, rotation=True), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + prob.model.add_subsystem( + 'group', TakeoffEOM(num_nodes=2, rotation=True, **options), promotes=['*'] + ) prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' @@ -182,7 +190,8 @@ def test_case1(self): class AscentEOMTestCase(unittest.TestCase): def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + self.prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2, **options), promotes=['*']) self.prob.model.set_input_defaults( Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' ) @@ -241,7 +250,8 @@ def tearDown(self): def test_case1(self): prob = om.Problem() - prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2), promotes=['*']) + options = {Mission.GRAVITY: (32.2, 'ft/s**2')} + prob.model.add_subsystem('group', TakeoffEOM(num_nodes=2, **options), promotes=['*']) prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' 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 2e9f73f9a..b2552ec7b 100644 --- a/aviary/mission/two_dof/ode/test/test_takeoff_ode.py +++ b/aviary/mission/two_dof/ode/test/test_takeoff_ode.py @@ -25,6 +25,7 @@ def setUp(self): aviary_options = get_option_defaults() aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + aviary_options.set_val(Mission.GRAVITY, val=32.2, units='ft/s**2') default_mission_subsystems = get_default_mission_subsystems( 'GASP', [build_engine_deck(aviary_options)] ) @@ -32,7 +33,7 @@ def setUp(self): self.prob.model = TakeOffODE( num_nodes=2, ground_roll=True, - aviary_options=get_option_defaults(), + aviary_options=aviary_options, subsystems=default_mission_subsystems, ) @@ -83,6 +84,7 @@ def setUp(self): aviary_options = get_option_defaults() aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + aviary_options.set_val(Mission.GRAVITY, val=32.2, units='ft/s**2') default_mission_subsystems = get_default_mission_subsystems( 'GASP', [build_engine_deck(aviary_options)] ) @@ -90,7 +92,7 @@ def setUp(self): self.prob.model = TakeOffODE( num_nodes=2, rotation=True, - aviary_options=get_option_defaults(), + aviary_options=aviary_options, subsystems=default_mission_subsystems, ) setup_model_options(self.prob, aviary_options) @@ -146,6 +148,8 @@ def setUp(self): aviary_options = get_option_defaults() aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + aviary_options.set_val(Mission.GRAVITY, val=32.2, units='ft/s**2') + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, val=[2], units='unitless') default_mission_subsystems = get_default_mission_subsystems( 'GASP', [build_engine_deck(aviary_options)] ) @@ -154,9 +158,7 @@ def setUp(self): num_nodes=2, aviary_options=aviary_options, subsystems=default_mission_subsystems ) - setup_model_options( - self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) - ) + setup_model_options(self.prob, AviaryValues(aviary_options)) def test_ascent_partials(self): # Test partial derivatives diff --git a/aviary/subsystems/aerodynamics/gasp_based/interference.py b/aviary/subsystems/aerodynamics/gasp_based/interference.py index e60226993..c224aef64 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/interference.py +++ b/aviary/subsystems/aerodynamics/gasp_based/interference.py @@ -2,9 +2,8 @@ import openmdao.api as om from openmdao.utils import cs_safe as cs -from aviary.constants import GRAV_ENGLISH_GASP -from aviary.variable_info.functions import add_aviary_input -from aviary.variable_info.variables import Aircraft, Dynamic +from aviary.variable_info.functions import add_aviary_input, add_aviary_option +from aviary.variable_info.variables import Aircraft, Dynamic, Mission FCFWC = 1 # Excrescence drag factor FCFWT = 1 # Aero technology factors for wing @@ -335,6 +334,8 @@ class WingFuselageInterferenceMission(om.ExplicitComponent): def initialize(self): self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Mission.GRAVITY, units='ft/s**2') + def setup(self): nn = self.options['num_nodes'] @@ -378,11 +379,12 @@ def setup_partials(self): ) def compute(self, inputs, outputs): + grav_english = self.options[Mission.GRAVITY][0] CKW, CBARW, EM, T0, XKV, AREASHIELDWF, FEINTWF = inputs.values() # from gaspmain.f # reli = reynolds number per foot - RELI = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * EM * np.sqrt(T0) / XKV # dynamic + RELI = np.sqrt(1.4 * grav_english * 53.32) * EM * np.sqrt(T0) / XKV # dynamic # from aero.f # CFIN CALCULATION FROM SCHLICHTING PG. 635-665 @@ -396,10 +398,11 @@ def compute(self, inputs, outputs): outputs['wing_fuselage_interference_flat_plate_equivalent'] = FEIWF def compute_partials(self, inputs, J): + grav_english = self.options[Mission.GRAVITY][0] CKW, CBARW, EM, T0, XKV, AREASHIELDWF, FEINTWF = inputs.values() - RELI = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * EM * np.sqrt(T0) / XKV - dRELI_dEM = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * np.sqrt(T0) / XKV + RELI = np.sqrt(1.4 * grav_english * 53.32) * EM * np.sqrt(T0) / XKV + dRELI_dEM = np.sqrt(1.4 * grav_english * 53.32) * np.sqrt(T0) / XKV CFIN = 0.455 / 7**2.58 / (1.0 + 0.144 * EM**2) ** 0.65 dCFIN_dEM = -0.65 * CFIN / (1.0 + 0.144 * EM**2) * 0.288 * EM @@ -446,7 +449,7 @@ def compute_partials(self, inputs, J): * AREASHIELDWF * 1 / (np.log(10) * (RELI) * 7) - * np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) + * np.sqrt(1.4 * grav_english * 53.32) * EM * 0.5 / (XKV * np.sqrt(T0)) @@ -462,7 +465,7 @@ def compute_partials(self, inputs, J): * AREASHIELDWF * 1 / (np.log(10) * (RELI) * 7) - * np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) + * np.sqrt(1.4 * grav_english * 53.32) * EM * np.sqrt(T0) / XKV**2 diff --git a/aviary/subsystems/aerodynamics/solve_alpha_group.py b/aviary/subsystems/aerodynamics/solve_alpha_group.py index ed1c7cf09..0761749a8 100644 --- a/aviary/subsystems/aerodynamics/solve_alpha_group.py +++ b/aviary/subsystems/aerodynamics/solve_alpha_group.py @@ -2,7 +2,8 @@ import openmdao.api as om from aviary import constants -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Dynamic, Mission +from aviary.variable_info.functions import add_aviary_option class SolveAlphaGroup(om.Group): @@ -14,13 +15,17 @@ class SolveAlphaGroup(om.Group): def initialize(self): self.options.declare('num_nodes', types=int) + add_aviary_option(self, Mission.GRAVITY, units='m/s**2') + def setup(self): + grav_metric = self.options[Mission.GRAVITY][0] + num_nodes = self.options['num_nodes'] self.add_subsystem( 'required_lift', om.ExecComp( 'required_lift = mass * grav_metric', - grav_metric={'val': constants.GRAV_METRIC_GASP}, + grav_metric={'val': grav_metric}, mass={'units': 'kg', 'shape': num_nodes}, required_lift={'units': 'N', 'shape': num_nodes}, has_diag_partials=True, diff --git a/aviary/subsystems/propulsion/utils.py b/aviary/subsystems/propulsion/utils.py index d1d762596..56479351c 100644 --- a/aviary/subsystems/propulsion/utils.py +++ b/aviary/subsystems/propulsion/utils.py @@ -81,6 +81,7 @@ class EngineModelVariables(Enum): def convert_geopotential_altitude(altitude): """ Converts altitudes from geopotential to geometric altitude + Only used for engine decks Assumes altitude is provided in feet. Parameters @@ -98,15 +99,19 @@ def convert_geopotential_altitude(altitude): except TypeError: altitude = [altitude] - g = constants.GRAV_EARTH - radius_earth = constants.RADIUS_EARTH[0] # meters + grav_metric = constants.GRAV_EARTH[0] + if constants.GRAV_EARTH[1] != 'm/s**2': + warnings.warn( + 'convert_geopotential_altitude() only functions properly when constants.GRAV_EARTH is specified in m/s**2' + ) + radius_earth = constants.RADIUS_EARTH[0] if constants.RADIUS_EARTH[1] != 'm': warnings.warn( 'convert_geopotential_altitude() only functions properly when constants.RADIUS_EARTH is specified in meters!' ) + CM1 = 0.99850 # Center of mass (Earth)? Unknown OC2 = 26.76566e-10 # Unknown - GNS = 9.8236930 # grav_accel_at_surface_earth? for i, alt in enumerate(altitude): HFT = alt @@ -117,8 +122,10 @@ def convert_geopotential_altitude(altitude): while abs(DH) > 1.0: R = radius_earth + Z - GN = GNS * (radius_earth / R) ** (CM1 + 1.0) - H = (R * GN * ((R / radius_earth) ** CM1 - 1.0) / CM1 - Z * (R - Z / 2.0) * OC2) / g + GN = grav_metric * (radius_earth / R) ** (CM1 + 1.0) + H = ( + R * GN * ((R / radius_earth) ** CM1 - 1.0) / CM1 - Z * (R - Z / 2.0) * OC2 + ) / grav_metric DH = HO - H Z += DH