Source code for g3d.calc.calculators.normal_shock

"""Normal-shock calculator"""
import os
from typing import Union, Any

if os.environ.get('__USE_CUDA', '0') == '1':
    import cupy as np
else:
    import numpy as np

from .calculator import G3DCalculator

from g3d.defs import CFlowVariableType


[docs] class G3DNormalShockCalculator(G3DCalculator): """Class collecting functions related to normal shocks""" def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize calculator parameters""" super().__init__(*args, **kwargs) def _set_default(self) -> None: super()._set_default() self.__PR = self._vars.add(name="PR", long_name="Pressure ratio") self.__TR = self._vars.add(name="TR", long_name="Temperature ratio") self.__RR = self._vars.add(name="RR", long_name="Density ratio") self.__PoR = self._vars.add(name="PoR", long_name="Total pressure ratio") self.__M1 = self._vars.add(name="M1", long_name="Mach number (upstream)") self.__T1 = self._vars.add(name="T1", long_name="Temperature (upstream)", type=CFlowVariableType.TEMPERATURE) self.__P1 = self._vars.add(name="P1", long_name="Pressure (upstream)", type=CFlowVariableType.PRESSURE) self.__RO1 = self._vars.add(name="RO1", long_name="Density (upstream)", type=CFlowVariableType.DENSITY) self.__Po1 = self._vars.add(name="Po1", long_name="Total pressure (upstream)", type=CFlowVariableType.PRESSURE) self.__As1 = self._vars.add(name="As1", long_name="Choke area (upstream)", type=CFlowVariableType.AREA) self.__M2 = self._vars.add(name="M2", long_name="Mach number (downstream)") self.__T2 = self._vars.add(name="T2", long_name="Temperature (downstream)", type=CFlowVariableType.TEMPERATURE) self.__P2 = self._vars.add(name="P2", long_name="Pressure (downstream)", type=CFlowVariableType.PRESSURE) self.__RO2 = self._vars.add(name="RO2", long_name="Density (downstream)", type=CFlowVariableType.DENSITY) self.__Po2 = self._vars.add(name="Po2", long_name="Total pressure (downstream)", type=CFlowVariableType.PRESSURE) self.__As2 = self._vars.add(name="As2", long_name="Choke area (downstream)", type=CFlowVariableType.AREA)
[docs] def get_downstream_Mach(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate Mach number downstream of normal shock (M2 []) as function of upstream Mach number (M1 []) input: upstream Mach number (M1 []) example: M2 = get_downstream_Mach(M1=M1) """ return self._eval(["M1"], self.__get_downstream_Mach, *args, **kwargs)
def __get_downstream_Mach(self, M1: float = None) -> float: if M1 is None: M1 = self.__M1.value return np.sqrt((1. + 0.5 * self._gas.gm1 * M1 * M1) / (self._gas.gamma * M1 * M1 - 0.5 * self._gas.gm1))
[docs] def get_upstream_Mach(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate Mach number upstream of normal shock (M1 []) as function of downstream Mach number (M2 []) input: downstream Mach number (M2 []) example: M1 = get_upstream_Mach(M2=M2s) """ return self._eval(["M2"], self.__get_upstream_Mach, *args, **kwargs)
def __get_upstream_Mach(self, M2: float = None) -> float: if M2 is None: M2 = self.__M2.value return self.__get_downstream_Mach(M2)
[docs] def get_downstream_density(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate density downstream of normal shock (RO2 [kg/m^3]) as function of upstream Mach number (M1 []), and upstream density (RO1 [kg/m^3]) input: upstream Mach number (M1 []), upstream density (RO1 [kg/m^3], default value: 1.0) example: RO2 = get_downstream_density(M1=M1, RO1=RO1) """ return self._eval(["M1", "RO1"], self.__get_downstream_density, *args, **kwargs)
def __get_downstream_density(self, M1: float = None, RO1: float = None) -> float: if M1 is None: M1 = self.__M1.value if RO1 is None: RO1 = self.__RO1.value return RO1 * ((self._gas.gp1 * M1 * M1) / (2. + self._gas.gm1 * M1 * M1))
[docs] def get_downstream_pressure(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate pressure downstream of normal shock (P2 [Pa]) as function of upstream Mach number (M1 []), and upstream pressure (P1 [Pa]) input: upstream Mach number (M1 []), upstream pressure (P1 [Pa], default value: 1.0) example: P2 = get_downstream_pressure(M1=M1, P1=P1) """ return self._eval(["M1", "P1"], self.__get_downstream_pressure, *args, **kwargs)
def __get_downstream_pressure(self, M1: float = None, P1: float = None) -> float: if M1 is None: M1 = self.__M1.value if P1 is None: P1 = self.__P1.value return P1 * (1.0 + ((2.0 * self._gas.gamma) / self._gas.gp1) * (M1 * M1 - 1.0))
[docs] def get_downstream_total_pressure(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate total pressure downstream of normal shock (Po2 [Pa]) as function of upstream Mach number (M1 []), and upstream total pressure (Po1 [Pa]) input: upstream Mach number (M1 []), upstream total pressure (Po1 [Pa], default value: 1.0) example: Po2 = get_downstream_total_pressure(M1=M1, Po1=Po1) """ return self._eval(["M1", "Po1"], self.__get_downstream_total_pressure, *args, **kwargs)
def __get_downstream_total_pressure(self, M1: float = None, Po1: float = None) -> float: if M1 is None: M1 = self.__M1.value if Po1 is None: Po1 = self.__Po1.value M2 = self.__get_downstream_Mach(M1) return Po1 * self.__get_downstream_pressure(M1, 1.0) * \ self._stagnation.get_total_pressure(M2, 1.0) / self._stagnation.get_total_pressure(M1, 1.0)
[docs] def get_downstream_temperature(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate temperature downstream of normal shock (T2 [K]) as function of upstream Mach number (M1 []), and upstream temperature (T1 [K]) input: upstream Mach number (M1 []), upstream temperature (T1 [K], default value: 1.0) example: T2 = get_downstream_pressure(M1=M1, T1=T1) """ return self._eval(["M1", "T1"], self.__get_downstream_temperature, *args, **kwargs)
def __get_downstream_temperature(self, M1: float = None, T1: float = None) -> float: if M1 is None: M1 = self.__M1.value if T1 is None: T1 = self.__T1.value return (T1 * (1.0 + ((2.0 * self._gas.gamma) / self._gas.gp1) * (M1 * M1 - 1.0)) * ((2. + self._gas.gm1 * M1 * M1) / (self._gas.gp1 * M1 * M1)))
[docs] def get_downstream_Astar(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate choke cross-section area downstream of normal shock (As2 [m^2]) as function of upstream Mach number (M1 []),and upstream choke cross-section area (As1 [m^2]) input: upstream Mach number (M1 []), upstream choke cross-section area (As1 [m^2], default value: 1.0) example: As2 = get_downstream_Astar(M1=M1, As1=As1) """ return self._eval(["M1", "As1"], self.__get_downstream_Astar, *args, **kwargs)
def __get_downstream_Astar(self, M1: float = None, As1: float = None) -> float: if M1 is None: M1 = self.__M1.value if As1 is None: As1 = self.__As1.value M2 = self.__get_downstream_Mach(M1) return (As1 * (M2 / M1) * np.sqrt(((2. + self._gas.gm1 * M1 ** 2) / (2. + self._gas.gm1 * M2 ** 2)) ** (self._gas.gp1 / self._gas.gm1)))
[docs] def get_upstream_Astar(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate choke cross-section area upstream of normal shock (As1 [m^2]) as function of downstream Mach number (M2 []),and downstream choke cross-section area (As2 [m^2]) input: downstream Mach number (M2 []), downstream choke cross-section area (As2 [m^2], default value: 1.0) example: As1 = get_upstream_Astar(M2=M2, As2=As2) """ return self._eval(["M2", "As2"], self.__get_upstream_Astar, *args, **kwargs)
def __get_upstream_Astar(self, M2: float = None, As2: float = None) -> float: if M2 is None: M2 = self.__M2.value if As2 is None: As2 = self.__As2.value M1 = self.__get_upstream_Mach(M2) return (As2 / ((M2 / M1) * np.sqrt(((2. + self._gas.gm1 * M1 ** 2) / (2. + self._gas.gm1 * M2 ** 2)) ** (self._gas.gp1 / self._gas.gm1))))
[docs] def get_upstream_Mach_from_pressure_ratio(self, *args: Any, **kwargs: Any) \ -> Union[np.float64, list[np.float64], float]: """ calculate upstream Mach number (M1 []) from normal shock pressure ratio (PR []) input: pressure ratio (PR []) example: M1 = get_upstream_Mach_from_pressure_ratio(PR=PR) """ return self._eval(["PR"], self.__get_upstream_Mach_from_pressure_ratio, *args, **kwargs)
def __get_upstream_Mach_from_pressure_ratio(self, PR: float = None) -> float: if PR is None: PR = self.__PR.value return np.sqrt(1. + (self._gas.gp1 / (2. * self._gas.gamma)) * (PR - 1.))
[docs] def get_upstream_Mach_from_density_ratio(self, *args: Any, **kwargs: Any) \ -> Union[np.float64, list[np.float64], float]: """ calculate upstream Mach number (M1 []) from normal shock density ratio (RR []) input: density ratio (RR []) example: M1 = get_upstream_Mach_from_density_ratio(RR=RR) """ return self._eval(["RR"], self.__get_upstream_Mach_from_density_ratio, *args, **kwargs)
def __get_upstream_Mach_from_density_ratio(self, RR: float = None) -> float: if RR is None: RR = self.__RR.value return np.sqrt((2. * RR) / (self._gas.gp1 - self._gas.gm1 * RR))
[docs] def get_upstream_Mach_from_temperature_ratio(self, *args: Any, **kwargs: Any) \ -> Union[np.float64, list[np.float64], float]: """ calculate upstream Mach number (M1 []) from normal shock temperature ratio (TR []) upstream Mach number is calculated using the built-in Newton-Raphson solver input: density ratio (TR []) example: M1 = get_upstream_Mach_from_temperature_ratio(TR=TR) """ self._newton.reset() self._newton.start_value = 2.0 return self._eval(["TR"], self.__get_upstream_Mach_from_temperature_ratio, *args, **kwargs)
def __get_upstream_Mach_from_temperature_ratio(self, TR: float = None) -> float: if TR is None: TR = self.__TR.value # run Newton solver to find Mach number newton = self._get_newton_kernel() return newton.solve(self.__get_downstream_temperature, target_value=TR)
[docs] def get_upstream_Mach_from_total_pressure_ratio(self, *args: Any, **kwargs: Any) \ -> Union[np.float64, list[np.float64], float]: """ calculate upstream Mach number (M1 []) from normal shock total pressure ratio (PoR []) upstream Mach number is calculated using the built-in Newton-Raphson solver input: density ratio (PoR []) example: M1 = get_upstream_Mach_from_total_pressure_ratio(PoR=PoR) """ self._newton.reset() self._newton.start_value = 2.0 return self._eval(["PoR"], self.__get_upstream_Mach_from_total_pressure_ratio, *args, **kwargs)
def __get_upstream_Mach_from_total_pressure_ratio(self, PoR: float = None) -> float: if PoR is None: PoR = self.__PoR.value self.__Po1.value = 1.0 # run Newton solver to find Mach number newton = self._get_newton_kernel() return newton.solve(self.__get_downstream_total_pressure, target_value=PoR)
[docs] def get_entropy_increase(self, *args: Any, **kwargs: Any) -> Union[Union[tuple[Any, ...], list[Any]], Any]: """ calculate normal shock entropy increase from upstream Mach number (M1 []) input: upstream Mach number (M1 []) example: dS = get_entropy_increase(M1=M1) """ return self._eval(["M1"], self.__get_entropy_increase, *args, **kwargs)
def __get_entropy_increase(self, M1: float = None) -> float: if M1 is None: M1 = self.__M1.value return -self._gas.R * np.log(self.__get_downstream_total_pressure(M1, 1.0))