{-# LANGUAGE FlexibleContexts #-}-- |-- Module : Simulation.Aivika.Dynamics.Internal.Memo-- Copyright : Copyright (c) 2009-2011, David Sorokin <david.sorokin@gmail.com>-- License : BSD3-- Maintainer : David Sorokin <david.sorokin@gmail.com>-- Stability : experimental-- Tested with: GHC 7.0.3---- This module defines memo functions. The memoization creates such dynamic processes, -- which values are cached in the integration time points. Then these values are -- interpolated in all other time points.--moduleSimulation.Aivika.Dynamics.Internal.Memo(memo,umemo,memo0,umemo0,iterateDynamics)whereimportData.ArrayimportData.Array.IO.SafeimportData.IORefimportControl.MonadimportSimulation.Aivika.Dynamics.Internal.SimulationimportSimulation.Aivika.Dynamics.Internal.DynamicsimportSimulation.Aivika.Dynamics.Internal.InterpolatenewMemoArray_::Ixi=>(i,i)->IO(IOArrayie)newMemoArray_=newArray_newMemoUArray_::(MArrayIOUArrayeIO,Ixi)=>(i,i)->IO(IOUArrayie)newMemoUArray_=newArray_-- | Memoize and order the computation in the integration time points using -- the interpolation that knows of the Runge-Kutta method.memo::Dynamicse->Simulation(Dynamicse){-# INLINE memo #-}memo(Dynamicsm)=Simulation$\r->doletsc=runSpecsr(phl,phu)=integPhaseBndssc(nl,nu)=integIterationBndsscarr<-newMemoArray_((phl,nl),(phu,nu))nref<-newIORef0phref<-newIORef0letrp=doletsc=pointSpecspn=pointIterationpph=pointPhasepphu=integPhaseHiBndscloopn'ph'=if(n'>n)||((n'==n)&&(ph'>ph))thenreadArrayarr(ph,n)elseletp'=p{pointIteration=n',pointPhase=ph',pointTime=basicTimescn'ph'}indoa<-mp'a`seq`writeArrayarr(ph',n')aifph'>=phuthendowriteIORefphref0writeIORefnref(n'+1)loop(n'+1)0elsedowriteIORefphref(ph'+1)loopn'(ph'+1)n'<-readIORefnrefph'<-readIORefphrefloopn'ph'return$interpolate$Dynamicsr-- | This is a more efficient version the 'memo' function which uses -- an unboxed array to store the values.umemo::(MArrayIOUArrayeIO)=>Dynamicse->Simulation(Dynamicse){-# INLINE umemo #-}umemo(Dynamicsm)=Simulation$\r->doletsc=runSpecsr(phl,phu)=integPhaseBndssc(nl,nu)=integIterationBndsscarr<-newMemoUArray_((phl,nl),(phu,nu))nref<-newIORef0phref<-newIORef0letrp=doletsc=pointSpecspn=pointIterationpph=pointPhasepphu=integPhaseHiBndscloopn'ph'=if(n'>n)||((n'==n)&&(ph'>ph))thenreadArrayarr(ph,n)elseletp'=p{pointIteration=n',pointPhase=ph',pointTime=basicTimescn'ph'}indoa<-mp'a`seq`writeArrayarr(ph',n')aifph'>=phuthendowriteIORefphref0writeIORefnref(n'+1)loop(n'+1)0elsedowriteIORefphref(ph'+1)loopn'(ph'+1)n'<-readIORefnrefph'<-readIORefphrefloopn'ph'return$interpolate$Dynamicsr-- | Memoize and order the computation in the integration time points using -- the 'discrete' interpolation. It consumes less memory than the 'memo'-- function but it is not aware of the Runge-Kutta method. There is a subtle-- difference when we request for values in the intermediate time points-- that are used by this method to integrate. In general case you should -- prefer the 'memo0' function above 'memo'.memo0::Dynamicse->Simulation(Dynamicse){-# INLINE memo0 #-}memo0(Dynamicsm)=Simulation$\r->doletsc=runSpecsrbnds=integIterationBndsscarr<-newMemoArray_bndsnref<-newIORef0letrp=doletsc=pointSpecspn=pointIterationploopn'=ifn'>nthenreadArrayarrnelseletp'=p{pointIteration=n',pointPhase=0,pointTime=basicTimescn'0}indoa<-mp'a`seq`writeArrayarrn'awriteIORefnref(n'+1)loop(n'+1)n'<-readIORefnrefloopn'return$discrete$Dynamicsr-- | This is a more efficient version the 'memo0' function which uses -- an unboxed array to store the values.umemo0::(MArrayIOUArrayeIO)=>Dynamicse->Simulation(Dynamicse){-# INLINE umemo0 #-}umemo0(Dynamicsm)=Simulation$\r->doletsc=runSpecsrbnds=integIterationBndsscarr<-newMemoUArray_bndsnref<-newIORef0letrp=doletsc=pointSpecspn=pointIterationploopn'=ifn'>nthenreadArrayarrnelseletp'=p{pointIteration=n',pointPhase=0,pointTime=basicTimescn'0}indoa<-mp'a`seq`writeArrayarrn'awriteIORefnref(n'+1)loop(n'+1)n'<-readIORefnrefloopn'return$discrete$Dynamicsr-- | Iterate sequentially the dynamic process with side effects in -- the integration time points. It is equivalent to a call of the-- 'memo0' function but significantly more efficient, for the array -- is not created.iterateDynamics::Dynamics()->Simulation(Dynamics()){-# INLINE iterateDynamics #-}iterateDynamics(Dynamicsm)=Simulation$\r->doletsc=runSpecsrnref<-newIORef0letrp=doletsc=pointSpecspn=pointIterationploopn'=unless(n'>n)$letp'=p{pointIteration=n',pointPhase=0,pointTime=basicTimescn'0}indoa<-mp'a`seq`writeIORefnref(n'+1)loop(n'+1)n'<-readIORefnrefloopn'return$discrete$Dynamicsr