Source code for thetis.implicitexplicit

"""
Implicit-explicit time integrators

"""
from .rungekutta import *


[docs] class IMEXGeneric(TimeIntegrator, ABC): """ Generic implementation of Runge-Kutta Implicit-Explicit schemes Derived classes must define the implicit :attr:`dirk_class` and explicit :attr:`erk_class` Runge-Kutta time integrator classes. This method solves the linearized equations: All implicit terms are fed to the implicit solver, while all the other terms are fed to the explicit solver. In case of non-linear terms proper linearization must defined in the equation using the two solution functions (solution, solution_old) """ @abstractproperty def dirk_class(self): """Implicit DIRK class""" pass @abstractproperty def erk_class(self): """Explicit Runge-Kutta class""" pass @PETSc.Log.EventDecorator("thetis.IMEXGeneric.__init__") def __init__(self, equation, solution, fields, dt, options, bnd_conditions): """ :arg equation: equation to solve :type equation: :class:`Equation` object :arg solution: :class:`Function` where solution will be stored :arg fields: Dictionary of fields that are passed to the equation :type fields: dict of :class:`Function` or :class:`Constant` objects :arg float dt: time step in seconds :arg options: :class:`TimeStepperOptions` instance containing parameter values. :arg dict bnd_conditions: Dictionary of boundary conditions passed to the equation """ super(IMEXGeneric, self).__init__(equation, solution, fields, dt, options) # NOTE: The same solver parameters are currently used for both implicit and explicit schemes # implicit scheme self.dirk = self.dirk_class(equation, solution, fields, dt, options, bnd_conditions=bnd_conditions, terms_to_add=('implicit')) self.dirk.ad_block_tag += '_impl' # explicit scheme self.erk = self.erk_class(equation, solution, fields, dt, options, bnd_conditions=bnd_conditions, terms_to_add=('explicit', 'source')) self.erk.ad_block_tag += '_expl' assert self.erk.n_stages == self.dirk.n_stages self.n_stages = self.erk.n_stages # FIXME this assumes that we are limited by whatever ERK solves ... # FIXME may violate max DIRK SSP time step (if any) self.cfl_coeff = self.erk.cfl_coeff
[docs] @PETSc.Log.EventDecorator("thetis.IMEXGeneric.update_solver") def update_solver(self): """Create solver objects""" self.dirk.update_solver() self.erk.update_solver()
[docs] @PETSc.Log.EventDecorator("thetis.IMEXGeneric.initialize") def initialize(self, solution): """Assigns initial conditions to all required fields.""" self.dirk.initialize(solution) self.erk.initialize(solution)
[docs] @PETSc.Log.EventDecorator("thetis.IMEXGeneric.advance") def advance(self, t, update_forcings=None): """Advances equations for one time step.""" for i in range(self.n_stages): self.solve_stage(i, t, update_forcings) self.get_final_solution()
[docs] @PETSc.Log.EventDecorator("thetis.IMEXGeneric.solve_stage") def solve_stage(self, i_stage, t, update_forcings=None): """ Solves i-th stage """ # set solution to u_n + dt*sum(a*k_erk) self.erk.update_solution(i_stage, additive=False) # set correct reference solution in the DIRK solver self.dirk.solution_old.assign(self.erk.solution) # solve implicit tendency (this is implicit solve) self.dirk.solve_tendency(i_stage, t, update_forcings) # set solution to u_n + dt*sum(a*k_erk) + *sum(a*k_dirk) self.dirk.update_solution(i_stage) # evaluate explicit tendency self.erk.solve_tendency(i_stage, t, update_forcings)
[docs] @PETSc.Log.EventDecorator("thetis.IMEXGeneric.get_final_solution") def get_final_solution(self): """ Evaluates the final solution. """ # set solution to u_n + sum(b*k_erk) self.erk.get_final_solution(additive=False) # set correct reference solution in the DIRK solver self.dirk.solution_old.assign(self.erk.solution) # set solution to u_n + sum(b*k_erk) + sum(b*k_dirk) self.dirk.get_final_solution() # update old solution self.erk.solution_old.assign(self.dirk.solution)
[docs] def set_dt(self, dt): """ Update time step :arg float dt: time step """ self.erk.set_dt(dt) self.dirk.set_dt(dt)
[docs] class IMEXLPUM2(IMEXGeneric): """ SSP-IMEX RK scheme (20) in Higureras et al. (2014) CFL coefficient is 2.0 Higueras et al (2014). Optimized strong stability preserving IMEX Runge-Kutta methods. Journal of Computational and Applied Mathematics 272(2014) 116-140. http://dx.doi.org/10.1016/j.cam.2014.05.011 """ erk_class = ERKLPUM2 dirk_class = DIRKLPUM2
[docs] class IMEXLSPUM2(IMEXGeneric): """ SSP-IMEX RK scheme (17) in Higureras et al. (2014) CFL coefficient is 2.0 Higueras et al (2014). Optimized strong stability preserving IMEX Runge-Kutta methods. Journal of Computational and Applied Mathematics 272(2014) 116-140. http://dx.doi.org/10.1016/j.cam.2014.05.011 """ erk_class = ERKLSPUM2 dirk_class = DIRKLSPUM2
[docs] class IMEXMidpoint(IMEXGeneric): """ Implicit-explicit midpoint scheme (1, 2, 2) from Ascher et al. (1997) Ascher et al. (1997). Implicit-explicit Runge-Kutta methods for time-dependent partial differential equations. Applied Numerical Mathematics, 25:151-167. http://dx.doi.org/10.1137/0732037 """ erk_class = ERKMidpoint dirk_class = ESDIRKMidpoint
[docs] class IMEXEuler(IMEXGeneric): """ Forward-Backward Euler """ erk_class = ERKEuler dirk_class = BackwardEuler