summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2010-02-07 09:29:50 +0000
committerAlberto Ruiz <aruiz@um.es>2010-02-07 09:29:50 +0000
commitaef0333b5180ea79e539bd53194f1dfed20b7db5 (patch)
tree6ece2434ecacab194331120bd47d09ab04ae0f4f
parent634683fcfab73a0bd830fef03fb9f4603ba837b6 (diff)
added odeSolve
-rw-r--r--CHANGES6
-rw-r--r--examples/Real.hs (renamed from examples/HMatrixReal.hs)2
-rw-r--r--examples/ode.hs34
-rw-r--r--hmatrix.cabal4
-rw-r--r--lib/Data/Packed/Matrix.hs4
-rw-r--r--lib/Numeric/GSL.hs2
-rw-r--r--lib/Numeric/GSL/Internal.hs6
-rw-r--r--lib/Numeric/GSL/ODE.hs107
-rw-r--r--lib/Numeric/GSL/gsl-aux.c89
-rw-r--r--lib/Numeric/LinearAlgebra/Tests.hs9
-rw-r--r--lib/Numeric/LinearAlgebra/Tests/Properties.hs2
11 files changed, 257 insertions, 8 deletions
diff --git a/CHANGES b/CHANGES
index 8dd8066..32d34c0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,11 @@
10.8.3.0 10.8.3.0
2======= 2=======
3 3
4- Matrix arithmetic automatically replicates single row/column matrices. 4- odeSolve
5 5
6- latexFormat, dispcf for complex matrices 6- Matrix arithmetic automatically replicates matrix with single row/column
7
8- latexFormat, dispcf
7 9
80.8.2.0 100.8.2.0
9======= 11=======
diff --git a/examples/HMatrixReal.hs b/examples/Real.hs
index 0edff10..b32a961 100644
--- a/examples/HMatrixReal.hs
+++ b/examples/Real.hs
@@ -1,7 +1,7 @@
1 1
2-- Alternative interface and utilities for creation of real arrays, useful to work in interactive mode. 2-- Alternative interface and utilities for creation of real arrays, useful to work in interactive mode.
3 3
4module HMatrixReal( 4module Real(
5 module Numeric.LinearAlgebra, 5 module Numeric.LinearAlgebra,
6 (<>), (*>), (<*), (<\>), (\>), 6 (<>), (*>), (<*), (<\>), (\>),
7 vector, 7 vector,
diff --git a/examples/ode.hs b/examples/ode.hs
new file mode 100644
index 0000000..082c46c
--- /dev/null
+++ b/examples/ode.hs
@@ -0,0 +1,34 @@
1import Numeric.GSL.ODE
2import Numeric.LinearAlgebra
3import Graphics.Plot
4
5vanderpol mu = do
6 let xdot mu t [x,v] = [v, -x + mu * v * (1-x^2)]
7 ts = linspace 1000 (0,50)
8 sol = toColumns $ odeSolve (xdot mu) [1,0] ts
9 mplot (ts : sol)
10 mplot sol
11
12
13harmonic w d = do
14 let xdot w d t [x,v] = [v, a*x + b*v] where a = -w^2; b = -2*d*w
15 ts = linspace 100 (0,20)
16 sol = odeSolve (xdot w d) [1,0] ts
17 mplot (ts : toColumns sol)
18
19
20kepler v a = mplot (take 2 $ toColumns sol) where
21 xdot t [x,y,vx,vy] = [vx,vy,x*k,y*k]
22 where g=1
23 k=(-g)*(x*x+y*y)**(-1.5)
24 ts = linspace 100 (0,30)
25 sol = odeSolve xdot [4, 0, v * cos (a*degree), v * sin (a*degree)] ts
26 degree = pi/180
27
28
29main = do
30 vanderpol 2
31 harmonic 1 0
32 harmonic 1 0.1
33 kepler 0.3 60
34 kepler 0.4 70
diff --git a/hmatrix.cabal b/hmatrix.cabal
index 6f6c832..1080dcd 100644
--- a/hmatrix.cabal
+++ b/hmatrix.cabal
@@ -25,6 +25,7 @@ extra-source-files: examples/tests.hs
25 examples/integrate.hs 25 examples/integrate.hs
26 examples/minimize.hs 26 examples/minimize.hs
27 examples/root.hs 27 examples/root.hs
28 examples/ode.hs
28 examples/pca1.hs 29 examples/pca1.hs
29 examples/pca2.hs 30 examples/pca2.hs
30 examples/pinv.hs 31 examples/pinv.hs
@@ -37,7 +38,7 @@ extra-source-files: examples/tests.hs
37 examples/error.hs 38 examples/error.hs
38 examples/devel/wrappers.hs 39 examples/devel/wrappers.hs
39 examples/devel/functions.c 40 examples/devel/functions.c
40 examples/HMatrixReal.hs 41 examples/Real.hs
41 42
42extra-source-files: lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.h, 43extra-source-files: lib/Numeric/LinearAlgebra/LAPACK/lapack-aux.h,
43 lib/Numeric/LinearAlgebra/LAPACK/clapack.h 44 lib/Numeric/LinearAlgebra/LAPACK/clapack.h
@@ -85,6 +86,7 @@ library
85 Numeric.GSL.Polynomials, 86 Numeric.GSL.Polynomials,
86 Numeric.GSL.Minimization, 87 Numeric.GSL.Minimization,
87 Numeric.GSL.Root, 88 Numeric.GSL.Root,
89 Numeric.GSL.ODE,
88 Numeric.GSL.Vector, 90 Numeric.GSL.Vector,
89 Numeric.GSL.Special, 91 Numeric.GSL.Special,
90 Numeric.GSL.Special.Gamma, 92 Numeric.GSL.Special.Gamma,
diff --git a/lib/Data/Packed/Matrix.hs b/lib/Data/Packed/Matrix.hs
index dced49f..e204a83 100644
--- a/lib/Data/Packed/Matrix.hs
+++ b/lib/Data/Packed/Matrix.hs
@@ -28,7 +28,7 @@ module Data.Packed.Matrix (
28 extractRows, 28 extractRows,
29 ident, diag, diagRect, takeDiag, 29 ident, diag, diagRect, takeDiag,
30 liftMatrix, liftMatrix2, liftMatrix2Auto, 30 liftMatrix, liftMatrix2, liftMatrix2Auto,
31 dispf, disps, dispcf, showComplex, latexFormat, format, 31 dispf, disps, dispcf, latexFormat, format,
32 loadMatrix, saveMatrix, fromFile, fileDimensions, 32 loadMatrix, saveMatrix, fromFile, fileDimensions,
33 readMatrix, fromArray2D 33 readMatrix, fromArray2D
34) where 34) where
@@ -339,7 +339,7 @@ lookslikeInt x = show (round x :: Int) ++".0" == shx || "-0.0" == shx
339isZero x = show x `elem` ["0.0","-0.0"] 339isZero x = show x `elem` ["0.0","-0.0"]
340isOne x = show x `elem` ["1.0","-1.0"] 340isOne x = show x `elem` ["1.0","-1.0"]
341 341
342-- | Pretty print a complex matrix with with at most n decimal digits. 342-- | Pretty print a complex matrix with at most n decimal digits.
343dispcf :: Int -> Matrix (Complex Double) -> String 343dispcf :: Int -> Matrix (Complex Double) -> String
344dispcf d m = sdims m ++ "\n" ++ format " " (showComplex d) m 344dispcf d m = sdims m ++ "\n" ++ format " " (showComplex d) m
345 345
diff --git a/lib/Numeric/GSL.hs b/lib/Numeric/GSL.hs
index cc5d156..68430bc 100644
--- a/lib/Numeric/GSL.hs
+++ b/lib/Numeric/GSL.hs
@@ -19,6 +19,7 @@ module Numeric.GSL (
19, module Numeric.GSL.Polynomials 19, module Numeric.GSL.Polynomials
20, module Numeric.GSL.Minimization 20, module Numeric.GSL.Minimization
21, module Numeric.GSL.Root 21, module Numeric.GSL.Root
22, module Numeric.GSL.ODE
22, module Numeric.GSL.Special 23, module Numeric.GSL.Special
23, module Complex 24, module Complex
24, setErrorHandlerOff 25, setErrorHandlerOff
@@ -31,6 +32,7 @@ import Numeric.GSL.Fourier
31import Numeric.GSL.Polynomials 32import Numeric.GSL.Polynomials
32import Numeric.GSL.Minimization 33import Numeric.GSL.Minimization
33import Numeric.GSL.Root 34import Numeric.GSL.Root
35import Numeric.GSL.ODE
34import Complex 36import Complex
35 37
36 38
diff --git a/lib/Numeric/GSL/Internal.hs b/lib/Numeric/GSL/Internal.hs
index 834dfc2..37bcc1b 100644
--- a/lib/Numeric/GSL/Internal.hs
+++ b/lib/Numeric/GSL/Internal.hs
@@ -30,6 +30,9 @@ foreign import ccall "wrapper"
30foreign import ccall "wrapper" 30foreign import ccall "wrapper"
31 mkVecVecfun :: TVV -> IO (FunPtr TVV) 31 mkVecVecfun :: TVV -> IO (FunPtr TVV)
32 32
33foreign import ccall "wrapper"
34 mkDoubleVecVecfun :: (Double -> TVV) -> IO (FunPtr (Double -> TVV))
35
33aux_vTov :: (Vector Double -> Vector Double) -> TVV 36aux_vTov :: (Vector Double -> Vector Double) -> TVV
34aux_vTov f n p nr r = g where 37aux_vTov f n p nr r = g where
35 V {fptr = pr} = f x 38 V {fptr = pr} = f x
@@ -43,6 +46,9 @@ aux_vTov f n p nr r = g where
43foreign import ccall "wrapper" 46foreign import ccall "wrapper"
44 mkVecMatfun :: TVM -> IO (FunPtr TVM) 47 mkVecMatfun :: TVM -> IO (FunPtr TVM)
45 48
49foreign import ccall "wrapper"
50 mkDoubleVecMatfun :: (Double -> TVM) -> IO (FunPtr (Double -> TVM))
51
46aux_vTom :: (Vector Double -> Matrix Double) -> TVM 52aux_vTom :: (Vector Double -> Matrix Double) -> TVM
47aux_vTom f n p rr cr r = g where 53aux_vTom f n p rr cr r = g where
48 V {fptr = pr} = flatten $ f x 54 V {fptr = pr} = flatten $ f x
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"
diff --git a/lib/Numeric/GSL/gsl-aux.c b/lib/Numeric/GSL/gsl-aux.c
index 0c71ca1..0fcde1c 100644
--- a/lib/Numeric/GSL/gsl-aux.c
+++ b/lib/Numeric/GSL/gsl-aux.c
@@ -22,6 +22,7 @@
22#include <gsl/gsl_complex_math.h> 22#include <gsl/gsl_complex_math.h>
23#include <gsl/gsl_rng.h> 23#include <gsl/gsl_rng.h>
24#include <gsl/gsl_randist.h> 24#include <gsl/gsl_randist.h>
25#include <gsl/gsl_odeiv.h>
25#include <string.h> 26#include <string.h>
26#include <stdio.h> 27#include <stdio.h>
27 28
@@ -507,7 +508,7 @@ double f_aux_min(const gsl_vector*x, void *pars) {
507 508
508 509
509void df_aux_min(const gsl_vector * x, void * pars, gsl_vector * g) { 510void df_aux_min(const gsl_vector * x, void * pars, gsl_vector * g) {
510 Tfdf * fdf = ((Tfdf*) pars); 511 Tfdf * fdf = ((Tfdf*) pars);
511 double* p = (double*)calloc(x->size,sizeof(double)); 512 double* p = (double*)calloc(x->size,sizeof(double));
512 double* q = (double*)calloc(g->size,sizeof(double)); 513 double* q = (double*)calloc(g->size,sizeof(double));
513 int k; 514 int k;
@@ -797,3 +798,89 @@ int random_vector(int seed, int code, RVEC(r)) {
797 } 798 }
798} 799}
799#undef RAN 800#undef RAN
801
802//////////////////////////////////////////////////////
803// ODE
804
805typedef struct {int n; int (*f)(double,int, const double*, int, double *); int (*j)(double,int, const double*, int, int, double*);} Tode;
806
807int odefunc (double t, const double y[], double f[], void *params) {
808 Tode * P = (Tode*) params;
809 (P->f)(t,P->n,y,P->n,f);
810 return GSL_SUCCESS;
811}
812
813int odejac (double t, const double y[], double *dfdy, double dfdt[], void *params) {
814 Tode * P = ((Tode*) params);
815 (P->j)(t,P->n,y,P->n,P->n,dfdy);
816 int j;
817 for (j=0; j< P->n; j++)
818 dfdt[j] = 0.0;
819 return GSL_SUCCESS;
820}
821
822
823int ode(int method, double h, double eps_abs, double eps_rel,
824 int f(double, int, const double*, int, double*),
825 int jac(double, int, const double*, int, int, double*),
826 KRVEC(xi), KRVEC(ts), RMAT(sol)) {
827
828 const gsl_odeiv_step_type * T;
829
830 switch(method) {
831 case 0 : {T = gsl_odeiv_step_rk2; break; }
832 case 1 : {T = gsl_odeiv_step_rk4; break; }
833 case 2 : {T = gsl_odeiv_step_rkf45; break; }
834 case 3 : {T = gsl_odeiv_step_rkck; break; }
835 case 4 : {T = gsl_odeiv_step_rk8pd; break; }
836 case 5 : {T = gsl_odeiv_step_rk2imp; break; }
837 case 6 : {T = gsl_odeiv_step_rk4imp; break; }
838 case 7 : {T = gsl_odeiv_step_bsimp; break; }
839 case 8 : {T = gsl_odeiv_step_gear1; break; }
840 case 9 : {T = gsl_odeiv_step_gear2; break; }
841 default: ERROR(BAD_CODE);
842 }
843
844
845 gsl_odeiv_step * s = gsl_odeiv_step_alloc (T, xin);
846 gsl_odeiv_control * c = gsl_odeiv_control_y_new (eps_abs, eps_rel);
847 gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc (xin);
848
849 Tode P;
850 P.f = f;
851 P.j = jac;
852 P.n = xin;
853
854 gsl_odeiv_system sys = {odefunc, odejac, xin, &P};
855
856 double t = tsp[0];
857
858 double* y = (double*)calloc(xin,sizeof(double));
859 int i,j;
860 for(i=0; i< xin; i++) {
861 y[i] = xip[i];
862 solp[i] = xip[i];
863 }
864
865 for (i = 1; i < tsn ; i++)
866 {
867 double ti = tsp[i];
868 while (t < ti)
869 {
870 gsl_odeiv_evolve_apply (e, c, s,
871 &sys,
872 &t, ti, &h,
873 y);
874 // if (h < hmin) h = hmin;
875 }
876 for(j=0; j<xin; j++) {
877 solp[i*xin + j] = y[j];
878 }
879 }
880
881 free(y);
882 gsl_odeiv_evolve_free (e);
883 gsl_odeiv_control_free (c);
884 gsl_odeiv_step_free (s);
885 return 0;
886}
diff --git a/lib/Numeric/LinearAlgebra/Tests.hs b/lib/Numeric/LinearAlgebra/Tests.hs
index e6b26a0..46c1804 100644
--- a/lib/Numeric/LinearAlgebra/Tests.hs
+++ b/lib/Numeric/LinearAlgebra/Tests.hs
@@ -135,6 +135,14 @@ rootFindingTest = TestList [ utest "root Hybrids" (fst sol1 ~~ [1,1])
135 135
136--------------------------------------------------------------------- 136---------------------------------------------------------------------
137 137
138odeTest = utest "ode" (last (toLists sol) ~~ [-1.7588880332411019, 8.364348908711941e-2])
139 where sol = odeSolveV RK8pd 1E-6 1E-6 0 (l2v $ vanderpol 10) Nothing (fromList [1,0]) ts
140 ts = linspace 101 (0,100)
141 l2v f = \t -> fromList . f t . toList
142 vanderpol mu _t [x,y] = [y, -x + mu * y * (1-x^2) ]
143
144---------------------------------------------------------------------
145
138randomTestGaussian = c :~1~: snd (meanCov dat) where 146randomTestGaussian = c :~1~: snd (meanCov dat) where
139 a = (3><3) [1,2,3, 147 a = (3><3) [1,2,3,
140 2,4,0, 148 2,4,0,
@@ -280,6 +288,7 @@ runTests n = do
280 , utest "rank" $ rank ((2><3)[1,0,0,1,6*eps,0]) == 1 288 , utest "rank" $ rank ((2><3)[1,0,0,1,6*eps,0]) == 1
281 && rank ((2><3)[1,0,0,1,7*eps,0]) == 2 289 && rank ((2><3)[1,0,0,1,7*eps,0]) == 2
282 , utest "block" $ fromBlocks [[ident 3,0],[0,ident 4]] == (ident 7 :: CM) 290 , utest "block" $ fromBlocks [[ident 3,0],[0,ident 4]] == (ident 7 :: CM)
291 , odeTest
283 ] 292 ]
284 return () 293 return ()
285 294
diff --git a/lib/Numeric/LinearAlgebra/Tests/Properties.hs b/lib/Numeric/LinearAlgebra/Tests/Properties.hs
index 405ce64..42c6ce2 100644
--- a/lib/Numeric/LinearAlgebra/Tests/Properties.hs
+++ b/lib/Numeric/LinearAlgebra/Tests/Properties.hs
@@ -148,7 +148,7 @@ svdProp4 m' = m |~| u <> real (diag s) <> trans v
148 && orthonormal u && orthonormal v 148 && orthonormal u && orthonormal v
149 && (dim s == r || r == 0 && dim s == 1) 149 && (dim s == r || r == 0 && dim s == 1)
150 where (u,s,v) = compactSVD m 150 where (u,s,v) = compactSVD m
151 m = m' <-> m' 151 m = fromBlocks [[m'],[m']]
152 r = rank m' 152 r = rank m'
153 153
154svdProp5a m = and (map (s1|~|) [s2,s3,s4,s5,s6]) where 154svdProp5a m = and (map (s1|~|) [s2,s3,s4,s5,s6]) where