diff options
Diffstat (limited to 'lib/Numeric/GSL/ODE.hs')
-rw-r--r-- | lib/Numeric/GSL/ODE.hs | 107 |
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 | {- | | ||
2 | Module : Numeric.GSL.ODE | ||
3 | Copyright : (c) Alberto Ruiz 2010 | ||
4 | License : GPL | ||
5 | |||
6 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
7 | Stability : provisional | ||
8 | Portability : uses ffi | ||
9 | |||
10 | Solution of ordinary differential equation (ODE) initial value problems. | ||
11 | |||
12 | <http://www.gnu.org/software/gsl/manual/html_node/Ordinary-Differential-Equations.html> | ||
13 | |||
14 | A simple example: | ||
15 | |||
16 | @import Numeric.GSL | ||
17 | import Numeric.LinearAlgebra | ||
18 | import Graphics.Plot | ||
19 | |||
20 | xdot t [x,v] = [v, -0.95*x - 0.1*v] | ||
21 | |||
22 | ts = linspace 100 (0,20) | ||
23 | |||
24 | sol = odeSolve xdot [10,0] ts | ||
25 | |||
26 | main = mplot (ts : toColumns sol)@ | ||
27 | |||
28 | -} | ||
29 | ----------------------------------------------------------------------------- | ||
30 | |||
31 | module Numeric.GSL.ODE ( | ||
32 | odeSolve, odeSolveV, ODEMethod(..) | ||
33 | ) where | ||
34 | |||
35 | import Data.Packed.Internal | ||
36 | import Data.Packed.Matrix | ||
37 | import Foreign | ||
38 | import Foreign.C.Types(CInt) | ||
39 | import Numeric.GSL.Internal | ||
40 | |||
41 | ------------------------------------------------------------------------- | ||
42 | |||
43 | -- | Stepping functions | ||
44 | data 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. | ||
57 | odeSolve | ||
58 | :: (Double -> [Double] -> [Double]) -- ^ xdot(t,x) | ||
59 | -> [Double] -- ^ initial conditions | ||
60 | -> Vector Double -- ^ desired solution times | ||
61 | -> Matrix Double -- ^ solution | ||
62 | odeSolve 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. | ||
70 | odeSolveV | ||
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 | ||
80 | odeSolveV 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 | |||
94 | foreign import ccall "ode" | ||
95 | ode_c :: CInt -> Double -> Double -> Double -> FunPtr (Double -> TVV) -> FunPtr (Double -> TVM) -> TVVM | ||
96 | |||
97 | ------------------------------------------------------- | ||
98 | |||
99 | checkdim1 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 | |||
104 | checkdim2 n m | ||
105 | | rows m == n && cols m == n = m | ||
106 | | otherwise = error $ "Error: "++ show n ++ "x" ++ show n | ||
107 | ++ " Jacobian expected in odeSolve" | ||