Source code for flow360_schema.models.simulation.models.turbulence_quantities

"""Turbulence quantities parameters."""

from abc import ABCMeta
from typing import Annotated, Literal

import pydantic as pd

from flow360_schema.framework.base_model import Flow360BaseModel
from flow360_schema.framework.physical_dimensions import (
    Frequency,
    KinematicViscosity,
    Length,
    SpecificEnergy,
)


class TurbulentKineticEnergy(Flow360BaseModel):
    """
    turbulentKineticEnergy : SpecificEnergyType [energy / mass]
        Turbulent kinetic energy. Applicable only when using SST model.
    """

    type_name: Literal["TurbulentKineticEnergy"] = pd.Field("TurbulentKineticEnergy", frozen=True)
    turbulent_kinetic_energy: SpecificEnergy.NonNegativeFloat64 = pd.Field()


class TurbulentIntensity(Flow360BaseModel):
    """
    turbulentIntensity : non-dimensional [`-`]
        Turbulent intensity. Applicable only when using SST model.
        This is related to turbulent kinetic energy as:
        `turbulentKineticEnergy = 1.5*pow(U_ref * turbulentIntensity, 2)`.
        Note the use of the freestream velocity U_ref instead of C_inf.
    """

    type_name: Literal["TurbulentIntensity"] = pd.Field("TurbulentIntensity", frozen=True)
    turbulent_intensity: pd.NonNegativeFloat = pd.Field()


class _SpecificDissipationRate(Flow360BaseModel, metaclass=ABCMeta):
    """
    specificDissipationRate : FrequencyType  [1 / time]
        Turbulent specific dissipation rate. Applicable only when using SST model.
    """

    type_name: Literal["SpecificDissipationRate"] = pd.Field("SpecificDissipationRate", frozen=True)
    specific_dissipation_rate: Frequency.NonNegativeFloat64 = pd.Field()


class TurbulentViscosityRatio(Flow360BaseModel):
    """
    turbulentViscosityRatio : non-dimensional [`-`]
        The ratio of turbulent eddy viscosity over the freestream viscosity. Applicable for both SA and SST model.
    """

    type_name: Literal["TurbulentViscosityRatio"] = pd.Field("TurbulentViscosityRatio", frozen=True)
    turbulent_viscosity_ratio: pd.PositiveFloat = pd.Field()


class TurbulentLengthScale(Flow360BaseModel, metaclass=ABCMeta):
    """
    turbulentLengthScale : LengthType [length]
        The turbulent length scale is an estimation of the size of the eddies that are modeled/not resolved.
        Applicable only when using SST model. This is related to the turbulent kinetic energy and turbulent
        specific dissipation rate as: `L_T = sqrt(k)/(pow(beta_0^*, 0.25)*w)` where `L_T` is turbulent length scale,
        `k` is turbulent kinetic energy, `beta_0^*` is 0.09 and `w` is turbulent specific dissipation rate.
        Applicable only when using SST model.
    """

    type_name: Literal["TurbulentLengthScale"] = pd.Field("TurbulentLengthScale", frozen=True)
    turbulent_length_scale: Length.PositiveFloat64 = pd.Field()


class ModifiedTurbulentViscosityRatio(Flow360BaseModel):
    """
    modifiedTurbulentViscosityRatio : non-dimensional [`-`]
        The ratio of modified turbulent eddy viscosity (SA) over the freestream viscosity.
        Applicable only when using SA model.
    """

    type_name: Literal["ModifiedTurbulentViscosityRatio"] = pd.Field("ModifiedTurbulentViscosityRatio", frozen=True)
    modified_turbulent_viscosity_ratio: pd.PositiveFloat = pd.Field()


class ModifiedTurbulentViscosity(Flow360BaseModel):
    """
    modifiedTurbulentViscosity : KinematicViscosityType [length**2 / time]
        The modified turbulent eddy viscosity (SA). Applicable only when using SA model.
    """

    type_name: Literal["ModifiedTurbulentViscosity"] = pd.Field("ModifiedTurbulentViscosity", frozen=True)
    modified_turbulent_viscosity: KinematicViscosity.PositiveFloat64 | None = pd.Field()


class SpecificDissipationRateAndTurbulentKineticEnergy(_SpecificDissipationRate, TurbulentKineticEnergy):
    type_name: Literal["SpecificDissipationRateAndTurbulentKineticEnergy"] = pd.Field(
        "SpecificDissipationRateAndTurbulentKineticEnergy", frozen=True
    )


