Source code for fridom.shallowwater.initial_conditions.single_wave

import fridom.shallowwater as sw


[docs] class SingleWave(sw.State): r""" An initial condition that consist of a single wave with a given wavenumber and a given mode. Description ----------- Creates a polarized wave from the eigenvectors of the linearized equations of motion. The wave is initizalized in spectral space as: .. math:: z(\boldsymbol{k}) = \boldsymbol{q}_s(\boldsymbol{k}) \delta_{\boldsymbol{k}, \boldsymbol{k}_0} \exp(i\phi) where :math:`\boldsymbol{q}_s` is the eigenvector of the mode `s` (see :py:mod:`fridom.shallowwater.grid.cartesian.eigenvectors`), and :math:`\delta_{\boldsymbol{k}, \boldsymbol{k}_0}` is the Kronecker delta function: .. math:: \delta_{\boldsymbol{k}, \boldsymbol{k}_0} = \begin{cases} 1 & \text{if } \boldsymbol{k} = 2\pi\boldsymbol{k}_0/\boldsymbol{L} \\ 0 & \text{otherwise} \end{cases} with :math:`\boldsymbol{L}` the domain size in the x, y, and z directions and :math:`\boldsymbol{k}_0` the wavenumber that is passed as an argument. The phase :math:`\phi` is also passed as an argument. Finally, the state is fourier transformed to physical space and normalized so that its L2 norm is equal to 1. Parameters ---------- `mset` : `ModelSettings` The model settings. `k` : `tuple[int]` The wavenumber in the x and y directions. A wavenumber of one means that the wave has a wavelength equal to the domain size in that direction. `s` : `int` The mode (0, 1, -1) 0 => geostrophic mode 1 => positive inertia-gravity mode -1 => negative inertia-gravity mode `phase` : `float` The phase of the wave. (default: 0) `use_discrete` : `bool` (default: True) Whether to use the discrete eigenvectors or the analytical ones. """
[docs] def __init__(self, mset: sw.ModelSettings, k: tuple[int], s: int = 1, phase: float = 0, use_discrete: bool = True) -> None: super().__init__(mset, is_spectral=False) # Shortcuts ncp = sw.config.ncp grid = mset.grid Kx, Ky = grid.K kx, ky = k Lx, Ly = grid.L pi = ncp.pi # Find index of the wavenumber in the grid (nearest neighbor) kx = 2*pi*kx/Lx; ky = 2*pi*ky/Ly is_kx = ncp.isclose(Kx, kx) is_ky = ncp.isclose(Ky, ky) k_loc = is_kx & is_ky # Construct the spectral field of the corresponding mode # all zeros except for the mode mask = ncp.where(k_loc, 1, 0) # Construct the eigenvector of the corresponding mode q = mset.grid.vec_q(s, use_discrete=use_discrete) # Construct the state z = (q * mask * ncp.exp(1j*phase)).ifft() # Normalize the state z /= z.norm_l2() # Set the state self.fields = z.fields # Calculate the frequency and period of the wave om = grid.omega((kx, ky), use_discrete=True) ts = mset.time_stepper self.omega = ts.time_discretization_effect(om) self.period = 2*pi/self.omega.real # save the wavenumbers self.kx = kx self.ky = ky return