Source code for flow360.component.flow360_params.volume_zones

"""
Volume zones parameters
"""

# pylint: disable=too-many-lines
# pylint: disable=unused-import
from __future__ import annotations

from abc import ABCMeta
from typing import Optional, Union

import pydantic as pd
from numpy import array, dot
from pydantic import StrictStr
from typing_extensions import Literal

from ..constants import NumericalConstants
from ..types import (
    Axis,
    Coordinate,
    List,
    NonNegativeFloat,
    PositiveFloat,
    PositiveInt,
    Tuple,
    Vector,
)
from .params_base import Flow360BaseModel
from .unit_system import (
    AngularVelocityType,
    HeatSourceType,
    InverseAreaType,
    InverseLengthType,
    LengthType,
)


class ReferenceFrameBase(Flow360BaseModel):
    """Base reference frame class"""

    model_type: str = pd.Field(alias="modelType")
    center: LengthType.Point = pd.Field(alias="centerOfRotation")
    axis: Axis = pd.Field(alias="axisOfRotation")
    parent_volume_name: Optional[str] = pd.Field(alias="parentVolumeName")

    # pylint: disable=missing-class-docstring,too-few-public-methods
    class Config(Flow360BaseModel.Config):
        exclude_on_flow360_export = ["model_type"]


