Source code for flow360.component.flow360_params.time_stepping

"""
Time stepping parameters
"""

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

from abc import ABCMeta
from typing import Dict, Optional, Union

import pydantic as pd
from typing_extensions import Literal

from ..types import PositiveFloat, PositiveInt
from .params_base import DeprecatedAlias, Flow360BaseModel
from .unit_system import TimeType


def _apply_default_to_none(original, default):
    for field_name in original.__fields__:
        value = getattr(original, field_name)
        if value is None:
            setattr(original, field_name, default.dict()[field_name])
    return original


[docs] class RampCFL(Flow360BaseModel): """ Ramp CFL for time stepping component """ type: Literal["ramp"] = pd.Field("ramp", const=True) initial: Optional[PositiveFloat] = pd.Field() final: Optional[PositiveFloat] = pd.Field() ramp_steps: Optional[int] = pd.Field(alias="rampSteps")
[docs] @classmethod def default_unsteady(cls): """ returns default unsteady Ramp CFL settings """ return cls(initial=1, final=1e6, ramp_steps=30)
[docs] @classmethod def default_steady(cls): """ returns default steady Ramp CFL settings """ return cls(initial=5, final=200, ramp_steps=40)
[docs] class AdaptiveCFL(Flow360BaseModel): """ Adaptive CFL for time stepping component """ type: Literal["adaptive"] = pd.Field("adaptive", const=True) min: Optional[PositiveFloat] = pd.Field(default=0.1) max: Optional[PositiveFloat] = pd.Field() max_relative_change: Optional[PositiveFloat] = pd.Field(alias="maxRelativeChange") convergence_limiting_factor: Optional[PositiveFloat] = pd.Field( alias="convergenceLimitingFactor" )
[docs] @classmethod def default_unsteady(cls): """ returns default unsteady Adaptive CFL settings """ return cls(max=1e6, convergence_limiting_factor=1.0, max_relative_change=50)
[docs] @classmethod def default_steady(cls): """ returns default steady Adaptive CFL settings """ return cls(max=1e4, convergence_limiting_factor=0.25, max_relative_change=1)
# pylint: disable=E0213 class BaseTimeStepping(Flow360BaseModel, metaclass=ABCMeta): """ Base class for time stepping component """ max_pseudo_steps: Optional[pd.conint(gt=0, le=100000)] = pd.Field(2000, alias="maxPseudoSteps") order_of_accuracy: Optional[Literal[1, 2]] = pd.Field(2, alias="orderOfAccuracy") CFL: Optional[Union[RampCFL, AdaptiveCFL]] = pd.Field( displayed="CFL", options=["Ramp CFL", "Adaptive CFL"] ) # pylint: disable=arguments-differ def to_solver(self, params, **kwargs) -> BaseTimeStepping: """ returns configuration object in flow360 units system """ return super().to_solver(params, **kwargs) # pylint: disable=missing-class-docstring,too-few-public-methods class Config(Flow360BaseModel.Config): deprecated_aliases = [DeprecatedAlias(name="physical_steps", deprecated="maxPhysicalSteps")] exclude_on_flow360_export = ["model_type"]
[docs] class SteadyTimeStepping(BaseTimeStepping): """ Steady time stepping component """ model_type: Literal["Steady"] = pd.Field("Steady", alias="modelType", const=True) physical_steps: Literal[1] = pd.Field(1, alias="physicalSteps", const=True) time_step_size: Literal["inf"] = pd.Field("inf", alias="timeStepSize", const=True) CFL: Optional[Union[RampCFL, AdaptiveCFL]] = pd.Field( displayed="CFL", options=["Ramp CFL", "Adaptive CFL"], default=AdaptiveCFL.default_steady(), ) @pd.root_validator(pre=True) def set_default_cfl(cls, values): """ Populate CFL's None fields with default """ if "CFL" not in values: return values # will be handeled by default cfl_input = values["CFL"] if isinstance(cfl_input, AdaptiveCFL): cfl_input = _apply_default_to_none(cfl_input, AdaptiveCFL.default_steady()) elif isinstance(cfl_input, RampCFL): cfl_input = _apply_default_to_none(cfl_input, RampCFL.default_steady()) return values
[docs] class UnsteadyTimeStepping(BaseTimeStepping): """ Unsteady time stepping component """ model_type: Literal["Unsteady"] = pd.Field("Unsteady", alias="modelType", const=True) physical_steps: PositiveInt = pd.Field(alias="physicalSteps") time_step_size: TimeType.Positive = pd.Field(alias="timeStepSize") CFL: Optional[Union[RampCFL, AdaptiveCFL]] = pd.Field( displayed="CFL", options=["Ramp CFL", "Adaptive CFL"], default=AdaptiveCFL.default_unsteady(), ) @pd.root_validator(pre=True) def set_default_cfl(cls, values): """ Populate CFL's None fields with default """ if "CFL" not in values: return values # will be handeled by default cfl_input = values["CFL"] if isinstance(cfl_input, AdaptiveCFL): cfl_input = _apply_default_to_none(cfl_input, AdaptiveCFL.default_unsteady()) elif isinstance(cfl_input, RampCFL): cfl_input = _apply_default_to_none(cfl_input, RampCFL.default_unsteady()) return values
TimeStepping = Union[SteadyTimeStepping, UnsteadyTimeStepping]