Source code for thetis.sediment_eq_2d

r"""
2D advection diffusion equation for sediment transport.

This can be either conservative :math:`q=HT` or non-conservative :math:`T` sediment and allows
for a separate source and sink term. The equation reads

.. math::
    \frac{\partial S}{\partial t}
    + \nabla_h \cdot (\textbf{u} S)
    = \nabla_h \cdot (\mu_h \nabla_h S) + F_{source} - (F_{sink} S)
    :label: sediment_eq_2d

where :math:`S` is :math:`q` for conservative and :math:`T` for non-conservative,
:math:`\nabla_h` denotes horizontal gradient, :math:`\textbf{u}` are the horizontal
velocities, and :math:`\mu_h` denotes horizontal diffusivity.
"""
from .equation import Equation
from .tracer_eq_2d import HorizontalDiffusionTerm, HorizontalAdvectionTerm, ConservativeHorizontalAdvectionTerm, TracerTerm

__all__ = [
    'SedimentEquation2D',
    'SedimentTerm',
    'ConservativeSedimentAdvectionTerm',
    'SedimentAdvectionTerm',
    'SedimentErosionTerm',
    'SedimentDepositionTerm',
]


[docs] class SedimentTerm(TracerTerm): """ Generic sediment term that provides commonly used members. """ def __init__(self, function_space, depth, options, sediment_model, conservative=False): """ :arg function_space: :class:`FunctionSpace` where the solution belongs :arg depth: :class:`DepthExpression` containing depth info :arg options: :class`ModelOptions2d` containing parameters :kwarg bool conservative: whether to use conservative tracer """ super(SedimentTerm, self).__init__(0, 'sediment_2d', function_space, depth, options) self.sediment_model = sediment_model self.conservative = conservative
[docs] def get_bnd_functions(self, c_in, uv_in, elev_in, bnd_id, bnd_conditions): funcs = bnd_conditions.get(bnd_id) c_ext, uv_ext, elev_ext = super().get_bnd_functions(c_in, uv_in, elev_in, bnd_id, bnd_conditions) if 'equilibrium' in funcs: if 'value' in funcs: raise ValueError("Cannot specify both equilibrium and value for sediment bcs.") c_ext = self.sediment_model.get_equilibrium_tracer() if self.conservative: c_ext = c_ext * self.depth.get_total_depth(elev_ext) return c_ext, uv_ext, elev_ext
[docs] class ConservativeSedimentAdvectionTerm(SedimentTerm, ConservativeHorizontalAdvectionTerm): """ Advection term for sediment equation Same as :class:`ConservativeHorizontalAdvectionTerm` but allows for equilibrium boundary condition through get_bnd_conditions() inherited from :class:`SedimentTerm`.""" pass
[docs] class SedimentAdvectionTerm(SedimentTerm, HorizontalAdvectionTerm): """ Advection term for sediment equation Same as :class:`HorizontalAdvectionTerm` but allows for equilibrium boundary condition through get_bnd_conditions() inherited from :class:`SedimentTerm`.""" pass
class SedimentDiffusionTerm(SedimentTerm, HorizontalDiffusionTerm): """ Diffusion term for sediment equation Same as :class:`HorizontalDiffusionTerm` but allows for equilibrium boundary condition through get_bnd_conditions() inherited from :class:`SedimentTerm`.""" pass
[docs] class SedimentErosionTerm(SedimentTerm): """ Erosion term for sediment equation"""
[docs] def residual(self, solution, solution_old, fields, fields_old, bnd_conditions): ero = self.sediment_model.get_erosion_term() if not self.conservative: elev = fields['elev_2d'] ero = ero / self.depth.get_total_depth(elev) f = self.test * ero * self.dx return f
[docs] class SedimentDepositionTerm(SedimentTerm): """ Deposition term for sediment equation"""
[docs] def residual(self, solution, solution_old, fields, fields_old, bnd_conditions): depo = self.sediment_model.get_deposition_coefficient() elev = fields['elev_2d'] H = self.depth.get_total_depth(elev) f = -self.test * depo/H * solution * self.dx return f
[docs] class SedimentEquation2D(Equation): """ 2D sediment advection-diffusion equation: :eq:`tracer_eq_2d` or :eq:`cons_tracer_eq_2d` with sediment source and sink term """ def __init__(self, function_space, depth, options, sediment_model, conservative=False): """ :arg function_space: :class:`FunctionSpace` where the solution belongs :arg depth: :class:`DepthExpression` containing depth info :arg options: :class`ModelOptions2d` containing parameters :kwarg bool conservative: whether to use conservative tracer """ super(SedimentEquation2D, self).__init__(function_space) args = (function_space, depth, options, sediment_model, conservative) if conservative: self.add_term(ConservativeSedimentAdvectionTerm(*args), 'explicit') else: self.add_term(SedimentAdvectionTerm(*args), 'explicit') self.add_term(SedimentDiffusionTerm(*args), 'explicit') self.add_term(SedimentErosionTerm(*args), 'source') self.add_term(SedimentDepositionTerm(*args), 'implicit')