module Numeric.DDE (
integ
, integ'
, integRk4
, integHeun2
, integRk4_2D
, integHeun2_2D
, Input (..)
, InputSnapshot (..)
, HistorySnapshot (..)
, RHS (..)
, Stepper (..)
, rk4
, heun2
) where
import Data.VectorSpace.Free
import Linear ( (^/), V1 (..), V2 (..) )
import Foreign.Storable ( Storable (..) )
import System.IO.Unsafe ( unsafePerformIO )
import qualified Data.Vector.Storable as V
import qualified Data.Vector.Storable.Mutable as VM
import Numeric.DDE.Types
rk4 :: Stepper
rk4 dt (RHS rhs') xy (Hist xy_tau1, Hist xy_tau1') (u1, u1') = xy_next
where
xy_next = xy ^+^ (a ^+^ 2 *^ b ^+^ 2 *^ c ^+^ d) ^/ 6
a = dt *^ rhs' (xy, Hist xy_tau1, inp1)
b = dt *^ rhs' (xy ^+^ a ^/ 2, Hist xy_tau1_b, inp1_b)
c = dt *^ rhs' (xy ^+^ b ^/ 2, Hist xy_tau1_c, inp1_c)
d = dt *^ rhs' (xy ^+^ c, Hist xy_tau1', inp1')
xy_tau1_b = (xy_tau1 ^+^ xy_tau1') ^/ 2
xy_tau1_c = xy_tau1_b
inp1 = Inp u1
inp1_b = Inp $ (u1 + u1') / 2
inp1_c = inp1_b
inp1' = Inp u1'
heun2 :: Stepper
heun2 hStep (RHS rhs') xy (xy_tau1, xy_tau1') (u1, u1') = xy_next
where
f1 = rhs' (xy, xy_tau1, Inp u1)
xy_ = xy ^+^ hStep *^ f1
f2 = rhs' (xy_, xy_tau1', Inp u1')
xy_next = xy ^+^ (hStep *^ (f1 ^+^ f2)) ^/ 2.0
integ'
:: Storable state
=> (state -> (HistorySnapshot state, HistorySnapshot state) -> (Double, Double) -> state)
-> Int
-> Int
-> Int
-> (state, V.Vector state, Input)
-> (state, V.Vector state)
integ' iter1 len1 krecord total (xy0, hist0, Input in1) = a
where
a = unsafePerformIO $ do
v <- VM.new (len1 + total)
copyHist v hist0
xy' <- go v len1 xy0
trace <- V.unsafeFreeze v
return (xy', V.slice (len1 + total krecord) krecord trace)
copyHist v hist =
mapM_ (\i -> VM.unsafeWrite v i (hist V.! i)) [0..V.length hist 1]
go !v !i !xy
| i == len1 + total =
return xy
| otherwise = do
xy_tau1 <- VM.unsafeRead v (i len1)
xy_tau1' <- VM.unsafeRead v (i len1 + 1)
let u1 = in1 V.! (i len1)
u1' = in1 V.! (i len1 + 1)
xy' = iter1 xy (Hist xy_tau1, Hist xy_tau1') (u1, u1')
VM.unsafeWrite v i xy'
go v (i + 1) xy'
integ
:: (Functor state, Storable (state Double), VectorSpace (state Double), Num (Scalar (state Double)))
=> Stepper
-> state Double
-> V.Vector (state Double)
-> Int
-> Scalar (state Double)
-> RHS (state Double)
-> Input
-> (state Double, V.Vector (state Double))
integ stp state0 hist0 len1 dt rhs' inp@(Input in1) = r
where
totalIters = V.length in1 1
iterator = stp dt rhs'
r = integ' iterator len1 totalIters totalIters (state0, hist0, inp)
integRk4 :: Int
-> Double
-> RHS (V1 Double)
-> Input
-> (V1 Double, V.Vector (V1 Double))
integRk4 len1 = integ rk4 state0 hist0 len1
where
state0 = V1 0.0
hist0 = V.replicate len1 state0
integHeun2 :: Int
-> Double
-> RHS (V1 Double)
-> Input
-> (V1 Double, V.Vector (V1 Double))
integHeun2 len1 = integ heun2 state0 hist0 len1
where
state0 = V1 0.0
hist0 = V.replicate len1 state0
integRk4_2D :: Int
-> Double
-> RHS (V2 Double)
-> Input
-> (V2 Double, V.Vector (V2 Double))
integRk4_2D len1 = integ rk4 state0 hist0 len1
where
state0 = V2 0.0 0.0
hist0 = V.replicate len1 state0
integHeun2_2D :: Int
-> Double
-> RHS (V2 Double)
-> Input
-> (V2 Double, V.Vector (V2 Double))
integHeun2_2D len1 = integ heun2 state0 hist0 len1
where
state0 = V2 0.0 0.0
hist0 = V.replicate len1 state0