API Reference
Problems
OrdinaryDiffEqOperatorSplitting.OperatorSplittingProblem — Type
OperatorSplittingProblem(f::AbstractOperatorSplitFunction, u0, tspan, p::Tuple)Functions
OrdinaryDiffEqOperatorSplitting.GenericSplitFunction — Type
GenericSplitFunction(functions::Tuple, solution_indices::Tuple)
GenericSplitFunction(functions::Tuple, solution_indices::Tuple, synchronizers::Tuple)This type of function describes a set of connected inner functions in mass-matrix form, as usually found in operator splitting procedures.
Solvers
OrdinaryDiffEqOperatorSplitting.LieTrotterGodunov — Type
LieTrotterGodunov <: AbstractOperatorSplittingAlgorithmFirst-order sequential operator splitting algorithm attributed to [1–3].
OrdinaryDiffEqOperatorSplitting.StrangMarchuk — Type
StrangMarchuk <: AbstractOperatorSplittingAlgorithmSecond-order symmetric (palindromic) operator splitting algorithm attributed to [4, 5].
For $N$ operators the scheme performs
$A_1(\Delta t/2) \to \cdots \to A_{N-1}(\Delta t/2) \to A_N(\Delta t) \to A_{N-1}(\Delta t/2) \to \cdots \to A_1(\Delta t/2)$
achieving second-order accuracy through symmetry.
OrdinaryDiffEqOperatorSplitting.PalindromicPairLieTrotterGodunov — Type
PalindromicPairLieTrotterGodunov <: AbstractOperatorSplittingAlgorithm
PalindromicPairLieTrotterGodunov(inner_algs; local_extrapolation = true)Second-order sequential operator splitting algorithm.
One step solves the palindromic pair of LieTrotterGodunov sequences
$A_1(\Delta t) \to \cdots \to A_N(\Delta t)$ and $A_N(\Delta t) \to \cdots \to A_1(\Delta t)$
from the same initial value. The leading splitting error of a Lie-Trotter sequence is $\frac{\Delta t^2}{2}\sum_{i<j} [A_j, A_i]$, and reversing the sequence flips the sign of every pairwise commutator, so the average of the pair is second order accurate for any number of operators. Half the pair difference estimates the local splitting error of a single sequence and drives the step size controller, making this the only splitting algorithm in this package that supports adaptive time stepping of the splitting itself.
Keywords
local_extrapolation: which member of the pair to propagate.true(default) advances the second-order average while controlling the step with the first-order estimate – classical local extrapolation, more accurate per step but the estimate over-reports the advanced solution's error, so the controller rejects steps it did not need to.falseadvances the first-order forward sequence $A_1 \to \cdots \to A_N$, for which the pair difference is the local error, so the controller is calibrated to what it advances.
Both the order statement and the error estimate account for the splitting error only: they presume the inner solvers resolve their sub-problems accurately relative to it (adaptive inner solvers, or fixed steps well below the splitting step). With coarse fixed-step inner solvers – say Euler() stepping at the splitting step size – the overall method degrades to the inner order and the controller is blind to that part of the error.
The difference measures the commutator of the operators. The inner solvers' error enters both orderings almost identically and therefore cancels in it, so the estimate constrains the splitting error alone. Under adaptive inner solvers that is exactly right – each operator controls its own error and this node controls the splitting – and tightening abstol/reltol drives the total error down as usual. With non-adaptive inner solvers the inner error rides along uncontrolled, and the step size is being chosen from an estimate that does not cover it.
The difference also vanishes identically wherever the operators commute, so at a state that is a fixed point of all of them the estimate is zero at any step size. On a problem where a too-large step can collapse the solution onto such a state, that degeneracy is reachable and dtmax bounds it – but a tolerance appropriate to the problem keeps it out of reach in the first place.
Per-node configuration
OrdinaryDiffEqOperatorSplitting.SplitNode — Type
SplitNodeAddress of a node in an operator splitting tree, together with the object that lives at that address.
Nodes are minted by indexing a GenericSplitFunction with integers. f[] addresses the root, f[i] its i-th operator and f[i, j] the j-th operator of that one:
node = f[2, 1] # equivalently f[2][1]
node.path # (2, 1)
node.object # the addressed sub functionThe splitting function defines the shape of the tree, so an address minted from it denotes the same position in every tree that mirrors it and can be resolved against each of them:
f[node] # the sub function
alg[node] # the inner algorithm
integrator[node] # the sub integratorAddresses are also how a TreeOption is told which node to configure.
OrdinaryDiffEqOperatorSplitting.TreeOption — Type
TreeOption(f::GenericSplitFunction, default)
TreeOption{T}(f::GenericSplitFunction, default)A value per node of an operator splitting tree, used to give individual subintegrators their own settings where init only accepts one value for all of them.
The option mirrors the shape of f and starts out holding default everywhere. Plain assignment sets a single node; broadcast assignment sets a node and everything below it:
dt = TreeOption(f, 1.0e-2)
dt[2] = 1.0e-4 # this node alone
dt[2] .= 1.0e-4 # this node and all operators below it
dt .= 1.0e-4 # every node
dt[f[2]] = 1.0e-4 # addressed by a SplitNode instead of a path
dt[2, 1] # read the value at [2, 1]Later assignments overwrite earlier ones, so a broadcast over a subtree clobbers more specific values written before it.
The element type is fixed by default; use TreeOption{Any}(f, default) for an option whose values are of mixed type, such as a step size controller.