module Simulation.Aivika.Trans.Dynamics.Memo
(memoDynamics,
memo0Dynamics,
iterateDynamics,
unzipDynamics,
unzip0Dynamics) where
import Control.Monad
import Simulation.Aivika.Trans.ProtoRef
import Simulation.Aivika.Trans.ProtoArray
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Dynamics.Extra
memoDynamics :: MonadComp m => Dynamics m e -> Simulation m (Dynamics m e)
memoDynamics (Dynamics m) =
Simulation $ \r ->
do let sc = runSpecs r
s = runSession r
phs = 1 + integPhaseHiBnd sc
ns = 1 + integIterationHiBnd sc
arr <- newProtoArray_ s (ns * phs)
nref <- newProtoRef s 0
phref <- newProtoRef s 0
let r p =
do let n = pointIteration p
ph = pointPhase p
i = n * phs + ph
loop n' ph' =
if (n' > n) || ((n' == n) && (ph' > ph))
then
readProtoArray arr i
else
let p' = p { pointIteration = n', pointPhase = ph',
pointTime = basicTime sc n' ph' }
i' = n' * phs + ph'
in do a <- m p'
a `seq` writeProtoArray arr i' a
if ph' >= phs 1
then do writeProtoRef phref 0
writeProtoRef nref (n' + 1)
loop (n' + 1) 0
else do writeProtoRef phref (ph' + 1)
loop n' (ph' + 1)
n' <- readProtoRef nref
ph' <- readProtoRef phref
loop n' ph'
return $ interpolateDynamics $ Dynamics r
memo0Dynamics :: MonadComp m => Dynamics m e -> Simulation m (Dynamics m e)
memo0Dynamics (Dynamics m) =
Simulation $ \r ->
do let sc = runSpecs r
s = runSession r
ns = 1 + integIterationHiBnd sc
arr <- newProtoArray_ s ns
nref <- newProtoRef s 0
let r p =
do let sc = pointSpecs p
n = pointIteration p
loop n' =
if n' > n
then
readProtoArray arr n
else
let p' = p { pointIteration = n', pointPhase = 0,
pointTime = basicTime sc n' 0 }
in do a <- m p'
a `seq` writeProtoArray arr n' a
writeProtoRef nref (n' + 1)
loop (n' + 1)
n' <- readProtoRef nref
loop n'
return $ discreteDynamics $ Dynamics r
iterateDynamics :: MonadComp m => Dynamics m () -> Simulation m (Dynamics m ())
iterateDynamics (Dynamics m) =
Simulation $ \r ->
do let sc = runSpecs r
s = runSession r
nref <- newProtoRef s 0
let r p =
do let sc = pointSpecs p
n = pointIteration p
loop n' =
unless (n' > n) $
let p' = p { pointIteration = n', pointPhase = 0,
pointTime = basicTime sc n' 0 }
in do a <- m p'
a `seq` writeProtoRef nref (n' + 1)
loop (n' + 1)
n' <- readProtoRef nref
loop n'
return $ discreteDynamics $ Dynamics r
unzipDynamics :: MonadComp m => Dynamics m (a, b) -> Simulation m (Dynamics m a, Dynamics m b)
unzipDynamics m =
Simulation $ \r ->
do m' <- invokeSimulation r (memoDynamics m)
let ma =
Dynamics $ \p ->
do (a, _) <- invokeDynamics p m'
return a
mb =
Dynamics $ \p ->
do (_, b) <- invokeDynamics p m'
return b
return (ma, mb)
unzip0Dynamics :: MonadComp m => Dynamics m (a, b) -> Simulation m (Dynamics m a, Dynamics m b)
unzip0Dynamics m =
Simulation $ \r ->
do m' <- invokeSimulation r (memo0Dynamics m)
let ma =
Dynamics $ \p ->
do (a, _) <- invokeDynamics p m'
return a
mb =
Dynamics $ \p ->
do (_, b) <- invokeDynamics p m'
return b
return (ma, mb)