diff --git a/aviary/constants.py b/aviary/constants.py index 39e56aa8bc..19f84f8577 100644 --- a/aviary/constants.py +++ b/aviary/constants.py @@ -2,9 +2,36 @@ units.add_unit('distance_units', '1*m') +GRAV_EARTH = ( + 9.80665, + 'm/s**2', +) # NIST https://physics.nist.gov/cgi-bin/cuu/Value?gn|search_for=gravity +GRAV_MARS = ( + 3.712, + 'm/s**2', +) # 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 + +# RADIUS_EARTH = (6371009, 'm') # Source: GRS80, mean earth radius (rounded to nearest meter) +RADIUS_EARTH = (6356766, 'm') # TODO remove and replace with above + +# RADIUS_MARS = ( +# 3386200, +# 'm', +# ) # Mars Global Reference Atmospheric Model (Mars-GRAM) 2024: User Guide, NASA/TM-20240012934, avg of equatorial and polar radius +RADIUS_MARS = (3396200, 'm') # TODO remove and replace with above +RADIUS_VENUS = ( + 6051800, + 'm', +) # 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 # remove this asap GRAV_METRIC_GASP = 9.81 # m/s^2 -GRAV_ENGLISH_GASP = 32.2 # ft/s^2 GRAV_METRIC_FLOPS = 9.80665 # m/s^2 +GRAV_ENGLISH_GASP = 32.2 # ft/s^2 GRAV_ENGLISH_FLOPS = 32.17399 # ft/s^2 GRAV_ENGLISH_LBM = 1.0 # lbf/lbm # See issue 1169 for the value of RHO_SEA_LEVEL_ENGLISH diff --git a/aviary/interface/test/sizing_results_for_test.json b/aviary/interface/test/sizing_results_for_test.json index 760aa600f8..4d4dbdbdfb 100644 --- a/aviary/interface/test/sizing_results_for_test.json +++ b/aviary/interface/test/sizing_results_for_test.json @@ -1124,6 +1124,18 @@ "unitless", "" ], + [ + "settings:atmosphere_model", + "STANDARD", + "unitless", + "" + ], + [ + "mission:gravity", + 9.80665, + "m/s**2", + "" + ], [ "mission:gross_mass", 175400.0, diff --git a/aviary/subsystems/atmosphere/atmosphere.py b/aviary/subsystems/atmosphere/atmosphere.py index bec651006d..9536ef28dc 100644 --- a/aviary/subsystems/atmosphere/atmosphere.py +++ b/aviary/subsystems/atmosphere/atmosphere.py @@ -1,23 +1,10 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Cold import atm_data as cold_210A -from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Hot import atm_data as hot_210A -from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Polar import atm_data as polar_210A -from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Tropical import atm_data as tropical_210A -from aviary.subsystems.atmosphere.data.StandardAtm1976 import atm_data as USatm1976 -from aviary.subsystems.atmosphere.data.MarsReference2024 import atm_data as MarsReference2024 -from aviary.subsystems.atmosphere.data.MarsHellasHot import atm_data as MarsHellasHot -from aviary.subsystems.atmosphere.data.MarsHellasCold import atm_data as MarsHellasCold -from aviary.subsystems.atmosphere.data.MarsEquatorHot import atm_data as MarsEquatorHot -from aviary.subsystems.atmosphere.data.MarsEquatorCold import atm_data as MarsEquatorCold -from aviary.subsystems.atmosphere.data.MarsPolarHot import atm_data as MarsPolarHot -from aviary.subsystems.atmosphere.data.MarsPolarCold import atm_data as MarsPolarCold -from aviary.subsystems.atmosphere.data.VenusReference2021 import atm_data as VenusReference2021 from aviary.subsystems.atmosphere.flight_conditions import FlightConditions from aviary.variable_info.enums import AtmosphereModel, SpeedType -from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Dynamic, Settings +from aviary.subsystems.atmosphere.utils.get_atmosphere_data import get_atmosphere_data class Atmosphere(om.Group): @@ -117,52 +104,19 @@ def setup(self): self._dt = self.options['delta_T_Celcius'] - self._R0 = 0 # instantiate and add correct value later + self.source_data, self.planet, planet_radius, _ = get_atmosphere_data( + self.options[Settings.ATMOSPHERE_MODEL] + ) + + self._R0 = planet_radius[0] # in meters + self._geometric = self.options['h_def'] == 'geometric' # From the U.S. Standard Atmosphere 1976 publication located here # https://www.ngdc.noaa.gov/stp/space-weather/online-publications/miscellaneous/us-standard-atmosphere-1976/us-standard-atmosphere_st76-1562_noaa.pdf Rs = 8314.32 # J/(kmol*K), Ideal Gas constant - - if self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.STANDARD: - self.source_data = USatm1976 - self.planet = 'Earth' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.TROPICAL: - self.source_data = tropical_210A - self.planet = 'Earth' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.POLAR: - self.source_data = polar_210A - self.planet = 'Earth' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.HOT: - self.source_data = hot_210A - self.planet = 'Earth' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.COLD: - self.source_data = cold_210A - self.planet = 'Earth' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_REFERENCE: - self.source_data = MarsReference2024 - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_HELLAS_HOT: - self.source_data = MarsHellasHot - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_HELLAS_COLD: - self.source_data = MarsHellasCold - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_EQUATOR_HOT: - self.source_data = MarsEquatorHot - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_EQUATOR_COLD: - self.source_data = MarsEquatorCold - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_POLAR_HOT: - self.source_data = MarsPolarHot - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.MARS_POLAR_COLD: - self.source_data = MarsPolarCold - self.planet = 'Mars' - elif self.options[Settings.ATMOSPHERE_MODEL] is AtmosphereModel.VENUS_REFERENCE: - self.source_data = VenusReference2021 - self.planet = 'Venus' + M_air = 0 # + gamma = 0 # # The constants below are used as a simplification to enable calculation of properties not given by by source data tables if self.planet == 'Earth': @@ -170,7 +124,6 @@ def setup(self): gamma = 1.4 # Ratio of specific heats self._S = 110.4 # (K) Southerlands constant for Earth air self._beta = 1.458e-6 # (s*m*K**(1/2)) viscosity scaling coefficient - self._R0 = 6_356_766 # (meters) The effective Earth Radius elif self.planet == 'Mars': M_air = 43.34 # (kg/kmol), mean molar mass of Mars atmosphere https://descanso.jpl.nasa.gov/propagation/mars/MarsPub_sec4.pdf gamma = 1.36 # Ratio of specific heats, Based on averaging values from Hellas_summar, Hellas_winter, Equatorial_summar, @@ -180,7 +133,6 @@ def setup(self): self._beta = 1.503e-6 # (s*m*K**(1/2)) viscosity scaling coefficient calculated from other constants listed for C02 # https://doc.comsol.com/5.6/doc/com.comsol.help.cfd/cfd_ug_fluidflow_high_mach.08.27.html # Calculated via the equation: self_beta = 1.370**10-5 * (273+self._S)/273**(3/2) - self._R0 = 3_396_200 # (meters) Mean Equatorial Radius of Mars elif self.planet == 'Venus': # 96% CO2 atmosphere M_air = 43.45 # (kg/kmol) Venus, 12 Apr 2024, by Cedric Gillmann et al. https://arxiv.org/html/2404.07669v2 @@ -189,7 +141,6 @@ def setup(self): self._S = 222 # (K) we use the constant for CO2 which is simillar to Mars because this atmosphere is primarily driven by CO2 interaction. self._beta = 1.503e-6 # (s*m*K**(1/2)) viscosity scaling coefficient calculated from other constants listed for C02, the same way as was done for Mars # the only input the the equation os self._S so this result is the same as Mars - self._R0 = 6_051_800 # (meters) Mean Equatorial Radius self._R_air = Rs / M_air # (J/ (kg * K)), gas constant for atmosphere self._K = gamma * Rs / M_air # (J/(kg * K)) diff --git a/aviary/subsystems/atmosphere/utils/get_atmosphere_data.py b/aviary/subsystems/atmosphere/utils/get_atmosphere_data.py new file mode 100644 index 0000000000..7fc8f0dc2f --- /dev/null +++ b/aviary/subsystems/atmosphere/utils/get_atmosphere_data.py @@ -0,0 +1,59 @@ +from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Cold import atm_data as cold_210A +from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Hot import atm_data as hot_210A +from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Polar import atm_data as polar_210A +from aviary.subsystems.atmosphere.data.MIL_SPEC_210A_Tropical import atm_data as tropical_210A +from aviary.subsystems.atmosphere.data.StandardAtm1976 import atm_data as USatm1976 +from aviary.subsystems.atmosphere.data.MarsReference2024 import atm_data as MarsReference2024 +from aviary.subsystems.atmosphere.data.MarsHellasHot import atm_data as MarsHellasHot +from aviary.subsystems.atmosphere.data.MarsHellasCold import atm_data as MarsHellasCold +from aviary.subsystems.atmosphere.data.MarsEquatorHot import atm_data as MarsEquatorHot +from aviary.subsystems.atmosphere.data.MarsEquatorCold import atm_data as MarsEquatorCold +from aviary.subsystems.atmosphere.data.MarsPolarHot import atm_data as MarsPolarHot +from aviary.subsystems.atmosphere.data.MarsPolarCold import atm_data as MarsPolarCold +from aviary.subsystems.atmosphere.data.VenusReference2021 import atm_data as VenusReference2021 +from aviary.variable_info.enums import AtmosphereModel +from aviary.constants import ( + RADIUS_EARTH, + RADIUS_MARS, + RADIUS_VENUS, + GRAV_EARTH, + GRAV_MARS, + GRAV_VENUS, +) + + +def get_atmosphere_data(atmosphere_model): + """ + Return the atmosphere source data, planet name, and gravitational constant + associated with the requested atmosphere model. + + Parameters + ---------- + atmosphere_model : AtmosphereModel + Atmosphere model enum. + + Returns + ------- + tuple + (source_data, planet, gravity) + """ + atmosphere_lookup = { + AtmosphereModel.STANDARD: (USatm1976, 'Earth', RADIUS_EARTH, GRAV_EARTH), + AtmosphereModel.TROPICAL: (tropical_210A, 'Earth', RADIUS_EARTH, GRAV_EARTH), + AtmosphereModel.POLAR: (polar_210A, 'Earth', RADIUS_EARTH, GRAV_EARTH), + AtmosphereModel.HOT: (hot_210A, 'Earth', RADIUS_EARTH, GRAV_EARTH), + AtmosphereModel.COLD: (cold_210A, 'Earth', RADIUS_EARTH, GRAV_EARTH), + AtmosphereModel.MARS_REFERENCE: (MarsReference2024, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_HELLAS_HOT: (MarsHellasHot, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_HELLAS_COLD: (MarsHellasCold, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_EQUATOR_HOT: (MarsEquatorHot, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_EQUATOR_COLD: (MarsEquatorCold, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_POLAR_HOT: (MarsPolarHot, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.MARS_POLAR_COLD: (MarsPolarCold, 'Mars', RADIUS_MARS, GRAV_MARS), + AtmosphereModel.VENUS_REFERENCE: (VenusReference2021, 'Venus', RADIUS_VENUS, GRAV_VENUS), + } + + try: + return atmosphere_lookup[atmosphere_model] + except KeyError: + raise ValueError(f'Could not find {atmosphere_model} in get_atmosphere_data().') diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index cc4fefbe36..6455e6d479 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -92,6 +92,21 @@ def preprocess_options( ): aviary_options.set_val(Aircraft.Design.PERCENT_EXCRESCENCE_DRAG, 0.06) + # preprocess atmosphere / GRAV?? + # Set the gravity model based on the atmosphere model to enable calculation of weight from mass + from aviary.subsystems.atmosphere.utils.get_atmosphere_data import get_atmosphere_data + + if Settings.ATMOSPHERE_MODEL not in aviary_options: + aviary_options.set_val( + Settings.ATMOSPHERE_MODEL, meta_data[Settings.ATMOSPHERE_MODEL]['default_value'] + ) + _, _, _, planet_gravity = get_atmosphere_data(aviary_options.get_val(Settings.ATMOSPHERE_MODEL)) + if Mission.GRAVITY not in aviary_options: # Check to see if the user has set a gravity profile. + # No gravity profile is set, set it now. + aviary_options.set_val( + Mission.GRAVITY, val=planet_gravity[0], units=planet_gravity[1] + ) # contains both value and units as a tuple. + def preprocess_crewpayload(aviary_options: AviaryValues, meta_data=CoreMetaData, verbosity=None): """ diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 7f6133e50d..0a333bb095 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -6892,6 +6892,17 @@ 'specifies a taxi phase as part of the regular mission phases.', ) +add_meta_data( + Mission.GRAVITY, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None}, + desc='Gravitational acceleration of the planet.', + types=float, + option=True, + # The default gravity model is set based on Settings.ATMOSPHERE_MODEL + units='m/s**2', +) + add_meta_data( Mission.GROSS_MASS, meta_data=_MetaData, diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 8ebb486e91..a6a2ab7d74 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -676,6 +676,7 @@ class Mission: FINAL_MASS = 'mission:final_mass' FINAL_TIME = 'mission:final_time' FUEL_MASS = 'mission:fuel_mass' + GRAVITY = 'mission:gravity' GROSS_MASS = 'mission:gross_mass' OPERATING_ITEMS_MASS = 'mission:operating_items_mass' OPERATING_ITEMS_MASS_ADDITIONAL = 'mission:operating_items_mass_additional'