summaryrefslogtreecommitdiff
path: root/lib/Numeric/GSL/ODE.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/GSL/ODE.hs')
-rw-r--r--lib/Numeric/GSL/ODE.hs107
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/Numeric/GSL/ODE.hs b/lib/Numeric/GSL/ODE.hs
new file mode 100644
index 0000000..3450b91
--- /dev/null
+++ b/lib/Numeric/GSL/ODE.hs
@@ -0,0 +1,107 @@
1{- |
2Module : Numeric.GSL.ODE
3Copyright : (c) Alberto Ruiz 2010
4License : GPL
5
6Maintainer : Alberto Ruiz (aruiz at um dot es)
7Stability : provisional
8Portability : uses ffi
9
10Solution of ordinary differential equation (ODE) initial value problems.
11
12<http://www.gnu.org/software/gsl/manual/html_node/Ordinary-Differential-Equations.html>
13
14A simple example:
15
16@import Numeric.GSL
17import Numeric.LinearAlgebra
18import Graphics.Plot
19
20xdot t [x,v] = [v, -0.95*x - 0.1*v]
21
22ts = linspace 100 (0,20)
23
24sol = odeSolve xdot [10,0] ts
25
26main = mplot (ts : toColumns sol)@
27
28-}
29-----------------------------------------------------------------------------
30
31module Numeric.GSL.ODE (
32 odeSolve, odeSolveV, ODEMethod(..)
33) where
34
35import Data.Packed.Internal
36import Data.Packed.Matrix
37import Foreign
38import Foreign.C.Types(CInt)
39import Numeric.GSL.Internal
40
41-------------------------------------------------------------------------
42
43-- | Stepping functions
44data ODEMethod = RK2 -- ^ Embedded Runge-Kutta (2, 3) method.
45 | RK4 -- ^ 4th order (classical) Runge-Kutta. The error estimate is obtained by halving the step-size. For more efficient estimate of the error, use 'RKf45'.
46 | RKf45 -- ^ Embedded Runge-Kutta-Fehlberg (4, 5) method. This method is a good general-purpose integrator.
47 | RKck -- ^ Embedded Runge-Kutta Cash-Karp (4, 5) method.
48 | RK8pd -- ^ Embedded Runge-Kutta Prince-Dormand (8,9) method.
49 | RK2imp -- ^ Implicit 2nd order Runge-Kutta at Gaussian points.
50 | RK4imp -- ^ Implicit 4th order Runge-Kutta at Gaussian points.
51 | BSimp -- ^ Implicit Bulirsch-Stoer method of Bader and Deuflhard. This algorithm requires the Jacobian.
52 | Gear1 -- ^ M=1 implicit Gear method.
53 | Gear2 -- ^ M=2 implicit Gear method.
54 deriving (Enum,Eq,Show,Bounded)
55
56-- | A version of 'odeSolveV' with reasonable default parameters and system of equations defined using lists.
57odeSolve
58 :: (Double -> [Double] -> [Double]) -- ^ xdot(t,x)
59 -> [Double] -- ^ initial conditions
60 -> Vector Double -- ^ desired solution times
61 -> Matrix Double -- ^ solution
62odeSolve xdot xi ts = odeSolveV RKf45 hi epsAbs epsRel (l2v xdot) Nothing (fromList xi) ts
63 where hi = (ts@>1 - ts@>0)/100
64 epsAbs = 1.49012e-08
65 epsRel = 1.49012e-08
66 l2v f = \t -> fromList . f t . toList
67 l2m f = \t -> fromLists . f t . toList
68
69-- | Evolution of the system with adaptive step-size control.
70odeSolveV
71 :: ODEMethod
72 -> Double -- ^ initial step size
73 -> Double -- ^ absolute tolerance for the state vector
74 -> Double -- ^ relative tolerance for the state vector
75 -> (Double -> Vector Double -> Vector Double) -- ^ xdot(t,x)
76 -> Maybe (Double -> Vector Double -> Matrix Double) -- ^ optional jacobian
77 -> Vector Double -- ^ initial conditions
78 -> Vector Double -- ^ desired solution times
79 -> Matrix Double -- ^ solution
80odeSolveV method h epsAbs epsRel f mbjac xiv ts = unsafePerformIO $ do
81 let n = dim xiv
82 fp <- mkDoubleVecVecfun (\t -> aux_vTov (checkdim1 n . f t))
83 jp <- case mbjac of
84 Just jac -> mkDoubleVecMatfun (\t -> aux_vTom (checkdim2 n . jac t))
85 Nothing -> return nullFunPtr
86 sol <- withVector xiv $ \xiv' ->
87 withVector ts $ \ts' ->
88 createMIO (dim ts) n
89 (ode_c (fi (fromEnum method)) h epsAbs epsRel fp jp // xiv' // ts' )
90 "ode"
91 freeHaskellFunPtr fp
92 return sol
93
94foreign import ccall "ode"
95 ode_c :: CInt -> Double -> Double -> Double -> FunPtr (Double -> TVV) -> FunPtr (Double -> TVM) -> TVVM
96
97-------------------------------------------------------
98
99checkdim1 n v
100 | dim v == n = v
101 | otherwise = error $ "Error: "++ show n
102 ++ " components expected in the result of the function supplied to odeSolve"
103
104checkdim2 n m
105 | rows m == n && cols m == n = m
106 | otherwise = error $ "Error: "++ show n ++ "x" ++ show n
107 ++ " Jacobian expected in odeSolve"