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_solver
Create 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) problem
Implicit 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 nlsolver
s 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) problem
Explicit 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) problem
Slow 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) session
Creates and initializes a session with the solver. The call
init problem tol inner ~slowstep:h_s ~roots:(nroots, g) t0 y0
has 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_result
Integrates 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_result
Like Arkode.MRIStep.evolve_normal
but returns after one internal solver step.
val get_dky : ('d, 'k) session -> ('d, 'k) Nvector.t -> float -> int -> unit
Returns the interpolated solution or derivatives.
get_dky s dky t k
computes the k
th 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 -> unit
Reinitializes 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.t
Resets 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 -> unit
Change 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 -> unit
Resets 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 -> unit
Specifies the interpolation module used for output value interpolation and implicit method predictors.
val set_interpolant_degree : ('d, 'k) session -> int -> unit
Specifies the degree of the polynomial interpolant used for output values and implicit method predictors.
val set_diagnostics : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unit
Write step adaptivity and solver diagnostics on the standard output (or given file).
val clear_diagnostics : ('d, 'k) session -> unit
Do not write step adaptivity or solver diagnostics of a file.
val set_error_file : ('d, 'k) session -> Sundials.Logfile.t -> unit
Configure 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) -> unit
Specifies 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 -> unit
Restores the default error handling function.
val set_fixed_step : ('d, 'k) session -> float -> unit
Disables 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 -> unit
Specifies the maximum number of messages warning that t + h = t
on
the next internal step.
val set_max_num_steps : ('d, 'k) session -> int -> unit
Specifies the maximum number of steps taken in attempting to reach a given output time.
val set_stop_time : ('d, 'k) session -> float -> unit
Limits the value of the independent variable t
when solving.
By default no stop time is imposed.
type'd
pre_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 -> unit
Set the function called before each inner integration.
val clear_pre_inner_fn : ('d, 'k) session -> unit
Clear the function called before each inner integration.
type'd
post_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 -> unit
Set the function called after each inner integration.
val clear_post_inner_fn : ('d, 'k) session -> unit
Clear the function called after each inner integration.
val set_postprocess_step_fn : ('d, 'k) session -> 'd postprocess_step_fn -> unit
Set a post processing step function.
val clear_postprocess_step_fn : ('d, 'k) session -> unit
Clear the post processing step function.
type'd
stage_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 -> unit
Set 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 -> unit
Clear the function called after the predictor algorithm.
val set_nonlin_conv_coef : ('d, 'k) session -> float -> unit
Specifies the safety factor used in the nonlinear convergence test.
val set_nonlin_crdown : ('d, 'k) session -> float -> unit
Specifies the constant used in estimating the nonlinear solver convergence rate.
val set_nonlin_rdiv : ('d, 'k) session -> float -> unit
Specifies the nonlinear correction threshold beyond which the iteration will be declared divergent.
val set_delta_gamma_max : ('d, 'k) session -> float -> unit
Specifies a scaled step size ratio tolerance beyond which the linear solver setup routine will be signalled.
val set_lsetup_frequency : ('d, 'k) session -> int -> unit
Specifies 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 -> unit
Specifies 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 -> unit
Specifies that the implicit portion of the problem is nonlinear.
val set_predictor_method : ('d, 'k) session -> predictor_method -> unit
Specifies the method for predicting implicit solutions.
val set_max_nonlin_iters : ('d, 'k) session -> int -> unit
Specifies 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 * int
Returns the real and integer workspace sizes.
real_size
, integer_size
)val get_num_steps : ('d, 'k) session -> int
Returns the cumulative number of internal steps taken by the solver.
val get_last_step : ('d, 'k) session -> float
Returns the integration step size taken on the last successful internal step.
val get_num_rhs_evals : ('d, 'k) session -> int * int
The 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 -> float
Returns the the current internal time reached by the solver.
val get_current_state : ('d, 'k) session -> 'd
Returns the current state vector. This vector provides direct access to the data within the integrator.
val get_current_coupling : ('d, 'k) session -> Coupling.t
Returns the coupling table currently in use by the solver.
val write_coupling : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unit
Output the current coupling table on the standard output (or given file).
val get_nonlin_system_data : ('d, 'k) session -> 'd nonlin_system_data
Gives 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 -> unit
Computes 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 -> float
Returns 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 -> float
Returns 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 -> unit
Returns the solution error weights at the current time.
val get_num_lin_solv_setups : ('d, 'k) session -> int
Returns the number of calls made to the linear solver's setup function.
val get_num_nonlin_solv_iters : ('d, 'k) session -> int
Returns the cumulative number of nonlinear (functional or Newton) iterations.
NonlinearOperationError
Nonlinear solver not configuredval get_num_nonlin_solv_conv_fails : ('d, 'k) session -> int
Returns the cumulative number of nonlinear convergence failures.
val get_nonlin_solv_stats : ('d, 'k) session -> int * int
Returns 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 -> unit
Summarize the session on the standard output (or given file).
val set_root_direction : ('d, 'k) session -> Sundials.RootDirs.d array -> unit
set_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 -> unit
Like Arkode.MRIStep.set_root_direction
but specifies a single direction for all root
functions.
val set_no_inactive_root_warn : ('d, 'k) session -> unit
Disables 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 -> int
Returns the number of root functions.
val get_root_info : ('d, 'k) session -> Sundials.Roots.t -> unit
Fills an array showing which functions were found to have a root.
val get_num_g_evals : ('d, 'k) session -> int
Returns the cumulative number of calls made to the user-supplied root function g.
val write_parameters : ?logfile:Sundials.Logfile.t -> ('d, 'k) session -> unit
Outputs all the solver parameters on the standard output (or given file).