[docs] class ReferenceFrameDynamic(ReferenceFrameBase): """:class:`ReferenceFrameDynamic` class for setting up dynamic reference frame Parameters ---------- center : Coordinate Coordinate representing the origin of rotation, eg. (0, 0, 0) axis : Axis Axis of rotation, eg. (0, 0, 1) Returns ------- :class:`ReferenceFrameDynamic` An instance of the component class ReferenceFrameDynamic. Example ------- >>> rf = ReferenceFrameDynamic( center=(0, 0, 0), axis=(0, 0, 1), ) """ model_type: Literal["Dynamic"] = pd.Field("Dynamic", alias="modelType", const=True)
[docs] class ReferenceFrameExpression(ReferenceFrameBase): """:class:`ReferenceFrameExpression` class for setting up reference frame using expression Parameters ---------- center : Coordinate Coordinate representing the origin of rotation, eg. (0, 0, 0) axis : Axis Axis of rotation, eg. (0, 0, 1) parent_volume_name : str, optional Name of the volume zone that the rotating reference frame is contained in, used to compute the acceleration in the nested rotating reference frame theta_radians : str, optional Expression for rotation angle (in radians) as a function of time theta_degrees : str, optional Expression for rotation angle (in degrees) as a function of time Returns ------- :class:`ReferenceFrameExpression` An instance of the component class ReferenceFrame. Example ------- >>> rf = ReferenceFrameExpression( center=(0, 0, 0), axis=(0, 0, 1), theta_radians="1 * t" ) """ model_type: Literal["Expression"] = pd.Field("Expression", alias="modelType", const=True) theta_radians: Optional[str] = pd.Field(alias="thetaRadians") theta_degrees: Optional[str] = pd.Field(alias="thetaDegrees") # pylint: disable=missing-class-docstring,too-few-public-methods class Config(ReferenceFrameBase.Config): require_one_of = [ "theta_radians", "theta_degrees", ]
[docs] class ReferenceFrameOmegaRadians(ReferenceFrameBase): """:class:`ReferenceFrameOmegaRadians` class for setting up reference frame Parameters ---------- center : Coordinate Coordinate representing the origin of rotation, eg. (0, 0, 0) axis : Axis Axis of rotation, eg. (0, 0, 1) omega_radians: float Nondimensional rotating speed, radians/nondim-unit-time Returns ------- :class:`ReferenceFrameOmegaRadians` An instance of the component class ReferenceFrameOmegaRadians. """ model_type: Literal["OmegaRadians"] = pd.Field("OmegaRadians", alias="modelType", const=True) omega_radians: float = pd.Field(alias="omegaRadians") # pylint: disable=arguments-differ
[docs] def to_solver(self, params, **kwargs) -> ReferenceFrameOmegaRadians: """ returns configuration object in flow360 units system """ return super().to_solver(params, **kwargs)
[docs] class ReferenceFrameOmegaDegrees(ReferenceFrameBase): """:class:`ReferenceFrameOmegaDegrees` class for setting up reference frame Parameters ---------- center : Coordinate Coordinate representing the origin of rotation, eg. (0, 0, 0) axis : Axis Axis of rotation, eg. (0, 0, 1) omega_degrees: AngularVelocityType Nondimensional rotating speed, radians/nondim-unit-time Returns ------- :class:`ReferenceFrameOmegaDegrees` An instance of the component class ReferenceFrameOmegaDegrees. """ model_type: Literal["OmegaDegrees"] = pd.Field("OmegaDegrees", alias="modelType", const=True) omega_degrees: float = pd.Field(alias="omegaDegrees") # pylint: disable=arguments-differ
[docs] def to_solver(self, params, **kwargs) -> ReferenceFrameOmegaDegrees: """ returns configuration object in flow360 units system """ return super().to_solver(params, **kwargs)
[docs] class ReferenceFrame(ReferenceFrameBase): """:class:`ReferenceFrame` class for setting up reference frame Parameters ---------- center : Coordinate Coordinate representing the origin of rotation, eg. (0, 0, 0) axis : Axis Axis of rotation, eg. (0, 0, 1) omega: AngularVelocityType Rotating speed, for example radians / s Returns ------- :class:`ReferenceFrame` An instance of the component class ReferenceFrame. Example ------- >>> rf = ReferenceFrame( center=(0, 0, 0), axis=(0, 0, 1), omega=1 * u.rad / u.s ) """ model_type: Literal["ReferenceFrame"] = pd.Field( "ReferenceFrame", alias="modelType", const=True ) omega: AngularVelocityType = pd.Field() # pylint: disable=arguments-differ
[docs] def to_solver(self, params, **kwargs) -> ReferenceFrameOmegaRadians: """ returns configuration object in flow360 units system """ solver_values = self._convert_dimensions_to_solver(params, **kwargs) omega_radians = solver_values.pop("omega").value solver_values.pop("model_type", None) return ReferenceFrameOmegaRadians(omega_radians=omega_radians, **solver_values)
class VolumeZoneBase(Flow360BaseModel, metaclass=ABCMeta): """Basic Boundary class""" model_type: str = pd.Field(alias="modelType")
[docs] class InitialConditionHeatTransfer(Flow360BaseModel): """InitialConditionHeatTransfer""" T: Union[PositiveFloat, StrictStr] = pd.Field(options=["Value", "Expression"])
ReferenceFrameType = Union[ ReferenceFrame, ReferenceFrameOmegaRadians, ReferenceFrameOmegaDegrees, ReferenceFrameExpression, ReferenceFrameDynamic, ]
[docs] class HeatTransferVolumeZone(VolumeZoneBase): """HeatTransferVolumeZone type""" model_type: Literal["HeatTransfer"] = pd.Field("HeatTransfer", alias="modelType", const=True) thermal_conductivity: PositiveFloat = pd.Field(alias="thermalConductivity") volumetric_heat_source: Optional[Union[NonNegativeFloat, StrictStr]] = pd.Field( alias="volumetricHeatSource", options=["Value", "Expression"] ) heat_capacity: Optional[PositiveFloat] = pd.Field(alias="heatCapacity") initial_condition: Optional[InitialConditionHeatTransfer] = pd.Field(alias="initialCondition")
[docs] class FluidDynamicsVolumeZone(VolumeZoneBase): """FluidDynamicsVolumeZone type""" model_type = pd.Field("FluidDynamics", alias="modelType", const=True) reference_frame: Optional[ReferenceFrameType] = pd.Field( alias="referenceFrame", discriminator="model_type" ) # pylint: disable=arguments-differ
[docs] def to_solver(self, params, **kwargs) -> FluidDynamicsVolumeZone: """ returns configuration object in flow360 units system """ return super().to_solver(params, **kwargs)
class PorousMediumBase(Flow360BaseModel): """PorousMediumBase type""" darcy_coefficient: InverseAreaType.Point = pd.Field(alias="DarcyCoefficient") forchheimer_coefficient: InverseLengthType.Point = pd.Field(alias="ForchheimerCoefficient") volumetric_heat_source: Optional[HeatSourceType] = pd.Field(alias="VolumetricHeatSource") axes: List[Axis] = pd.Field(min_items=2, max_items=3, default=[[1, 0, 0], [0, 1, 0]]) # pylint: disable=no-self-argument @pd.root_validator def validate_axes_orthogonal(cls, values): """ check if axes are orthogonal """ axes = values.get("axes") x_axis, y_axis = array(axes[0]), array(axes[1]) max_dot = dot(x_axis, y_axis) if len(axes) == 3: z_axis = array(axes[2]) max_dot = max(max_dot, dot(x_axis, z_axis), dot(y_axis, z_axis)) if max_dot > NumericalConstants.epsilon: raise ValueError("Porous zone axes not orthogonal.") return values
[docs] class PorousMediumVolumeZone(VolumeZoneBase, PorousMediumBase): """PorousMediumVolumeZone type""" model_type: Literal["PorousMedium"] = pd.Field("PorousMedium", alias="modelType", const=True)
VolumeZoneType = Union[FluidDynamicsVolumeZone, HeatTransferVolumeZone, PorousMediumVolumeZone]