| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Circuit.Stats.ODE
Description
Ordinary differential equation integrators as streaming Process machines.
A vector field is represented as a Diff so the same field can be reused
in differentiable contexts; the integrators themselves use only the forward
pass.
The step size is kept separate from the state so that vector-valued states
(for example EuclideanPair) can be stepped with a
scalar step size.
The scalar self-actions for Double (and Float) that this module used to
supply as orphan instances now live in NumHask.Algebra.Action.
Synopsis
- vectorField :: Additive s => (s -> s) -> Diff' s s
- eulerStep :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> h -> s
- rk4Step :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> h -> s
- euler :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> [h] -> [s]
- rk4 :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> [h] -> [s]
- eulerProcess :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> Process h s
- rk4Process :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> Process h s
Vector fields
vectorField :: Additive s => (s -> s) -> Diff' s s Source #
Lift a pure vector field into a Diff with zero pullback.
>>>let f = vectorField (\y -> y) :: Diff' Double Double>>>fst (runDiff f 2.0)2.0
Single steps
eulerStep :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> h -> s Source #
One Euler step: y' = y + h · f(y).
>>>let f = vectorField (\y -> y) :: Diff' Double Double>>>eulerStep f 1.0 0.11.1
rk4Step :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> h -> s Source #
One RK4 step.
>>>let f = vectorField (\y -> y) :: Diff' Double Double>>>rk4Step f 1.0 0.11.1051708333333334
Trajectory generators
euler :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> [h] -> [s] Source #
Integrate a Diff vector field over a list of step sizes using Euler.
The result includes the initial state as the first element.
>>>let f = vectorField (\y -> y) :: Diff' Double Double>>>euler f 1.0 [0.1, 0.1, 0.1][1.0,1.1,1.2100000000000002,1.3310000000000002]
rk4 :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> [h] -> [s] Source #
Integrate a Diff vector field over a list of step sizes using RK4.
The result includes the initial state as the first element.
Harmonic oscillator x'' = −x written as x' = v, v' = −x:
>>>let f = vectorField (\(EuclideanPair (x, v)) -> EuclideanPair (v, -x)) :: Diff' (EuclideanPair Double) (EuclideanPair Double)>>>take 5 (rk4 f (EuclideanPair (1.0, 0.0)) (replicate 40 ((pi :: Double) / 20)))[EuclideanPair {euclidPair = (1.0,0.0)},EuclideanPair {euclidPair = (0.9876883614494284,-0.1564336685819834)},EuclideanPair {euclidPair = (0.9510568066766389,-0.3090154275945243)},EuclideanPair {euclidPair = (0.8910073220447337,-0.45398824664172294)},EuclideanPair {euclidPair = (0.8090185150345391,-0.5877824515637287)}]
Process machines
eulerProcess :: (Additive s, MultiplicativeAction s, Scalar s ~ h) => Diff' s s -> s -> Process h s Source #
A Process machine that performs Euler integration.
Input is the step size h; output is the current state. The first input
is used only to kick off the machine, so its value is ignored.
rk4Process :: (Additive s, Additive (Scalar s), DivisiveAction s, Scalar s ~ h) => Diff' s s -> s -> Process h s Source #
A Process machine that performs RK4 integration.
Input is the step size h; output is the current state. The first input
is used only to kick off the machine, so its value is ignored.