/* # Copyright (c) 2005, 2007, 2008 Andrew Fraser # This file is part of HMM_DS_Code. # # HMM_DS_Code is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # # HMM_DS_Code is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # // ToDo: Run 'indent'. // ToDo: Maybe rename some variables to more descriptive longer names. // ToDo: Mark all functions not exported as 'static'. // ToDo: Markup source for 'doxygen'. // ToDo: ? Is thread safety an issue? Would it be useful to make this // ToDo: code thread-safe ? */ #include #include #include #include #include #include #include #include #include struct ParPac { double s,b,r; }; /* A function that calls a gsl integrator to step the Lorenz system forward in time a spcified number of steps. The Lorenz system is: \dot x = s(y-x) \dot y = rx -xz -y \dot z = xy -bz Derived from http://sources.redhat.com/gsl/ref/gsl-ref_25.html also see http://www.gnu.org/software/gsl/manual/gsl-ref_toc.html */ int Lfunc (double t, const double x[3], double f[3], void *params) { struct ParPac *pac = (struct ParPac *) params; double s = pac->s; double b = pac->b; double r = pac->r; /* These three equations are the vector field for the Lorenz system */ f[0] = (s*(x[1] - x[0])); f[1] = (x[0]*(r-x[2]) - x[1]); f[2] = (x[0]*x[1] - b*x[2]); return GSL_SUCCESS; } /* Ljac may be out of date. Check before using it */ int Ljac (double t, const double x[], double *dfdx, double dfdt[], void *params) { double *dpp = (double *) params; double s = dpp[0]; double b = dpp[1]; double r = dpp[2]; gsl_matrix_view dfdx_mat = gsl_matrix_view_array (dfdx, 3, 3); gsl_matrix * m = &dfdx_mat.matrix; /* out, in */ gsl_matrix_set (m, 0, 0, -s); gsl_matrix_set (m, 0, 1, s); gsl_matrix_set (m, 0, 2, 0); gsl_matrix_set (m, 1, 0, r); gsl_matrix_set (m, 1, 1, -1); gsl_matrix_set (m, 1, 2, -x[0]); gsl_matrix_set (m, 2, 0, x[1]); gsl_matrix_set (m, 2, 1, x[0]); gsl_matrix_set (m, 2, 2, -b); dfdt[0] = 0.0; dfdt[1] = 0.0; dfdt[2] = 0.0; return GSL_SUCCESS; } int Lsteps( double *y, /* Initial condition y[0:2] */ struct ParPac *pac, /* Paramters */ double ts, /* Time step */ int Nt, /* Number of time steps */ float *result) /* Memory for results */ { const gsl_odeiv_step_type * T = gsl_odeiv_step_rkf45; gsl_odeiv_step * s = gsl_odeiv_step_alloc (T, 3); /*This function returns a pointer to a newly allocated instance of a stepping function of type T for a system of 3 dimensions. */ gsl_odeiv_control * c = gsl_odeiv_control_y_new (1e-7, 0.0); /*This function creates a new control object which will keep the local error on each step within an absolute error of 1e-7. If the second argument were eps_rel and not zero, it would keep the relative error of eps_rel with respect to the solution y_i(t). */ gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc (3); /* This function returns a pointer to a newly allocated instance of an evolution function for a system of 3 dimensions. */ gsl_odeiv_system sys = {Lfunc, Ljac, 3, pac}; double t, t1; double h = 1e-6; int i; result[0] = y[0]; result[1] = y[1]; result[2] = y[2]; t = 0; for(i=1;is; double b = pac->b; double r = pac->r; double DF[3][3] = {-s, s, 0, /* This is the derivative */ r-x[2], -1, -x[0], /* of the vector field */ x[1], x[0], -b}; double *T[3]; double *Tdot[3]; {int i,j,k; /* Set T and Tdot to point */ for(i = 0; i<3; i++){ /* into the arguments x */ T[i] = x + 3*(i+1); /* and f respectively */ Tdot[i] = f + 3*(i+1); } /* These three equations are the vector field for the Lorenz system */ f[0] = (s*(x[1] - x[0])); f[1] = (x[0]*(r-x[2]) - x[1]); f[2] = (x[0]*x[1] - b*x[2]); /* Set Tdot = DF * T */ for(i = 0; i<3; i++){ for(j = 0; j<3; j++){ Tdot[i][j] = 0; for(k = 0; k<3; k++){ Tdot[i][j] += DF[i][k] * T[k][j]; } } } } return GSL_SUCCESS; } int Ltansteps( double *y, /* Initial condition y[0:11] */ struct ParPac *pac, /* Paramters */ double ts, /* Time step */ int Nt, /* Number of time steps */ double *result) /* Want result[Nt][12] but weave can't */ { const gsl_odeiv_step_type * T = gsl_odeiv_step_rkf45; gsl_odeiv_step * s = gsl_odeiv_step_alloc (T, 12); /*This function returns a pointer to a newly allocated instance of a stepping function of type T for a system of 12 dimensions. */ gsl_odeiv_control * c = gsl_odeiv_control_y_new (1e-7, 0.0); /*This function creates a new control object which will keep the local error on each step within an absolute error of 1e-7. If the second argument were eps_rel and not zero, it would keep the relative error of eps_rel with respect to the solution y_i(t). */ gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc (12); /* This function returns a pointer to a newly allocated instance of an evolution function for a system of 12 dimensions. */ gsl_odeiv_system sys = {Ltan, NULL, 12, pac}; double t, t1; double h = 1e-6; int i,it; for(i=0;i<12;i++) result[i] = y[i]; t = 0; for(it=1;its; double b = pac->b; double r = pac->r; /* These three equations are the vector field for the Lorenz system */ f[0] = -(s*(x[1] - x[0])); f[1] = -(x[0]*(r-x[2]) - x[1]); f[2] = -(x[0]*x[1] - b*x[2]); return GSL_SUCCESS; } int LBstep( double *y, /* Initial condition y[0:2] */ struct ParPac *pac, /* Paramters */ double ts, /* Time step */ float *result) /* Array to hold results result[0:2] */ { const gsl_odeiv_step_type * T = gsl_odeiv_step_rkf45; gsl_odeiv_step * s = gsl_odeiv_step_alloc (T, 3); gsl_odeiv_control * c = gsl_odeiv_control_y_new (1e-2, 0.0); gsl_odeiv_evolve * e = gsl_odeiv_evolve_alloc (3); gsl_odeiv_system sys = {LBfunc, Ljac, 3, pac}; double t; double h = 1e-6; t = 0; while (t < ts) { int status = gsl_odeiv_evolve_apply (e, c, s, &sys, &t, ts, &h, y); if (status != GSL_SUCCESS) { fprintf(stderr, "failure of gsl_odeiv_evolve_apply.\n"); return(-1); } } result[0] = y[0]; result[1] = y[1]; result[2] = y[2]; gsl_odeiv_evolve_free(e); gsl_odeiv_control_free(c); gsl_odeiv_step_free(s); return(0); }