Source code for fridom.nonhydro.modules.forcings.gaussian_wave_maker
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"):
super().__init__()
self.position = position
self.width = width
self.frequency = frequency
self.amplitude = amplitude
self.variable = variable
[docs]
@fr.modules.module_method
def setup(self, mset: 'nh.ModelSettings'):
super().setup(mset)
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
return
[docs]
@fr.utils.jaxjit
def add_source_term(self, dz: nh.State, time: float) -> nh.State:
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:
mz.dz = self.add_source_term(mz.dz, mz.clock.time)
return mz
@property
def info(self) -> dict:
res = super().info
res["position"] = self.position
res["width"] = self.width
res["frequency"] = self.frequency
res["amplitude"] = self.amplitude
return res