"""Functions for computation of the partial derivative of atmosphere state parameters."""
# This file is part of StdAtm
# Copyright (C) 2023 ONERA & ISAE-SUPAERO
# StdAtm is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from functools import lru_cache, singledispatch
from numbers import Real
from typing import Union
import math
import numpy as np
from .state_parameters import (
SEA_LEVEL_PRESSURE,
SEA_LEVEL_TEMPERATURE,
TROPOPAUSE,
AIR_GAS_CONSTANT,
)
# PARTIAL TEMPERATURE =================================================================
[docs]@singledispatch
def compute_partial_temperature(altitude) -> np.ndarray:
"""
:param altitude: in m
:return: Partial of temperature in K with respect to altitude in m
"""
# Implementation for numpy arrays
idx_tropo = altitude < TROPOPAUSE
# Since the derivative for the stratosphere is zero, we will start with a zeros_like and not
# an empty_like
partial_temperature = np.zeros_like(altitude)
partial_temperature[idx_tropo] = -0.0065
return partial_temperature
@compute_partial_temperature.register
@lru_cache()
def _(altitude: Real) -> float:
# Implementation for floats
if altitude < TROPOPAUSE:
partial_temperature = -0.0065
else:
partial_temperature = 0.0
return partial_temperature
# PARTIAL PRESSURE =================================================================
COEFF_PARTIAL_PRESSURE_1 = -5.25587611 / 44330.78
COEFF_PARTIAL_PRESSURE_2 = -0.0001576883 * 22632.0 * math.log(2.718281)
[docs]@singledispatch
def compute_partial_pressure(altitude) -> np.ndarray:
"""
:param altitude: in m
:return: Partial of pressure in Pa with respect to altitude in m
"""
# Implementation for numpy arrays
idx_tropo = altitude < TROPOPAUSE
idx_strato = np.logical_not(idx_tropo)
partial_pressure = np.empty_like(altitude)
partial_pressure[idx_tropo] = (
COEFF_PARTIAL_PRESSURE_1
* SEA_LEVEL_PRESSURE
* (1 - (altitude[idx_tropo] / 44330.78)) ** 4.25587611
)
partial_pressure[idx_strato] = COEFF_PARTIAL_PRESSURE_2 * 2.718281 ** (
1.7345725 - 0.0001576883 * altitude[idx_strato]
)
return partial_pressure
@compute_partial_pressure.register
@lru_cache()
def _(altitude: Real) -> float:
# Implementation for floats
if altitude < TROPOPAUSE:
partial_temperature = (
COEFF_PARTIAL_PRESSURE_1
* SEA_LEVEL_PRESSURE
* (1 - (altitude / 44330.78)) ** 4.25587611
)
else:
partial_temperature = COEFF_PARTIAL_PRESSURE_2 * 2.718281 ** (
1.7345725 - 0.0001576883 * altitude
)
return partial_temperature
# PARTIAL DENSITY =================================================================
[docs]def compute_partial_density(
temperature: Union[np.ndarray, Real],
pressure: Union[np.ndarray, Real],
partial_temperature_altitude: Union[np.ndarray, Real],
partial_pressure_altitude: Union[np.ndarray, Real],
) -> Union[np.ndarray, Real]:
"""
:param temperature: in K
:param pressure: in Pa
:param partial_temperature_altitude: derivative of the temperature in K with respect to the
altitude
:param partial_pressure_altitude: derivative of the pressure in Pa with respect to the
altitude
:return: Partial of density in kg/m**3 with respect to altitude
"""
partial_density = (
1.0
/ AIR_GAS_CONSTANT
* (partial_pressure_altitude * temperature - pressure * partial_temperature_altitude)
/ temperature**2.0
)
return partial_density
# SPEED OF SOUND =================================================
[docs]def compute_partial_speed_of_sound(
temperature: Union[np.ndarray, Real],
partial_temperature_altitude: Union[np.ndarray, Real],
) -> Union[np.ndarray, Real]:
"""
:param temperature: in K
:param partial_temperature_altitude: derivative of the temperature in K with respect to the
altitude
:return: Partial of speed of sound in m/s with respect to altitude
"""
partial_speed_of_sound = (
0.5 * (1.4 * AIR_GAS_CONSTANT / temperature) ** 0.5 * partial_temperature_altitude
)
return partial_speed_of_sound
# DYNAMIC VISCOSITY =================================================
COEFF_PARTIAL_MU_1 = 0.000017894 * (SEA_LEVEL_TEMPERATURE + 110.4) / SEA_LEVEL_TEMPERATURE**1.5
[docs]def compute_partial_dynamic_viscosity(
temperature: Union[np.ndarray, Real],
partial_temperature_altitude: Union[np.ndarray, Real],
) -> Union[np.ndarray, Real]:
"""
:param temperature: in K
:param partial_temperature_altitude: derivative of the temperature in K with respect to the
altitude
:return: Partial of dynamic viscosity in kg/m/s with respect to altitude
"""
partial_dynamic_viscosity = (
COEFF_PARTIAL_MU_1
* (0.5 * temperature**1.5 + 110.4 * 1.5 * temperature**0.5)
/ (temperature + 110.4) ** 2.0
* partial_temperature_altitude
)
return partial_dynamic_viscosity
# KINEMATIC VISCOSITY =================================================
[docs]def compute_partial_kinematic_viscosity(
dynamic_viscosity: Union[np.ndarray, Real],
density: Union[np.ndarray, Real],
partial_dynamic_viscosity_altitude: Union[np.ndarray, Real],
partial_density_altitude: Union[np.ndarray, Real],
) -> Union[np.ndarray, Real]:
"""
:param dynamic_viscosity: in kg/m/s
:param density: in kg/m**3
:param partial_dynamic_viscosity_altitude: derivative of the dynamic viscosity in kg/m/s with
respect to the altitude
:param partial_density_altitude: derivative of the density in kg/m**3 with respect to the
altitude
:return: Partial of kinematic viscosity in m**2/s with respect to altitude
"""
partial_kinematic_viscosity = (
partial_dynamic_viscosity_altitude * density - dynamic_viscosity * partial_density_altitude
) / density**2.0
return partial_kinematic_viscosity