module Simulation.Aivika.Trans.Internal.Dynamics
(
Dynamics(..),
DynamicsLift(..),
invokeDynamics,
runDynamicsInStartTime,
runDynamicsInStopTime,
runDynamicsInIntegTimes,
runDynamicsInTime,
runDynamicsInTimes,
catchDynamics,
finallyDynamics,
throwDynamics,
time,
isTimeInteg,
integIteration,
integPhase,
traceDynamics) where
import Control.Exception
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Fix
import Control.Applicative
import Debug.Trace (trace)
import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
instance Monad m => Monad (Dynamics m) where
return a = Dynamics $ \p -> return a
(Dynamics m) >>= k =
Dynamics $ \p ->
do a <- m p
let Dynamics m' = k a
m' p
runDynamicsInStartTime :: Dynamics m a -> Simulation m a
runDynamicsInStartTime (Dynamics m) =
Simulation $ m . integStartPoint
runDynamicsInStopTime :: Dynamics m a -> Simulation m a
runDynamicsInStopTime (Dynamics m) =
Simulation $ m . integStopPoint
runDynamicsInIntegTimes :: Monad m => Dynamics m a -> Simulation m [m a]
runDynamicsInIntegTimes (Dynamics m) =
Simulation $ return . map m . integPoints
runDynamicsInTime :: Double -> Dynamics m a -> Simulation m a
runDynamicsInTime t (Dynamics m) =
Simulation $ \r -> m $ pointAt r t
runDynamicsInTimes :: Monad m => [Double] -> Dynamics m a -> Simulation m [m a]
runDynamicsInTimes ts (Dynamics m) =
Simulation $ \r -> return $ map (m . pointAt r) ts
instance Functor m => Functor (Dynamics m) where
fmap f (Dynamics x) = Dynamics $ \p -> fmap f $ x p
instance Applicative m => Applicative (Dynamics m) where
pure = Dynamics . const . pure
(Dynamics x) <*> (Dynamics y) = Dynamics $ \p -> x p <*> y p
liftMD :: Monad m => (a -> b) -> Dynamics m a -> Dynamics m b
liftMD f (Dynamics x) =
Dynamics $ \p -> do { a <- x p; return $ f a }
liftM2D :: Monad m => (a -> b -> c) -> Dynamics m a -> Dynamics m b -> Dynamics m c
liftM2D f (Dynamics x) (Dynamics y) =
Dynamics $ \p -> do { a <- x p; b <- y p; return $ f a b }
instance (Num a, Monad m) => Num (Dynamics m a) where
x + y = liftM2D (+) x y
x y = liftM2D () x y
x * y = liftM2D (*) x y
negate = liftMD negate
abs = liftMD abs
signum = liftMD signum
fromInteger i = return $ fromInteger i
instance (Fractional a, Monad m) => Fractional (Dynamics m a) where
x / y = liftM2D (/) x y
recip = liftMD recip
fromRational t = return $ fromRational t
instance (Floating a, Monad m) => Floating (Dynamics m a) where
pi = return pi
exp = liftMD exp
log = liftMD log
sqrt = liftMD sqrt
x ** y = liftM2D (**) x y
sin = liftMD sin
cos = liftMD cos
tan = liftMD tan
asin = liftMD asin
acos = liftMD acos
atan = liftMD atan
sinh = liftMD sinh
cosh = liftMD cosh
tanh = liftMD tanh
asinh = liftMD asinh
acosh = liftMD acosh
atanh = liftMD atanh
instance MonadTrans Dynamics where
lift = Dynamics . const
instance MonadIO m => MonadIO (Dynamics m) where
liftIO = Dynamics . const . liftIO
instance Monad m => MonadCompTrans Dynamics m where
liftComp = Dynamics . const
class DynamicsLift t m where
liftDynamics :: Dynamics m a -> t m a
instance Monad m => DynamicsLift Dynamics m where
liftDynamics = id
instance Monad m => SimulationLift Dynamics m where
liftSimulation (Simulation x) = Dynamics $ x . pointRun
instance Monad m => ParameterLift Dynamics m where
liftParameter (Parameter x) = Dynamics $ x . pointRun
catchDynamics :: (MonadException m, Exception e) => Dynamics m a -> (e -> Dynamics m a) -> Dynamics m a
catchDynamics (Dynamics m) h =
Dynamics $ \p ->
catchComp (m p) $ \e ->
let Dynamics m' = h e in m' p
finallyDynamics :: MonadException m => Dynamics m a -> Dynamics m b -> Dynamics m a
finallyDynamics (Dynamics m) (Dynamics m') =
Dynamics $ \p ->
finallyComp (m p) (m' p)
throwDynamics :: (MonadException m, Exception e) => e -> Dynamics m a
throwDynamics e =
Dynamics $ \p ->
throwComp e
instance MonadFix m => MonadFix (Dynamics m) where
mfix f =
Dynamics $ \p ->
do { rec { a <- invokeDynamics p (f a) }; return a }
time :: Monad m => Dynamics m Double
time = Dynamics $ return . pointTime
isTimeInteg :: Monad m => Dynamics m Bool
isTimeInteg = Dynamics $ \p -> return $ pointPhase p >= 0
integIteration :: Monad m => Dynamics m Int
integIteration = Dynamics $ return . pointIteration
integPhase :: Monad m => Dynamics m Int
integPhase = Dynamics $ return . pointPhase
traceDynamics :: Monad m => String -> Dynamics m a -> Dynamics m a
traceDynamics message m =
Dynamics $ \p ->
trace ("t = " ++ show (pointTime p) ++ ": " ++ message) $
invokeDynamics p m