Source code for irksome.stepper

from .dirk_stepper import DIRKTimeStepper
from .explicit_stepper import ExplicitTimeStepper
from .imex import RadauIIAIMEXMethod, DIRKIMEXMethod
from .stage_derivative import StageDerivativeTimeStepper, AdaptiveTimeStepper
from .stage_value import StageValueTimeStepper
from .tools import AI


[docs] def TimeStepper(F, butcher_tableau, t, dt, u0, **kwargs): """Helper function to dispatch between various back-end classes for doing time stepping. Returns an instance of the appropriate class. :arg F: A :class:`ufl.Form` instance describing the semi-discrete problem F(t, u; v) == 0, where `u` is the unknown :class:`firedrake.Function and `v` iss the :class:firedrake.TestFunction`. :arg butcher_tableau: A :class:`ButcherTableau` instance giving the Runge-Kutta method to be used for time marching. :arg t: a :class:`Function` on the Real space over the same mesh as `u0`. This serves as a variable referring to the current time. :arg dt: a :class:`Function` on the Real space over the same mesh as `u0`. This serves as a variable referring to the current time step. The user may adjust this value between time steps. :arg u0: A :class:`firedrake.Function` containing the current state of the problem to be solved. :arg bcs: An iterable of :class:`firedrake.DirichletBC` or :class: `firedrake.EquationBC` containing the strongly-enforced boundary conditions. Irksome will manipulate these to obtain boundary conditions for each stage of the RK method. :arg nullspace: A list of tuples of the form (index, VSB) where index is an index into the function space associated with `u` and VSB is a :class: `firedrake.VectorSpaceBasis` instance to be passed to a `firedrake.MixedVectorSpaceBasis` over the larger space associated with the Runge-Kutta method :arg stage_type: Whether to formulate in terms of a stage derivatives or stage values. Support for `firedrake.EquationBC` in `bcs` is limited to the stage derivative formulation. :arg splitting: An callable used to factor the Butcher matrix :arg bc_type: For stage derivative formulation, how to manipulate the strongly-enforced boundary conditions. Support for `firedrake.EquationBC` in `bcs` is limited to DAE style BCs. :arg solver_parameters: A :class:`dict` of solver parameters that will be used in solving the algebraic problem associated with each time step. :arg update_solver_parameters: A :class:`dict` of parameters for inverting the mass matrix at each step (only used if stage_type is "value") :arg adaptive_parameters: A :class:`dict` of parameters for use with adaptive time stepping (only used if stage_type is "deriv") """ valid_kwargs_per_stage_type = { "deriv": ["stage_type", "bcs", "nullspace", "solver_parameters", "appctx", "bc_type", "splitting", "adaptive_parameters"], "value": ["stage_type", "basis_type", "bcs", "nullspace", "solver_parameters", "update_solver_parameters", "appctx", "splitting", "bounds"], "dirk": ["stage_type", "bcs", "nullspace", "solver_parameters", "appctx"], "explicit": ["stage_type", "bcs", "solver_parameters", "appctx"], "imex": ["Fexp", "stage_type", "bcs", "nullspace", "it_solver_parameters", "prop_solver_parameters", "splitting", "appctx", "num_its_initial", "num_its_per_step"], "dirkimex": ["Fexp", "stage_type", "bcs", "nullspace", "solver_parameters", "mass_parameters", "appctx"]} valid_adapt_parameters = ["tol", "dtmin", "dtmax", "KI", "KP", "max_reject", "onscale_factor", "safety_factor", "gamma0_params"] stage_type = kwargs.get("stage_type", "deriv") adapt_params = kwargs.get("adaptive_parameters") if adapt_params is not None: assert stage_type == "deriv", "Adaptive time stepping is only implemented for derivative stage type" for cur_kwarg in kwargs.keys(): if cur_kwarg not in valid_kwargs_per_stage_type: assert cur_kwarg in valid_kwargs_per_stage_type[stage_type] if stage_type == "deriv": bcs = kwargs.get("bcs") bc_type = kwargs.get("bc_type", "DAE") splitting = kwargs.get("splitting", AI) appctx = kwargs.get("appctx") solver_parameters = kwargs.get("solver_parameters") nullspace = kwargs.get("nullspace") if adapt_params is None: return StageDerivativeTimeStepper( F, butcher_tableau, t, dt, u0, bcs, appctx=appctx, solver_parameters=solver_parameters, nullspace=nullspace, bc_type=bc_type, splitting=splitting) else: for param in adapt_params: assert param in valid_adapt_parameters tol = adapt_params.get("tol", 1e-3) dtmin = adapt_params.get("dtmin", 1.e-15) dtmax = adapt_params.get("dtmax", 1.0) KI = adapt_params.get("KI", 1/15) KP = adapt_params.get("KP", 0.13) max_reject = adapt_params.get("max_reject", 10) onscale_factor = adapt_params.get("onscale_factor", 1.2) safety_factor = adapt_params.get("safety_factor", 0.9) gamma0_params = adapt_params.get("gamma0_params") return AdaptiveTimeStepper( F, butcher_tableau, t, dt, u0, bcs, appctx=appctx, solver_parameters=solver_parameters, nullspace=nullspace, bc_type=bc_type, splitting=splitting, tol=tol, dtmin=dtmin, dtmax=dtmax, KI=KI, KP=KP, max_reject=max_reject, onscale_factor=onscale_factor, safety_factor=safety_factor, gamma0_params=gamma0_params) elif stage_type == "value": bcs = kwargs.get("bcs") splitting = kwargs.get("splitting", AI) appctx = kwargs.get("appctx") solver_parameters = kwargs.get("solver_parameters") basis_type = kwargs.get("basis_type") update_solver_parameters = kwargs.get("update_solver_parameters") nullspace = kwargs.get("nullspace") return StageValueTimeStepper( F, butcher_tableau, t, dt, u0, bcs=bcs, appctx=appctx, solver_parameters=solver_parameters, splitting=splitting, basis_type=basis_type, update_solver_parameters=update_solver_parameters, nullspace=nullspace) elif stage_type == "dirk": bcs = kwargs.get("bcs") appctx = kwargs.get("appctx") solver_parameters = kwargs.get("solver_parameters") nullspace = kwargs.get("nullspace") return DIRKTimeStepper( F, butcher_tableau, t, dt, u0, bcs, solver_parameters, appctx, nullspace) elif stage_type == "explicit": bcs = kwargs.get("bcs") appctx = kwargs.get("appctx") solver_parameters = kwargs.get("solver_parameters") return ExplicitTimeStepper( F, butcher_tableau, t, dt, u0, bcs, solver_parameters, appctx) elif stage_type == "imex": Fexp = kwargs.get("Fexp") assert Fexp is not None, "Calling an IMEX scheme with no explicit form. Did you really mean to do this?" bcs = kwargs.get("bcs") appctx = kwargs.get("appctx") splitting = kwargs.get("splitting", AI) it_solver_parameters = kwargs.get("it_solver_parameters") prop_solver_parameters = kwargs.get("prop_solver_parameters") nullspace = kwargs.get("nullspace") num_its_initial = kwargs.get("num_its_initial", 0) num_its_per_step = kwargs.get("num_its_per_step", 0) return RadauIIAIMEXMethod( F, Fexp, butcher_tableau, t, dt, u0, bcs, it_solver_parameters, prop_solver_parameters, splitting, appctx, nullspace, num_its_initial, num_its_per_step) elif stage_type == "dirkimex": Fexp = kwargs.get("Fexp") assert Fexp is not None, "Calling an IMEX scheme with no explicit form. Did you really mean to do this?" bcs = kwargs.get("bcs") appctx = kwargs.get("appctx") solver_parameters = kwargs.get("solver_parameters") mass_parameters = kwargs.get("mass_parameters") nullspace = kwargs.get("nullspace") return DIRKIMEXMethod( F, Fexp, butcher_tableau, t, dt, u0, bcs, solver_parameters, mass_parameters, appctx, nullspace)