class TurbulentViscosityRatioAndTurbulentKineticEnergy(TurbulentViscosityRatio, TurbulentKineticEnergy):
    type_name: Literal["TurbulentViscosityRatioAndTurbulentKineticEnergy"] = pd.Field(
        "TurbulentViscosityRatioAndTurbulentKineticEnergy", frozen=True
    )


class TurbulentLengthScaleAndTurbulentKineticEnergy(TurbulentLengthScale, TurbulentKineticEnergy):
    type_name: Literal["TurbulentLengthScaleAndTurbulentKineticEnergy"] = pd.Field(
        "TurbulentLengthScaleAndTurbulentKineticEnergy", frozen=True
    )


class TurbulentIntensityAndSpecificDissipationRate(TurbulentIntensity, _SpecificDissipationRate):
    type_name: Literal["TurbulentIntensityAndSpecificDissipationRate"] = pd.Field(
        "TurbulentIntensityAndSpecificDissipationRate", frozen=True
    )


class TurbulentIntensityAndTurbulentViscosityRatio(TurbulentIntensity, TurbulentViscosityRatio):
    type_name: Literal["TurbulentIntensityAndTurbulentViscosityRatio"] = pd.Field(
        "TurbulentIntensityAndTurbulentViscosityRatio", frozen=True
    )


class TurbulentIntensityAndTurbulentLengthScale(TurbulentIntensity, TurbulentLengthScale):
    type_name: Literal["TurbulentIntensityAndTurbulentLengthScale"] = pd.Field(
        "TurbulentIntensityAndTurbulentLengthScale", frozen=True
    )


class SpecificDissipationRateAndTurbulentViscosityRatio(_SpecificDissipationRate, TurbulentViscosityRatio):
    type_name: Literal["SpecificDissipationRateAndTurbulentViscosityRatio"] = pd.Field(
        "SpecificDissipationRateAndTurbulentViscosityRatio", frozen=True
    )


class SpecificDissipationRateAndTurbulentLengthScale(_SpecificDissipationRate, TurbulentLengthScale):
    type_name: Literal["SpecificDissipationRateAndTurbulentLengthScale"] = pd.Field(
        "SpecificDissipationRateAndTurbulentLengthScale", frozen=True
    )


class TurbulentViscosityRatioAndTurbulentLengthScale(TurbulentViscosityRatio, TurbulentLengthScale):
    type_name: Literal["TurbulentViscosityRatioAndTurbulentLengthScale"] = pd.Field(
        "TurbulentViscosityRatioAndTurbulentLengthScale", frozen=True
    )


TurbulenceQuantitiesType = Annotated[
    TurbulentViscosityRatio
    | TurbulentKineticEnergy
    | TurbulentIntensity
    | TurbulentLengthScale
    | ModifiedTurbulentViscosityRatio
    | ModifiedTurbulentViscosity
    | SpecificDissipationRateAndTurbulentKineticEnergy
    | TurbulentViscosityRatioAndTurbulentKineticEnergy
    | TurbulentLengthScaleAndTurbulentKineticEnergy
    | TurbulentIntensityAndSpecificDissipationRate
    | TurbulentIntensityAndTurbulentViscosityRatio
    | TurbulentIntensityAndTurbulentLengthScale
    | SpecificDissipationRateAndTurbulentViscosityRatio
    | SpecificDissipationRateAndTurbulentLengthScale
    | TurbulentViscosityRatioAndTurbulentLengthScale,
    pd.Field(discriminator="type_name"),
]


