Source code for fridom.nonhydro.model_settings

"""Model settings for the nonhydrostatic model."""
from __future__ import annotations

from functools import partial
from typing import Literal

import fridom.framework as fr
import fridom.nonhydro as nh


[docs] @partial(fr.utils.jaxify, dynamic=("f_coriolis", "N2", "dsqr", "Ro")) class ModelSettings(fr.ModelSettingsBase): """ Model settings for the 3D non-hydrostatic model. Parameters ---------- grid : Grid The grid object. """ model_name = "3D - Nonhydrostatic model"
[docs] def __init__(self, grid: fr.grid.GridBase, **kwargs: any) -> None: super().__init__(grid) # TODO(Silvano): rename variables to meaningful names # Set standard parameters self.tendencies = nh.modules.MainTendency() self._f0 = 1 # constant coriolis parameter f0 self._beta = 0 # beta term d(f)/dy self._f_coriolis = None # the coriolis parameter field self._N2 = 1 # stratification N² self._N2_field = None # stratification N² field self._dsqr = 1 # aspect ratio self._Ro = 1 # Rossby number # Finally, set attributes from keyword arguments self.set_attributes(**kwargs)
[docs] def setup_settings_parameters(self) -> None: # noqa: D102 # Coriolis parameter f_coriolis = fr.ScalarField(self, name="f", long_name="Coriolis parameter", units="1/s", position=self.grid.cell_center, topo=(True, True, True), # TODO(Silvano): don't need topo in x and z ) self._f_coriolis = f_coriolis self._update_coriolis() # Background stratification stratification = fr.ScalarField(self, name="N²", long_name="Stratification", units="1/s^2", position=self.grid.cell_center, topo=(True, True, True), # TODO(Silvano): don't need topo in x and y ) self._N2_field = stratification self.N2 = self.N2 # make sure that the advection term is scaled by the Rossby number self.tendencies.advection.scaling = self.Ro
[docs] def state_constructor(self) -> nh.State: # noqa: D102 return nh.State(self, is_spectral=self.grid.spectral_grid)
[docs] def diagnostic_state_constructor(self) -> nh.DiagnosticState: # noqa: D102 return nh.DiagnosticState(self, is_spectral=self.grid.spectral_grid)
# ================================================================ # Properties # ================================================================ @property def parameters(self) -> dict: # noqa: D102 res = super().parameters res["coriolis parameter f0"] = f"{self.f0} 1/s" res["beta term"] = f"{self.beta} 1/(m*s)" res["Stratification N²"] = f"{self.N2} 1/s^2" res["Aspect ratio dsqr"] = f"{self.dsqr}" res["Rossby number Ro"] = f"{self.Ro}" return res @property def f0(self) -> float: """The constant term of the Coriolis parameter (f=f0 + beta*y).""" return self._f0 @f0.setter def f0(self, value: float) -> None: self._f0 = value self._update_coriolis() @property def beta(self) -> float: """The beta term of the Coriolis parameter (f=f0 + beta*y).""" return self._beta @beta.setter def beta(self, value: float) -> None: self._beta = value self._update_coriolis() @property def f_coriolis(self) -> fr.ScalarField: """The Coriolis parameter (f=f0 + beta*y).""" return self._f_coriolis @f_coriolis.setter def f_coriolis(self, value: fr.ScalarField) -> None: if not isinstance(value, fr.ScalarField): msg = "The coriolis parameter must be a ScalarField." raise TypeError(msg) self._f_coriolis = value def _update_coriolis(self) -> None: if self._f_coriolis is None: # nothing to be updated if the coriolis parameter is not set return _x, y, _z = self.f_coriolis.get_mesh() self._f_coriolis.arr = self.f0 + self.beta * y @property def N2(self) -> float: """The stratification N².""" return self._N2 @N2.setter def N2(self, value: float) -> None: # update the stratification field if self._N2_field is not None: x, y, z = self._N2_field.get_mesh() self._N2_field.arr = z*0 + value self._N2 = value @property def N2_field(self) -> fr.ScalarField: """The stratification N² field.""" return self._N2_field @N2_field.setter def N2_field(self, value: fr.ScalarField) -> None: if not isinstance(value, fr.ScalarField): msg = "The stratification field must be a ScalarField." raise TypeError(msg) self._N2_field = value @property def Ro(self) -> float: """The Rossby number.""" return self._Ro @Ro.setter def Ro(self, value: float) -> None: self._Ro = value # scale the advection term self.tendencies.advection.scaling = value @property def dsqr(self) -> float: r"""The aspect ratio. :math:`\delta^2`.""" return self._dsqr @dsqr.setter def dsqr(self, value: float) -> None: self._dsqr = value