Source code for fridom.nonhydro.modules.forcings.gaussian_wave_maker
"""A gaussian wave maker module."""
from __future__ import annotations
import fridom.framework as fr
import fridom.nonhydro as nh
[docs]
@fr.utils.jaxify
class GaussianWaveMaker(fr.modules.Module):
r"""
A Gaussian wave maker that forces the u-component of the velocity field.
Description
-----------
Creates a gaussian source term of the form:
.. math::
M(\boldsymbol{x}) = \prod_{i=1}^{3} \exp\left(-\frac{(x_i - p_i)^2}{w_i^2}\right)
.. math::
S(\boldsymbol{x}, t) = A \sin(2\pi f t) M(\boldsymbol{x})
where :math:`A` is the amplitude, :math:`x_i` is the x coordinate,
:math:`p_i` is the position, :math:`w_i` is the width and :math:`f`
is the frequency of the wave maker. The source term is added to the
u-component of the velocity field:
.. math::
\partial_t u \leftarrow \partial_t u + S(\boldsymbol{x}, t)
Parameters
----------
position : tuple[float | None]
The position of the wave maker (center of the gaussian).
The wave maker is constant over axis with `position[axis]=None`.
width : tuple[float | None]
The width of the wave maker (width of the gaussian).
The wave maker is constant over axis with `width[axis]=None`.
frequency : float
The frequency of the wave maker.
amplitude : float
The amplitude of the wave maker.
variable : str
The variable to force. (Default: "u")
"""
name = "Gaussian Wave Maker"
[docs]
def __init__(self,
position: tuple[float | None],
width: tuple[float | None],
frequency: float,
amplitude: float,
variable: str = "u") -> None:
super().__init__()
self.position = position
self.width = width
self.frequency = frequency
self.amplitude = amplitude
self.variable = variable
def _on_setup(self) -> None:
ncp = fr.config.ncp
# Construct mask
mask = ncp.ones_like(self.grid.X[0])
for x, pos, width in zip(self.grid.X, self.position, self.width):
if pos is not None and width is not None:
mask *= ncp.exp(-(x - pos)**2 / width**2)
mask *= self.amplitude
self.mask = mask
[docs]
@fr.utils.jaxjit
def add_source_term(self, dz: nh.State, time: float) -> nh.State:
"""Add the source term to the u-component of the velocity field."""
ncp = fr.config.ncp
tendency = self.mask * ncp.sin(2 * ncp.pi * self.frequency * time)
dz.fields[self.variable] += tendency
return dz
[docs]
@fr.modules.module_method
def update(self, mz: nh.ModelState) -> nh.ModelState: # noqa: D102
mz.dz = self.add_source_term(mz.dz, mz.clock.time)
return mz
@property
def info(self) -> dict: # noqa: D102
res = super().info
res["position"] = self.position
res["width"] = self.width
res["frequency"] = self.frequency
res["amplitude"] = self.amplitude
return res