diff --git a/diffrax/solver/base.py b/diffrax/solver/base.py index 8073c600..3c8eacab 100644 --- a/diffrax/solver/base.py +++ b/diffrax/solver/base.py @@ -187,20 +187,21 @@ class AbstractWrappedSolver(AbstractSolver): class HalfSolver(AbstractWrappedSolver, AbstractAdaptiveSDESolver): - """Wraps another solver, trading cost in order to provide error estimates. (These - error estimates mean that the solver can be used with an adaptive step size - controller, like [`diffrax.PIDController`][].) + """Wraps another solver, trading cost in order to provide error estimates. (That + is, it means the solver can be used with an adaptive step size controller, + regardless of whether the underlying solver supports adaptive step sizing.) For every step of the wrapped solver, it does this by also making two half-steps, - and comparing the results. (Hence the name "HalfSolver".) + and comparing the results between the full step and the two half steps. Hence the + name "HalfSolver". As such each step costs 3 times the computational cost of the wrapped solver. !!! tip - Many solvers already provided error estimates, making `HalfSolver` primarily + Many solvers already provide error estimates, making `HalfSolver` primarily useful when using a solver that doesn't provide error estimates -- e.g. - [`diffrax.Euler`][] -- in particular this is common when solving SDEs. + [`diffrax.Euler`][] -- such solvers are most common when solving SDEs. """ @property diff --git a/diffrax/solver/dopri5.py b/diffrax/solver/dopri5.py index a30804dd..2ba617df 100644 --- a/diffrax/solver/dopri5.py +++ b/diffrax/solver/dopri5.py @@ -66,18 +66,19 @@ class Dopri5(AbstractERK): volume={6}, pages={19--26} } + ``` However (despite the name), the Butcher tableau used here is actually due to Shampine: ```bibtex - @article{ + @article{shampine1986some, author={Lawrence F. Shampine}, journal={Mathematics of Computation}, number={173}, pages={135--150}, publisher={American Mathematical Society}, - title={Some Practical Runge-Kutta Formulas}, + title={Some Practical {R}unge-{K}utta Formulas}, volume={46}, year={1986}, doi={https://doi.org/10.2307/2008219} diff --git a/diffrax/solver/leapfrog_midpoint.py b/diffrax/solver/leapfrog_midpoint.py index 8836ee91..11ce0950 100644 --- a/diffrax/solver/leapfrog_midpoint.py +++ b/diffrax/solver/leapfrog_midpoint.py @@ -27,6 +27,7 @@ class LeapfrogMidpoint(AbstractSolver): ??? cite "Reference" + ```bibtex @article{shampine2009stability, title={Stability of the leapfrog/midpoint method}, author={L. F. Shampine}, @@ -36,6 +37,7 @@ class LeapfrogMidpoint(AbstractSolver): pages={293-298}, year={2009}, } + ``` """ term_structure = jax.tree_structure(0) diff --git a/diffrax/solver/milstein.py b/diffrax/solver/milstein.py index 5d98bd6c..beecfb4b 100644 --- a/diffrax/solver/milstein.py +++ b/diffrax/solver/milstein.py @@ -31,9 +31,9 @@ class StratonovichMilstein(AbstractStratonovichSolver): !!! warning - Requires commutative noise. Note that this commutativity condition is not - checked. - """ + Requires [commutative noise](https://docs.kidger.site/diffrax/usage/how-to-choose-a-solver/#stochastic-differential-equations). + Note that this commutativity condition is not checked. + """ # noqa: E501 term_structure = jax.tree_structure((0, 0)) interpolation_cls = LocalLinearInterpolation @@ -79,9 +79,9 @@ class ItoMilstein(AbstractItoSolver): !!! warning - Requires commutative noise. Note that this commutativity condition is not - checked. - """ + Requires [commutative noise](https://docs.kidger.site/diffrax/usage/how-to-choose-a-solver/#stochastic-differential-equations). + Note that this commutativity condition is not checked. + """ # noqa: E501 term_structure = jax.tree_structure((0, 0)) interpolation_cls = LocalLinearInterpolation diff --git a/docs/api/solver.md b/docs/api/solver.md index 5e609a13..e240245c 100644 --- a/docs/api/solver.md +++ b/docs/api/solver.md @@ -1,6 +1,6 @@ # Solvers -The complete list of solvers, categorised by type, is as follows. +The complete list of solvers, categorised by type, is as follows. See also [How to choose a solver](../usage/how-to-choose-a-solver.md). !!! info "Term structure" @@ -106,8 +106,9 @@ The complete list of solvers, categorised by type, is as follows. The state of the system (the initial value of which is given by `y0` to [`diffrax.diffeqsolve`][]) must be a 2-tuple (of PyTrees). The terms (given by the value of `terms` to [`diffrax.diffeqsolve`][]) must be a 2-tuple of `AbstractTerms`. - Letting `v, w = y0` and `f, g = terms`, then `v` is updated according to - `f(t, w, args) * dt` and `w` is updated according to `g(t, v, args) * dt`. + Letting `v, w = y0` and `f, g = terms`, then `v` is updated according to `f(t, w, args) * dt` and `w` is updated according to `g(t, v, args) * dt`. + + See also this [Wikipedia page](https://en.wikipedia.org/wiki/Semi-implicit_Euler_method#Setting). ::: diffrax.SemiImplicitEuler selection: diff --git a/docs/index.md b/docs/index.md index 8a93d87e..1f62de58 100644 --- a/docs/index.md +++ b/docs/index.md @@ -49,4 +49,10 @@ If this page has caught your interest, then have a look at the [Getting Started] !!! help - Both Diffrax and its documentation are very new! If anything is unclear, or if you have any suggestions, then please open an issue or pull request on [GitHub](https://github.com/patrick-kidger/diffrax). + Both Diffrax and its documentation are very new! If: + + - anything is unclear; + - you have any suggestions; + - you need any more features; + + then please open an issue or pull request on [GitHub](https://github.com/patrick-kidger/diffrax). diff --git a/docs/usage/how-to-choose-a-solver.md b/docs/usage/how-to-choose-a-solver.md index fa5b9e3b..c0cad17e 100644 --- a/docs/usage/how-to-choose-a-solver.md +++ b/docs/usage/how-to-choose-a-solver.md @@ -38,9 +38,7 @@ See also the [Stiff ODE example](../examples/stiff_ode.ipynb). ## Stochastic differential equations -!!! info - - SDE solvers are relatively specialised depending on the type of problem. Each solver will converge to either the Itô solution or the Stratonovich solution. In addition some solvers require "commutative noise". +SDE solvers are relatively specialised depending on the type of problem. Each solver will converge to either the Itô solution or the Stratonovich solution. In addition some solvers require "commutative noise". ??? info "Commutative noise" @@ -83,7 +81,7 @@ $\mathrm{d}y(t) = μ(t, y(t))\mathrm{d}t + σ(t, y(t))\mathrm{d}w(t)$ Then the diffusion matrix $σ$ is said to be additive if $σ(t, y) = σ(t)$. That is to say if the diffusion is independent of $y$. -In this case then the Itô solution and the Stratonovich solution coincide, and mathematically speaking the choice of Itô vs Stratonovich is unimportant. (In addition, additive noise is commutative niose.) +In this case then the Itô solution and the Stratonovich solution coincide, and mathematically speaking the choice of Itô vs Stratonovich is unimportant. - The cheapest (but least accurate) solver is [`diffrax.Euler`][]. - Otherwise [`diffrax.Heun`][] is a good choice. It gets first-order strong convergence and second-order weak convergence. @@ -100,7 +98,7 @@ If the control is differentiable (e.g. an interpolation of discrete data) and is vector_field = ... control = ... term = ControlTerm(vector_field, control) -term.to_ode() +term = term.to_ode() ``` Then use any of the ODE solvers as discussed above.