module MRIStep:sig..end
MRIStep Time-Stepping Module for two-rate initial value problems.
This module solves problems of the form $\dot{y} = f_s(t, y) + f_f(t, y)$, $y(t_0) = y_0$.
Its interface is structured as follows.
include Arkode.Common
type('d, 'k)session =('d, 'k, Arkode.mristep) session
A session with the MRIStep time-stepping solver.
An example session with MRIStep (arkode_mri_skel.ml):
open Sundials
module MRIStep = Arkode.MRIStep
module ARKStep = Arkode.ARKStep
(* 1. Define right-hand-side functions. *)
let fslow _t y yd = yd.{0} <- y.{1};
yd.{1} <- 0.0
let ffast _t _y yd = yd.{0} <- 0.0;
yd.{1} <- -9.81
(* 2. Optionally define a root function. *)
let g _t y gout = gout.{0} <- 1.0 -. y.{0}
(* 3. Set vector of initial values.
The length of this vector determines the problem size. *)
let y = RealArray.of_list [ 10.0; 0.0 ]
let ynv = Nvector_serial.wrap y
(* 4. Create an ARKStep solver for the fast (inner) integration *)
let sf = ARKStep.(init (explicit ffast) default_tolerances 0.0 ynv)
(* 5. Create and initialize a solver session. *)
let slowstep = 0.01
let s = MRIStep.(init (explicit fslow)
default_tolerances
InnerStepper.(from_arkstep sf)
~roots:(1, g) ~slowstep 0.0 ynv);;
(* 6. Set optional inputs, e.g.,
call [set_*] functions to change solver parameters. *)
MRIStep.set_stop_time s 10.0;;
MRIStep.set_all_root_directions s RootDirs.Increasing;;
(* 7. Advance the solution in time,
by repeatedly calling [evolve_normal] or [evolve_one_step]. *)
let rec go (t, r) =
Printf.printf "% .10e\t% .10e\t% .10e\n" t y.{0} y.{1};
match r with
| MRIStep.Success -> go (MRIStep.evolve_normal s (t +. 0.5) ynv)
| MRIStep.RootsFound -> begin
y.{1} <- -0.8 *. y.{1};
MRIStep.reinit s t ynv;
ARKStep.reinit sf t ynv;
go (t, MRIStep.Success)
end
| MRIStep.StopTimeReached -> ();;
Printf.printf "time\ty\ty'\n";;
go (0.0, MRIStep.Success);;
(* 8. Get optional outputs,
call the [get_*] functions to examine solver statistics. *)
let ns = MRIStep.get_num_steps s
type[> Nvector_serial.kind ]serial_session =(Nvector_serial.data, [> Nvector_serial.kind ] as 'a) session
Alias for sessions based on serial nvectors.
type ('data, 'kind) linear_solver
Linear solvers used by MRIStep.
type[> Nvector_serial.kind ]serial_linear_solver =(Nvector_serial.data, [> Nvector_serial.kind ] as 'a)
linear_solver
Alias for linear solvers that are restricted to serial nvectors.
module Dls:sig..end
Direct Linear Solvers operating on dense, banded, and sparse matrices.
module Spils:sig..end
Scaled Preconditioned Iterative Linear Solvers.
val matrix_embedded_solver : (unit, 'data, 'kind, [> `MatE ]) Sundials.LinearSolver.t ->
('data, 'kind) linear_solverCreate an MRIStep-specific linear solver from a generic matrix embedded solver.
module InnerStepper:sig..end
Integrators for problems on the MRIStep fast time-scale.
module Coupling:sig..end
Coupling coefficients between fast and slow time scales.
type ('d, 'k) problem
The form of the initial value problem.
val implicit : ?nlsolver:('data, 'kind, ('data, 'kind) session, [ `Nvec ])
Sundials_NonlinearSolver.t ->
?nlsrhsfn:'data rhsfn ->
?lsolver:('data, 'kind) linear_solver ->
?linearity:linearity -> 'data rhsfn -> ('data, 'kind) problemImplicit slow right-hand-side function only. The fields are as follows.
nlsolver, the nonlinear solver used for implicit stage solves,nlsrhsfn, alternative implicit right-hand-side function to use in
nonlinear system function evaluations,lsolver, used by nlsolvers based on Newton interation.linearity, specifies whether the implicit slow right-hand side
function $f^S(t, y)$ is linear in $y$ or
nonlinear (the default), andf_s, the implicit, slow portion of the right-hand-side function,If an nlsolver is not specified, then the
Newton module is used by default.
The alternative implicit right-hand-side function for nonlinear system function evaluations is only supported for Sundials >= 5.8.0.
val explicit : 'data rhsfn -> ('data, 'kind) problemExplicit slow right-hand-side function only. The argument specifies the explicit portion of the slow right-hand-side problem.
val imex : ?nlsolver:('data, 'kind, ('data, 'kind) session, [ `Nvec ])
Sundials_NonlinearSolver.t ->
?nlsrhsfn:'data rhsfn ->
?lsolver:('data, 'kind) linear_solver ->
?linearity:linearity ->
fsi:'data rhsfn ->
fse:'data rhsfn -> unit -> ('data, 'kind) problemSlow problem with both implicit and explicit parts. The arguments
are as described under Arkode.MRIStep.implicit and Arkode.MRIStep.explicit.
val init : ?context:Sundials.Context.t ->
('data, 'kind) problem ->
('data, 'kind) tolerance ->
('data, 'kind) InnerStepper.t ->
?coupling:Coupling.t ->
slowstep:float ->
?roots:int * 'data rootsfn ->
float -> ('data, 'kind) Nvector.t -> ('data, 'kind) sessionCreates and initializes a session with the solver. The call
init problem tol inner ~slowstep:h_s ~roots:(nroots, g) t0 y0has as arguments:
problem, specifies the problem to solve (see Arkode.MRIStep.problem),tol, the slow-step integration tolerances,inner, an inner stepper to use for the fast integrator,~coupling, use a customized set of slow-to-fast coupling
coefficients,h_s, the slow step size,nroots, the number of root functions,g, the root function ((nroots, g) defaults to
Arkode.Common.no_roots),t0, the initial value of the independent variable, andy0, a vector of initial values that also determines the number
of equations.This function does everything necessary to initialize a session, i.e.,
it makes the calls referenced below. The Arkode.MRIStep.evolve_normal and
Arkode.MRIStep.evolve_one_step functions may be called directly.
If the inner (fast) stepper uses a fixed step size h_f that does not
evenly divide the time interval between the stages of the outer (slow)
method, then the actual value used for the fast steps will
be slightly smaller than h_f to ensure that
$(c_i^s - c_{i-1}^s)h_s/h_f$ is an integer value. Specifically,
the fast step for the ith slow stage will be
$h = \frac{(c_i^s - c_{i-1}^s)h_s}
{\left\lceil (c_i^s - c_{i-1}^s)h_s/h_f \right\rceil}$ .
If fixed step sizes and a stop time are used, then the fixed step size
will be used for all steps except the final step, which may be shorter.
To resume use of the previous fixed step size, another call to
Arkode.MRIStep.set_fixed_step is required before calling either Arkode.MRIStep.evolve_normal or
Arkode.MRIStep.evolve_one_step.
Neither Root finding nor non-identity mass matrices are supported in the inner session.
For Sundials < 5.4.0, the tolerance must be Arkode.Common.default_tolerances
and the coupling, nlsolver, lsolver, and linearity arguments are
not available.
By default, the session is created using the context returned by
Sundials.Context.default, but this can be overridden by passing
an optional context argument.
val evolve_normal : ('d, 'k) session ->
float -> ('d, 'k) Nvector.t -> float * solver_resultIntegrates an ODE system over an interval. The call
tret, r = evolve_normal s tout yout has as arguments
s, a solver session,tout, the next time at which a solution is desired, and,yout, a vector to store the computed solution.It returns tret, the time reached by the solver, which will be equal to
tout if no errors occur, and, r, a Arkode.Common.solver_result.
IllInput Missing or illegal solver inputs.TooMuchWork The requested time could not be reached in mxstep internal steps.VectorOpErr A vector operation error occurredInnerStepFail The inner stepper had an unrecoverable errorval evolve_one_step : ('d, 'k) session ->
float -> ('d, 'k) Nvector.t -> float * solver_resultLike Arkode.MRIStep.evolve_normal but returns after one internal solver step.
val get_dky : ('d, 'k) session -> ('d, 'k) Nvector.t -> float -> int -> unitReturns the interpolated solution or derivatives.
get_dky s dky t k computes the kth derivative of the function
at time t, i.e.,
$\frac{d^\mathtt{k}}{\mathit{dt}^\mathtt{k}}y(\mathtt{t})$,
and stores it in dky. The arguments must satisfy
$t_n - h_n \leq \mathtt{t} \leq t_n$—where $t_n$
denotes Arkode.MRIStep.get_current_time and $h_n$ denotes Arkode.MRIStep.get_last_step,—
and $0 \leq \mathtt{k} \leq 3$.
This function may only be called after a successful return from either
Arkode.MRIStep.evolve_normal or Arkode.MRIStep.evolve_one_step.
BadT t is not in the interval $[t_n - h_n, t_n]$.BadK k is not in the range {0, 1, ..., dord}.val reinit : ('d, 'k) session ->
?problem:('d, 'k) problem ->
?roots:int * 'd rootsfn -> float -> ('d, 'k) Nvector.t -> unitReinitializes the solver with new parameters and state values. The
values of the independent variable, i.e., the simulation time, and the
state variables must be given. If given, problem specifies new
callback functions and solvers, and roots specifies a new root finding
function. The new problem must have the same size as the previous one.
The number of Runge Kutta stages for both the slow and
fast methods in the new problem must not be larger than that of the
previous one.
val reset : ('d, 'k) session -> float -> ('d, 'k) Nvector.tResets the state to the given independent variable value and dependent variable vector. All previously set options, internal counter values, and step-size/error histories are retained.
val resize : ('d, 'k) session ->
?resize_nvec:'d resize_fn -> ('d, 'k) Nvector.t -> float -> unitChange the number of equations and unknowns between integrator steps.
The call
resize s ~resize_nvec:rfn ynew t0
has as arguments:
s, the solver session to resize,rfn, a resize function that transforms nvectors in place-otherwise
they are simply destroyed and recloned,ynew, the newly-sized solution vector with the value $y(t_0)$, andt0, the current value of the independent variable $t_0$.val set_defaults : ('d, 'k) session -> unitResets all optional input parameters to their default values. Neither the problem-defining functions nor the root-finding functions are changed.
val set_interpolant_type : ('d, 'k) session -> interpolant_type -> unitSpecifies the interpolation module used for output value interpolation and implicit method predictors.
val set_interpolant_degree : ('d, 'k) session -> int -> unitSpecifies the degree of the polynomial interpolant used for output values and implicit method predictors.
val set_diagnostics : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unitWrite step adaptivity and solver diagnostics on the standard output (or given file).
val clear_diagnostics : ('d, 'k) session -> unitDo not write step adaptivity or solver diagnostics of a file.
val set_error_file : ('d, 'k) session -> Sundials.Logfile.t -> unitConfigure the default error handler to write messages to a file. By default it writes to Logfile.stderr.
val set_err_handler_fn : ('d, 'k) session ->
(Sundials.Util.error_details -> unit) -> unitSpecifies a custom function for handling error messages. The handler must not fail: any exceptions are trapped and discarded.
val clear_err_handler_fn : ('d, 'k) session -> unitRestores the default error handling function.
val set_fixed_step : ('d, 'k) session -> float -> unitDisables time step adaptivity and fix the step size for all internal
steps. See the notes under Arkode.MRIStep.init.
val set_max_hnil_warns : ('d, 'k) session -> int -> unitSpecifies the maximum number of messages warning that t + h = t on
the next internal step.
val set_max_num_steps : ('d, 'k) session -> int -> unitSpecifies the maximum number of steps taken in attempting to reach a given output time.
val set_stop_time : ('d, 'k) session -> float -> unitLimits the value of the independent variable t when solving.
By default no stop time is imposed.
type'dpre_inner_fn =float -> 'd array -> unit
A function to be called before each inner integration. This function may be used, for instance, to perform communications or memory transfers of forcing data supplied by the outer integrator to the inner integrator.
The first argument is the current value of the independent variable. The second is an array of outer forcing vectors.
Within the function, raising a Sundials.RecoverableFailure exception
indicates a recoverable error. Any other exception is treated as an
unrecoverable error.
val set_pre_inner_fn : ('d, 'k) session -> 'd pre_inner_fn -> unitSet the function called before each inner integration.
val clear_pre_inner_fn : ('d, 'k) session -> unitClear the function called before each inner integration.
type'dpost_inner_fn =float -> 'd -> unit
A function to be called after each inner integration. This function may be used, for instance, to perform communications or memory transfers of state data supplied by the inner integrator to the outer integrator.
The first argument is the current value of the independent variable. The second is the current value of the dependent variable vector.
Within the function, raising a Sundials.RecoverableFailure exception
indicates a recoverable error. Any other exception is treated as an
unrecoverable error.
val set_post_inner_fn : ('d, 'k) session -> 'd post_inner_fn -> unitSet the function called after each inner integration.
val clear_post_inner_fn : ('d, 'k) session -> unitClear the function called after each inner integration.
val set_postprocess_step_fn : ('d, 'k) session -> 'd postprocess_step_fn -> unitSet a post processing step function.
val clear_postprocess_step_fn : ('d, 'k) session -> unitClear the post processing step function.
type'dstage_predict_fn =float -> 'd -> unit
A function to be called after the predictor algorithm to update the predictor.
The first argument is the current value of the independent variable. The second is the predicated stage solution which may be updated directly.
All exceptions are treated as unrecoverable errors.
val set_stage_predict_fn : ('d, 'k) session -> 'd stage_predict_fn -> unitSet the function called after the predictor algorithm and before the calculation of an implicit stage solution.
If a stage prediction function is set and the current predictor method,
see Arkode.MRIStep.set_predictor_method, is
MinimumCorrectionPredictor, then the
TrivialPredictor will be used instead.
val clear_stage_predict_fn : ('d, 'k) session -> unitClear the function called after the predictor algorithm.
val set_nonlin_conv_coef : ('d, 'k) session -> float -> unitSpecifies the safety factor used in the nonlinear convergence test.
val set_nonlin_crdown : ('d, 'k) session -> float -> unitSpecifies the constant used in estimating the nonlinear solver convergence rate.
val set_nonlin_rdiv : ('d, 'k) session -> float -> unitSpecifies the nonlinear correction threshold beyond which the iteration will be declared divergent.
val set_delta_gamma_max : ('d, 'k) session -> float -> unitSpecifies a scaled step size ratio tolerance beyond which the linear solver setup routine will be signalled.
val set_lsetup_frequency : ('d, 'k) session -> int -> unitSpecifies the frequency of calls to the linear solver setup routine. Positive values specify the number of time steps between setup calls, negative values force recomputation at each Newton step, and zero values reset to the default (20).
val set_linear : ('d, 'k) session -> bool -> unitSpecifies that the implicit portion of the problem is linear. The flag
indicates whether the Jacobian of $f_I(t,y)$, or, when using an
iterative linear solver, the preconditioner is time-dependent (true)
or not (false).
val set_nonlinear : ('d, 'k) session -> unitSpecifies that the implicit portion of the problem is nonlinear.
val set_predictor_method : ('d, 'k) session -> predictor_method -> unitSpecifies the method for predicting implicit solutions.
val set_max_nonlin_iters : ('d, 'k) session -> int -> unitSpecifies the maximum number of nonlinear solver iterations permitted per RK stage at each step.
NonlinearOperationError Nonlinear solver not configuredval get_work_space : ('d, 'k) session -> int * intReturns the real and integer workspace sizes.
real_size, integer_size)val get_num_steps : ('d, 'k) session -> intReturns the cumulative number of internal steps taken by the solver.
val get_last_step : ('d, 'k) session -> floatReturns the integration step size taken on the last successful internal step.
val get_num_rhs_evals : ('d, 'k) session -> int * intThe number of calls to the (outer) right-hand-side functions.
Returns a pair nfse, nfsi = get_num_rhs_evals s, where nfse
is the number of calls to the explicit part and nfsi is the number of
calls to the implicit part.
val get_current_time : ('d, 'k) session -> floatReturns the the current internal time reached by the solver.
val get_current_state : ('d, 'k) session -> 'dReturns the current state vector. This vector provides direct access to the data within the integrator.
val get_current_coupling : ('d, 'k) session -> Coupling.tReturns the coupling table currently in use by the solver.
val write_coupling : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unitOutput the current coupling table on the standard output (or given file).
val get_nonlin_system_data : ('d, 'k) session -> 'd nonlin_system_dataGives direct access to the internal data required to construct the
current nonlinear implicit system within a nonlinear solver. This
function should be called inside the nonlinear system function.
If the nonlinear solver uses the lsetup or lsolve functions, then
the nonlinear solver system function must fill the zi and fi
vectors with, respectively, the current state and corresponding
evaluation of the right-hand-side function:
$z_i = z_{\mathit{pred}} + z_{\mathit{cor}}$ and
$F_i = f^S(t^S_{n,i}, z_i)$ where $z_{\mathit{cor}}$ is the
first argument of the nonlinear solver system function. Within a custom
linear solver, then the vectors zi and fi are only current after
an evaluation of the nonlinear system function.
val compute_state : ('d, 'k) session ->
('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> unitComputes the current stage state vector using the stored prediction and
the supplied correction from the nonlinear solver. The call
compute_state s zcor z computes $z_i(t) = z_{\mathit{pred}}
+ z_{\mathit{cor}}$ .
val get_current_gamma : ('d, 'k) session -> floatReturns the current value of $\gamma$ . This scalar appears in the internal Newton equation, either $A = I - \gamma J$ or $A = M - \gamma J$ .
val get_tol_scale_factor : ('d, 'k) session -> floatReturns a suggested factor by which the user's tolerances should be scaled when too much accuracy has been requested for some internal step.
val get_err_weights : ('d, 'k) session -> ('d, 'k) Nvector.t -> unitReturns the solution error weights at the current time.
val get_num_lin_solv_setups : ('d, 'k) session -> intReturns the number of calls made to the linear solver's setup function.
val get_num_nonlin_solv_iters : ('d, 'k) session -> intReturns the cumulative number of nonlinear (functional or Newton) iterations.
NonlinearOperationError Nonlinear solver not configuredval get_num_nonlin_solv_conv_fails : ('d, 'k) session -> intReturns the cumulative number of nonlinear convergence failures.
val get_nonlin_solv_stats : ('d, 'k) session -> int * intReturns both the numbers of nonlinear iterations performed nniters and
nonlinear convergence failures nncfails.
NonlinearOperationError Nonlinear solver not configurednniters, nncfails)val write_session : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unitSummarize the session on the standard output (or given file).
val set_root_direction : ('d, 'k) session -> Sundials.RootDirs.d array -> unitset_root_direction s dir specifies the direction of zero-crossings to
be located and returned. dir may contain one entry for each root
function.
val set_all_root_directions : ('d, 'k) session -> Sundials.RootDirs.d -> unitLike Arkode.MRIStep.set_root_direction but specifies a single direction for all root
functions.
val set_no_inactive_root_warn : ('d, 'k) session -> unitDisables issuing a warning if some root function appears to be identically zero at the beginning of the integration.
val get_num_roots : ('d, 'k) session -> intReturns the number of root functions.
val get_root_info : ('d, 'k) session -> Sundials.Roots.t -> unitFills an array showing which functions were found to have a root.
val get_num_g_evals : ('d, 'k) session -> intReturns the cumulative number of calls made to the user-supplied root function g.
val write_parameters : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unitOutputs all the solver parameters on the standard output (or given file).