[docs] def TurbulenceQuantities( viscosity_ratio=None, modified_viscosity_ratio=None, modified_viscosity=None, specific_dissipation_rate=None, turbulent_kinetic_energy=None, turbulent_length_scale=None, turbulent_intensity=None, ) -> TurbulenceQuantitiesType: r""" :func:`TurbulenceQuantities` function specifies turbulence conditions for the :class:`~flow360.Inflow` or :class:`~flow360.Freestream` at boundaries. The turbulence properties that can be specified are listed below. All values are dimensional. For valid specifications as well as the default values, please see the `Notes` section below. Parameters ---------- viscosity_ratio : >= 0 The ratio between the turbulent viscosity and freestream laminar viscosity. Applicable to both :class:`~flow360.KOmegaSST` and :class:`~flow360.SpalartAllmaras`. Its value will be converted to :py:attr:`modifiedTurbulentViscosityRatio` when using SpalartAllmaras model. modified_viscosity_ratio : >= 0 The ratio between the modified turbulent viscosity (in SA model) and freestream laminar viscosity. Applicable to :class:`~flow360.SpalartAllmaras`. modified_viscosity : >=0 The modified turbulent viscosity, aka nuHat. Applicable to :class:`~flow360.SpalartAllmaras`. specific_dissipation_rate : >= 0 The turbulent specific dissipation rate. Applicable to :class:`~flow360.KOmegaSST`. turbulent_kinetic_energy : >=0 The turbulent kinetic energy. Applicable to :class:`~flow360.KOmegaSST`. turbulent_length_scale : > 0 The turbulent length scale is an estimation of the size of the eddies that are modeled/not resolved. Applicable to :class:`~flow360.KOmegaSST`. turbulent_intensity : >= 0 The turbulent intensity is related to the turbulent kinetic energy by :math:`k = 1.5(U_{ref} * I)^2` where :math:`k` is the dimensional turbulent kinetic energy, :math:`U_{ref}` is the reference velocity and :math:`I` is the turbulent intensity. The value represents the actual magnitude of intensity instead of percentage. Applicable to :class:`~flow360.KOmegaSST`. Returns ------- A matching tubulence specification object. Raises ------- ValueError If the TurbulenceQuantities inputs do not represent a valid specification. """ non_none_arg_count = sum(arg is not None for arg in locals().values()) if non_none_arg_count == 0: return None if non_none_arg_count > 2: raise ValueError( "Provided number of inputs exceeds the limit for any of the listed specifications. " + "Please recheck TurbulenceQuantities inputs and make sure they represent a valid specification." ) if viscosity_ratio is not None: if non_none_arg_count == 1: return TurbulentViscosityRatio(turbulent_viscosity_ratio=viscosity_ratio) if turbulent_kinetic_energy is not None: return TurbulentViscosityRatioAndTurbulentKineticEnergy( turbulent_viscosity_ratio=viscosity_ratio, turbulent_kinetic_energy=turbulent_kinetic_energy, ) if turbulent_intensity is not None: return TurbulentIntensityAndTurbulentViscosityRatio( turbulent_viscosity_ratio=viscosity_ratio, turbulent_intensity=turbulent_intensity, ) if specific_dissipation_rate is not None: return SpecificDissipationRateAndTurbulentViscosityRatio( turbulent_viscosity_ratio=viscosity_ratio, specific_dissipation_rate=specific_dissipation_rate, ) if turbulent_length_scale is not None: return TurbulentViscosityRatioAndTurbulentLengthScale( turbulent_viscosity_ratio=viscosity_ratio, turbulent_length_scale=turbulent_length_scale, ) if modified_viscosity_ratio is not None and non_none_arg_count == 1: return ModifiedTurbulentViscosityRatio(modified_turbulent_viscosity_ratio=modified_viscosity_ratio) if modified_viscosity is not None and non_none_arg_count == 1: return ModifiedTurbulentViscosity(modified_turbulent_viscosity=modified_viscosity) if turbulent_intensity is not None: if non_none_arg_count == 1: return TurbulentIntensity(turbulent_intensity=turbulent_intensity) if specific_dissipation_rate is not None: return TurbulentIntensityAndSpecificDissipationRate( turbulent_intensity=turbulent_intensity, specific_dissipation_rate=specific_dissipation_rate, ) if turbulent_length_scale is not None: return TurbulentIntensityAndTurbulentLengthScale( turbulent_intensity=turbulent_intensity, turbulent_length_scale=turbulent_length_scale, ) if turbulent_kinetic_energy is not None: if non_none_arg_count == 1: return TurbulentKineticEnergy(turbulent_kinetic_energy=turbulent_kinetic_energy) if specific_dissipation_rate is not None: return SpecificDissipationRateAndTurbulentKineticEnergy( turbulent_kinetic_energy=turbulent_kinetic_energy, specific_dissipation_rate=specific_dissipation_rate, ) if turbulent_length_scale is not None: return TurbulentLengthScaleAndTurbulentKineticEnergy( turbulent_kinetic_energy=turbulent_kinetic_energy, turbulent_length_scale=turbulent_length_scale, ) if turbulent_length_scale is not None and non_none_arg_count == 1: return TurbulentLengthScale(turbulent_length_scale=turbulent_length_scale) if specific_dissipation_rate is not None: if turbulent_length_scale is not None: return SpecificDissipationRateAndTurbulentLengthScale( specific_dissipation_rate=specific_dissipation_rate, turbulent_length_scale=turbulent_length_scale, ) raise ValueError( "Provided inputs do not create a valid specification. " + "Please recheck TurbulenceQuantities inputs and make sure they represent a valid specification." )