Source code for fridom.shallowwater.initial_conditions.coherent_eddy

import fridom.shallowwater as sw

[docs] class CoherentEddy(sw.State): r""" Coherent barotropic eddy with Gaussian shape. Description ----------- There are two versions of the coherent eddy. In the first version, the streamfunction of the eddy is given by an gaussian function: .. math:: \psi = A \exp\left( -\frac{(x - p_x L_x)^2 + (y - p_y L_y)^2}{(\sigma L_x)^2}\right) where :math:`A` is the amplitude, :math:`(p_x, p_y)` is the relative position of the eddy, :math:`(\sigma L_x)` is the width of the eddy, and :math:`L_x, L_y` are the domain sizes in the x and y directions. The velocity field is given by: .. math:: u = \partial_y \psi, \quad v = -\partial_x \psi The second version of the coherent eddy prescribes the horizontal velocity as a gaussian function: .. math:: \zeta = A \exp\left( -\frac{(x - p_x L_x)^2 + (y - p_y L_y)^2}{(\sigma L_x)^2}\right) Then the streamfunction is computed in spectral space: .. math:: \hat{\psi} = \frac{\hat{\zeta}}{k_x^2 + k_y^2} Parameters ---------- `mset` : `ModelSettings` The model settings. `pos_x` : `float`, optional (default=0.5) The relative position of the eddy in the x-direction. `pos_y` : `float`, optional (default=0.5) The relative position of the eddy in the y-direction. `width` : `float`, optional (default=0.1) The relative width of the eddy. (relative to the domain size in the x-direction) `amplitude` : `float`, optional (default=1) The amplitude of the eddy. When the amplitude negative, the eddy rotates clockwise. Otherwise, it rotates counterclockwise. `gauss_field` : `str`, optional (default='vorticity') The field that is prescribed as a gaussian function. It can be either 'vorticity' or 'streamfunction'. """
[docs] def __init__(self, mset: sw.ModelSettings, pos_x: float = 0.5, pos_y: float = 0.5, width: float = 0.1, amplitude: float = 1, gauss_field: str = 'vorticity' ) -> None: super().__init__(mset) ncp = sw.config.ncp grid = self.grid Lx, Ly = grid.L FACE = sw.grid.AxisPosition.FACE position = sw.grid.Position((FACE, FACE)) DIRICHLET = sw.grid.BCType.DIRICHLET bc_types = (DIRICHLET, DIRICHLET) field = sw.ScalarField( mset, position=position, name="psi", bc_types=bc_types) X, Y = field.get_mesh() field.arr = amplitude * ncp.exp( -((X - pos_x * Lx)**2 + (Y - pos_y * Ly)**2) / (width*Lx)**2) if gauss_field == 'vorticity': kx, ky = grid.K k2 = kx**2 + ky**2 psi = field.fft() / k2 psi.arr = ncp.where(k2 == 0, 0, psi.arr) psi = psi.ifft() self.psi = psi elif gauss_field == 'streamfunction': psi = field else: raise ValueError(f"Unknown gauss_field: {gauss_field}") self.p.arr = psi.arr * mset.f_coriolis.arr self.u.arr = - psi.diff(axis=1).arr self.v.arr = psi.diff(axis=0).arr return