packages feed

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 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,