diff options
Diffstat (limited to 'lib/Numeric')
-rw-r--r-- | lib/Numeric/GSL.hs | 2 | ||||
-rw-r--r-- | lib/Numeric/GSL/Internal.hs | 6 | ||||
-rw-r--r-- | lib/Numeric/GSL/ODE.hs | 107 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.c | 89 | ||||
-rw-r--r-- | lib/Numeric/LinearAlgebra/Tests.hs | 9 | ||||
-rw-r--r-- | lib/Numeric/LinearAlgebra/Tests/Properties.hs | 2 |
6 files changed, 213 insertions, 2 deletions
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 | |||
31 | import Numeric.GSL.Polynomials | 32 | import Numeric.GSL.Polynomials |
32 | import Numeric.GSL.Minimization | 33 | import Numeric.GSL.Minimization |
33 | import Numeric.GSL.Root | 34 | import Numeric.GSL.Root |
35 | import Numeric.GSL.ODE | ||
34 | import Complex | 36 | import 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" | |||
30 | foreign import ccall "wrapper" | 30 | foreign import ccall "wrapper" |
31 | mkVecVecfun :: TVV -> IO (FunPtr TVV) | 31 | mkVecVecfun :: TVV -> IO (FunPtr TVV) |
32 | 32 | ||
33 | foreign import ccall "wrapper" | ||
34 | mkDoubleVecVecfun :: (Double -> TVV) -> IO (FunPtr (Double -> TVV)) | ||
35 | |||
33 | aux_vTov :: (Vector Double -> Vector Double) -> TVV | 36 | aux_vTov :: (Vector Double -> Vector Double) -> TVV |
34 | aux_vTov f n p nr r = g where | 37 | aux_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 | |||
43 | foreign import ccall "wrapper" | 46 | foreign import ccall "wrapper" |
44 | mkVecMatfun :: TVM -> IO (FunPtr TVM) | 47 | mkVecMatfun :: TVM -> IO (FunPtr TVM) |
45 | 48 | ||
49 | foreign import ccall "wrapper" | ||
50 | mkDoubleVecMatfun :: (Double -> TVM) -> IO (FunPtr (Double -> TVM)) | ||
51 | |||
46 | aux_vTom :: (Vector Double -> Matrix Double) -> TVM | 52 | aux_vTom :: (Vector Double -> Matrix Double) -> TVM |
47 | aux_vTom f n p rr cr r = g where | 53 | aux_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 | {- | | ||
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" | ||
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 | ||
509 | void df_aux_min(const gsl_vector * x, void * pars, gsl_vector * g) { | 510 | void 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 | |||
805 | typedef struct {int n; int (*f)(double,int, const double*, int, double *); int (*j)(double,int, const double*, int, int, double*);} Tode; | ||
806 | |||
807 | int 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 | |||
813 | int 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 | |||
823 | int 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 | ||
138 | odeTest = 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 | |||
138 | randomTestGaussian = c :~1~: snd (meanCov dat) where | 146 | randomTestGaussian = 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 | ||
154 | svdProp5a m = and (map (s1|~|) [s2,s3,s4,s5,s6]) where | 154 | svdProp5a m = and (map (s1|~|) [s2,s3,s4,s5,s6]) where |