aivika-transformers 5.4 → 5.5
raw patch · 5 files changed
+183/−3 lines, 5 filesdep ~aivikaPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aivika
API changes (from Hackage documentation)
+ Simulation.Aivika.Trans.Internal.Specs: RungeKutta4b :: Method
+ Simulation.Aivika.Trans.Internal.Specs: delayPoint :: Point m -> Int -> Point m
+ Simulation.Aivika.Trans.Internal.Types: RungeKutta4b :: Method
+ Simulation.Aivika.Trans.Specs: RungeKutta4b :: Method
+ Simulation.Aivika.Trans.SystemDynamics: delayByDT :: Monad m => Dynamics m a -> Dynamics m Int -> Dynamics m a
+ Simulation.Aivika.Trans.SystemDynamics: delayIByDT :: MonadSD m => Dynamics m a -> Dynamics m Int -> Dynamics m a -> Simulation m (Dynamics m a)
Files
- CHANGELOG.md +7/−0
- Simulation/Aivika/Trans/Internal/Specs.hs +29/−1
- Simulation/Aivika/Trans/Internal/Types.hs +1/−0
- Simulation/Aivika/Trans/SystemDynamics.hs +144/−0
- aivika-transformers.cabal +2/−2
CHANGELOG.md view
@@ -1,4 +1,11 @@ +Version 5.5+-----++* Added the 4th order Runge-Kutta 3/8-method.++* Added experimental functions delayByDT and delayIByDT.+ Version 5.4 -----
Simulation/Aivika/Trans/Internal/Specs.hs view
@@ -29,7 +29,8 @@ integStopPoint, simulationStopPoint, timeGrid,- pointAt) where+ pointAt,+ delayPoint) where import Simulation.Aivika.Trans.Internal.Types @@ -69,6 +70,7 @@ Euler -> [0] RungeKutta2 -> [0, 1] RungeKutta4 -> [0, 1, 2, 3]+ RungeKutta4b -> [0, 1, 2, 3] -- | Returns the first and last integration phases. integPhaseBnds :: Specs m -> (Int, Int)@@ -77,6 +79,7 @@ Euler -> (0, 0) RungeKutta2 -> (0, 1) RungeKutta4 -> (0, 3)+ RungeKutta4b -> (0, 3) -- | Returns the first integration phase, i.e. zero. integPhaseLoBnd :: Specs m -> Int@@ -89,6 +92,7 @@ Euler -> 0 RungeKutta2 -> 1 RungeKutta4 -> 3+ RungeKutta4b -> 3 -- | Returns a simulation time for the integration point specified by -- the specs, iteration and phase.@@ -107,6 +111,10 @@ delta RungeKutta4 1 = spcDT sc / 2 delta RungeKutta4 2 = spcDT sc / 2 delta RungeKutta4 3 = spcDT sc+ delta RungeKutta4b 0 = 0+ delta RungeKutta4b 1 = spcDT sc / 3+ delta RungeKutta4b 2 = 2 * spcDT sc / 3+ delta RungeKutta4b 3 = spcDT sc -- | Return the integration time values. integTimes :: Specs m -> [Double]@@ -193,3 +201,23 @@ | i == n' = (i, t2) | otherwise = (i, t0 + (fromIntegral i) * dt) in map f [0 .. n']++-- | Delay the point by the specified positive number of iterations.+delayPoint :: Point m -> Int -> Point m+delayPoint p dn+ | dn <= 0 = error "Expected the positive number of iterations: delayPoint"+ | otherwise =+ let sc = pointSpecs p+ n = pointIteration p+ ph = pointPhase p+ in if ph < 0+ then let t' = pointTime p - fromIntegral dn * spcDT sc+ n' = fromIntegral $ floor $ (t' - spcStartTime sc) / spcDT sc+ in p { pointTime = t',+ pointIteration = n',+ pointPhase = -1 }+ else let n' = n - dn+ t' = basicTime sc n' ph+ in p { pointTime = t',+ pointIteration = n',+ pointPhase = ph }
Simulation/Aivika/Trans/Internal/Types.hs view
@@ -44,6 +44,7 @@ data Method = Euler -- ^ Euler's method | RungeKutta2 -- ^ the 2nd order Runge-Kutta method | RungeKutta4 -- ^ the 4th order Runge-Kutta method+ | RungeKutta4b -- ^ the 4th order Runge-Kutta 3/8-method deriving (Eq, Ord, Show) -- | It indentifies the simulation run.
Simulation/Aivika/Trans/SystemDynamics.hs view
@@ -49,6 +49,8 @@ -- * Discrete Functions delay, delayI,+ delayByDT,+ delayIByDT, step, pulse, pulseP,@@ -255,6 +257,82 @@ _ -> error "Incorrect phase: integRK4" +integRK4b :: Monad m+ => Dynamics m Double+ -> Dynamics m Double+ -> Dynamics m Double+ -> Point m+ -> m Double+{-# INLINABLE integRK4b #-}+integRK4b (Dynamics f) (Dynamics i) (Dynamics y) p =+ case pointPhase p of+ 0 -> case pointIteration p of+ 0 -> + i p+ n -> do+ let sc = pointSpecs p+ ty = basicTime sc (n - 1) 0+ t1 = ty+ t2 = basicTime sc (n - 1) 1+ t3 = basicTime sc (n - 1) 2+ t4 = basicTime sc (n - 1) 3+ py = p { pointTime = ty, pointIteration = n - 1, pointPhase = 0 }+ p1 = py+ p2 = p { pointTime = t2, pointIteration = n - 1, pointPhase = 1 }+ p3 = p { pointTime = t3, pointIteration = n - 1, pointPhase = 2 }+ p4 = p { pointTime = t4, pointIteration = n - 1, pointPhase = 3 }+ vy <- y py+ k1 <- f p1+ k2 <- f p2+ k3 <- f p3+ k4 <- f p4+ let !v = vy + spcDT sc / 8.0 * (k1 + 3.0 * (k2 + k3) + k4)+ return v+ 1 -> do+ let sc = pointSpecs p+ n = pointIteration p+ ty = basicTime sc n 0+ t1 = ty+ py = p { pointTime = ty, pointIteration = n, pointPhase = 0 }+ p1 = py+ vy <- y py+ k1 <- f p1+ let !v = vy + spcDT sc / 3.0 * k1+ return v+ 2 -> do+ let sc = pointSpecs p+ n = pointIteration p+ ty = basicTime sc n 0+ t1 = ty+ t2 = basicTime sc n 1+ py = p { pointTime = ty, pointIteration = n, pointPhase = 0 }+ p1 = py+ p2 = p { pointTime = t2, pointIteration = n, pointPhase = 1 }+ vy <- y py+ k1 <- f p1+ k2 <- f p2+ let !v = vy + spcDT sc * (- k1 / 3.0 + k2)+ return v+ 3 -> do+ let sc = pointSpecs p+ n = pointIteration p+ ty = basicTime sc n 0+ t1 = ty+ t2 = basicTime sc n 1+ t3 = basicTime sc n 2+ py = p { pointTime = ty, pointIteration = n, pointPhase = 0 }+ p1 = py+ p2 = p { pointTime = t2, pointIteration = n, pointPhase = 1 }+ p3 = p { pointTime = t3, pointIteration = n, pointPhase = 2 }+ vy <- y py+ k1 <- f p1+ k2 <- f p2+ k3 <- f p3+ let !v = vy + spcDT sc * (k1 - k2 + k3)+ return v+ _ -> + error "Incorrect phase: integRK4b"+ -- | Return an integral with the specified derivative and initial value. -- -- To create a loopback, you should use the recursive do-notation.@@ -282,6 +360,7 @@ Euler -> return $ Dynamics $ integEuler diff i y RungeKutta2 -> return $ Dynamics $ integRK2 diff i y RungeKutta4 -> return $ Dynamics $ integRK4 diff i y+ RungeKutta4b -> return $ Dynamics $ integRK4b diff i y return y integEulerEither :: Monad m@@ -698,6 +777,71 @@ "The lag time cannot be negative." | otherwise = error $ "Cannot return the current data: delay. " +++ "The lag time is too small."+ y++-- | Return the delayed value by the specified positive number of+-- integration time steps used for calculating the lag time.+delayByDT :: Monad m+ => Dynamics m a+ -- ^ the value to delay+ -> Dynamics m Int+ -- ^ the delay as a multiplication of the corresponding number+ -- and the integration time step+ -> Dynamics m a+ -- ^ the delayed value+{-# INLINABLE delayByDT #-}+delayByDT (Dynamics x) (Dynamics d) = discreteDynamics $ Dynamics r + where+ r p = do + let sc = pointSpecs p+ n = pointIteration p+ a <- d p+ let p' = delayPoint p a+ n' = pointIteration p'+ y | n' < 0 = x $ p { pointTime = spcStartTime sc,+ pointIteration = 0, + pointPhase = 0 }+ | n' < n = x p'+ | n' > n = error $+ "Cannot return the future data: delayByDT. " +++ "The lag time cannot be negative."+ | otherwise = error $+ "Cannot return the current data: delayByDT. " +++ "The lag time is too small."+ y+ +-- | Return the delayed value by the specified initial value and+-- a positive number of integration time steps used for calculating+-- the lag time. It allows creating a loop back.+delayIByDT :: MonadSD m+ => Dynamics m a+ -- ^ the value to delay+ -> Dynamics m Int+ -- ^ the delay as a multiplication of the corresponding number+ -- and the integration time step+ -> Dynamics m a+ -- ^ the initial value+ -> Simulation m (Dynamics m a)+ -- ^ the delayed value+{-# INLINABLE delayIByDT #-}+delayIByDT (Dynamics x) (Dynamics d) (Dynamics i) = M.memoDynamics $ Dynamics r + where+ r p = do + let sc = pointSpecs p+ n = pointIteration p+ a <- d p+ let p' = delayPoint p a+ n' = pointIteration p'+ y | n' < 0 = i $ p { pointTime = spcStartTime sc,+ pointIteration = 0, + pointPhase = 0 }+ | n' < n = x p'+ | n' > n = error $+ "Cannot return the future data: delayIByDT. " +++ "The lag time cannot be negative."+ | otherwise = error $+ "Cannot return the current data: delayIByDT. " ++ "The lag time is too small." y
aivika-transformers.cabal view
@@ -1,5 +1,5 @@ name: aivika-transformers-version: 5.4+version: 5.5 synopsis: Transformers for the Aivika simulation library description: This package is a generalization of the aivika [1] simulation library@@ -175,7 +175,7 @@ random >= 1.0.0.3, mwc-random >= 0.13.0.0, vector >= 0.10.0.1,- aivika >= 5.4+ aivika >= 5.5 other-extensions: FlexibleContexts, FlexibleInstances,