static VALUE rb_gsl_odeiv_step_apply(int argc, VALUE *argv, VALUE obj) { gsl_odeiv_step *s = NULL; gsl_odeiv_system *sys = NULL; gsl_vector *y = NULL, *yerr = NULL; gsl_vector *vtmp1 = NULL, *vtmp2 = NULL; double *dydt_in = NULL, *dydt_out = NULL; double t, h; switch (argc) { case 5: break; case 7: if (VECTOR_P(argv[5])) { Data_Get_Struct(argv[5], gsl_vector, vtmp2); if (vtmp2) dydt_out = vtmp2->data; } /* no break */ case 6: if (VECTOR_P(argv[4])) { Data_Get_Struct(argv[4], gsl_vector, vtmp1); if (vtmp1) dydt_in = vtmp1->data; } break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 5, 6 or 7)", argc); break; } Need_Float(argv[0]); Need_Float(argv[1]); CHECK_VECTOR(argv[2]); CHECK_VECTOR(argv[3]); CHECK_SYSTEM(argv[argc-1]); Data_Get_Struct(obj, gsl_odeiv_step, s); t = NUM2DBL(argv[0]); h = NUM2DBL(argv[1]); Data_Get_Struct(argv[2], gsl_vector, y); Data_Get_Struct(argv[3], gsl_vector, yerr); Data_Get_Struct(argv[argc-1], gsl_odeiv_system, sys); return INT2FIX(gsl_odeiv_step_apply(s, t, h, y->data, yerr->data, dydt_in, dydt_out, sys)); }
CAMLprim value ml_gsl_odeiv_step_apply(value step, value t, value h, value y, value yerr, value odydt_in, value odydt_out, value syst) { CAMLparam5(step, syst, y, yerr, odydt_out); LOCALARRAY(double, y_copy, Double_array_length(y)); LOCALARRAY(double, yerr_copy, Double_array_length(yerr)); size_t len_dydt_in = odydt_in == Val_none ? 0 : Double_array_length(Unoption(odydt_in)) ; size_t len_dydt_out = odydt_out == Val_none ? 0 : Double_array_length(Unoption(odydt_out)) ; LOCALARRAY(double, dydt_in, len_dydt_in); LOCALARRAY(double, dydt_out, len_dydt_out); int status; if(len_dydt_in) memcpy(dydt_in, Double_array_val(Unoption(odydt_in)), Bosize_val(Unoption(odydt_in))); memcpy(y_copy, Double_array_val(y), Bosize_val(y)); memcpy(yerr_copy, Double_array_val(yerr), Bosize_val(yerr)); status = gsl_odeiv_step_apply(ODEIV_STEP_VAL(step), Double_val(t), Double_val(h), y_copy, yerr_copy, len_dydt_in ? dydt_in : NULL, len_dydt_out ? dydt_out : NULL, ODEIV_SYSTEM_VAL(syst)); /* GSL does not call the error handler for this function */ if (status) GSL_ERROR_VAL ("gsl_odeiv_step_apply", status, Val_unit); memcpy(Double_array_val(y), y_copy, sizeof(y_copy)); memcpy(Double_array_val(yerr), yerr_copy, sizeof(yerr_copy)); if(len_dydt_out) memcpy(Double_array_val(Unoption(odydt_out)), dydt_out, Bosize_val(Unoption(odydt_out))); CAMLreturn(Val_unit); }
void test_odeiv_stepper (const gsl_odeiv_step_type *T, const gsl_odeiv_system *sys, const double h, const double t, const char desc[], const double ystart[], const double yfin[], const double relerr) { /* tests stepper T with one fixed length step advance of system sys and compares with given values yfin */ double y[MAXEQ] = {0.0}; double yerr[MAXEQ] = {0.0}; size_t ne = sys->dimension; size_t i; gsl_odeiv_step *step = gsl_odeiv_step_alloc (T, ne); DBL_MEMCPY (y, ystart, MAXEQ); { int s = gsl_odeiv_step_apply (step, t, h, y, yerr, 0, 0, sys); if (s != GSL_SUCCESS) { gsl_test(s, "test_odeiv_stepper: %s step_apply returned %d", desc, s); } } for (i = 0; i < ne; i++) { gsl_test_rel (y[i], yfin[i], relerr, "%s %s step(%d)", gsl_odeiv_step_name (step), desc,i); } gsl_odeiv_step_free (step); }
inline void do_step( const double dt ) { gsl_odeiv_step_apply ( m_s , m_t , dt , m_x , m_x_err , 0 , 0 , &m_sys ); //m_t += dt; }
/* Wrappers for the evaluation of the system */ static PyObject * PyGSL_odeiv_step_apply(PyGSL_odeiv_step *self, PyObject *args) { PyObject *result = NULL; PyObject *y0_o = NULL, *dydt_in_o = NULL; PyArrayObject *volatile y0 = NULL, * volatile yerr = NULL, *volatile dydt_in = NULL, *volatile dydt_out = NULL, *volatile yout = NULL; double t=0, h=0, *volatile dydt_in_d; int dimension, r, flag; FUNC_MESS_BEGIN(); assert(PyGSL_ODEIV_STEP_Check(self)); if(! PyArg_ParseTuple(args, "ddOOO", &t, &h, &y0_o, &dydt_in_o)){ return NULL; } dimension = self->system.dimension; y0 = PyGSL_PyArray_PREPARE_gsl_vector_view(y0_o, PyArray_DOUBLE, 1, dimension, 1, NULL); if(y0 == NULL) goto fail; if (Py_None == dydt_in_o){ dydt_in_d = NULL; }else{ dydt_in = PyGSL_PyArray_PREPARE_gsl_vector_view(dydt_in_o, PyArray_DOUBLE, 1, dimension, 2, NULL); if(dydt_in == NULL) goto fail; dydt_in_d = (double *) dydt_in->data; } dydt_out = (PyArrayObject *) PyArray_FromDims(1, &dimension, PyArray_DOUBLE); if (dydt_out == NULL) goto fail; yerr = (PyArrayObject *) PyArray_FromDims(1, &dimension, PyArray_DOUBLE); if(yerr == NULL) goto fail; yout = (PyArrayObject *) PyArray_CopyFromObject((PyObject * ) y0, PyArray_DOUBLE, 1, 1); if(yout == NULL) goto fail; if((flag=setjmp(self->buffer)) == 0){ FUNC_MESS("\t\t Setting Jmp Buffer"); } else { FUNC_MESS("\t\t Returning from Jmp Buffer"); goto fail; } r = gsl_odeiv_step_apply(self->step, t, h, (double *) yout->data, (double *) yerr->data, dydt_in_d, (double *) dydt_out->data, &(self->system)); if (GSL_SUCCESS != r){ PyErr_SetString(PyExc_TypeError, "Error While evaluating gsl_odeiv"); goto fail; } FUNC_MESS(" Returnlist create "); assert(yout != NULL); assert(yerr != NULL); assert(dydt_out != NULL); result = Py_BuildValue("(OOO)", yout, yerr, dydt_out); FUNC_MESS(" Memory free "); /* Deleting the arrays */ Py_DECREF(y0); y0 = NULL; Py_DECREF(yout); yout = NULL; Py_DECREF(yerr); yerr = NULL; Py_DECREF(dydt_out); dydt_out = NULL; /* This array does not need to exist ... */ Py_XDECREF(dydt_in); dydt_in=NULL; FUNC_MESS_END(); return result; fail: FUNC_MESS("IN Fail"); Py_XDECREF(y0); Py_XDECREF(yout); Py_XDECREF(yerr); Py_XDECREF(dydt_in); Py_XDECREF(dydt_out); FUNC_MESS("IN Fail End"); return NULL; }
/* Evolution framework method. * * Uses an adaptive step control object */ int gsl_odeiv_evolve_apply (gsl_odeiv_evolve * e, gsl_odeiv_control * con, gsl_odeiv_step * step, const gsl_odeiv_system * dydt, double *t, double t1, double *h, double y[]) { const double t0 = *t; double h0 = *h; int step_status; int final_step = 0; double dt = t1 - t0; /* remaining time, possibly less than h */ if (e->dimension != step->dimension) { GSL_ERROR ("step dimension must match evolution size", GSL_EINVAL); } if ((dt < 0.0 && h0 > 0.0) || (dt > 0.0 && h0 < 0.0)) { GSL_ERROR ("step direction must match interval direction", GSL_EINVAL); } /* No need to copy if we cannot control the step size. */ if (con != NULL) { DBL_MEMCPY (e->y0, y, e->dimension); } /* Calculate initial dydt once if the method can benefit. */ if (step->type->can_use_dydt_in) { int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in); if (status) { return status; } } try_step: if ((dt >= 0.0 && h0 > dt) || (dt < 0.0 && h0 < dt)) { h0 = dt; final_step = 1; } else { final_step = 0; } if (step->type->can_use_dydt_in) { step_status = gsl_odeiv_step_apply (step, t0, h0, y, e->yerr, e->dydt_in, e->dydt_out, dydt); } else { step_status = gsl_odeiv_step_apply (step, t0, h0, y, e->yerr, NULL, e->dydt_out, dydt); } /* Check for stepper internal failure */ if (step_status != GSL_SUCCESS) { *h = h0; /* notify user of step-size which caused the failure */ return step_status; } e->count++; e->last_step = h0; if (final_step) { *t = t1; } else { *t = t0 + h0; } if (con != NULL) { /* Check error and attempt to adjust the step. */ double h_old = h0; const int hadjust_status = gsl_odeiv_control_hadjust (con, step, y, e->yerr, e->dydt_out, &h0); if (hadjust_status == GSL_ODEIV_HADJ_DEC) { /* Check that the reported status is correct (i.e. an actual decrease in h0 occured) and the suggested h0 will change the time by at least 1 ulp */ double t_curr = GSL_COERCE_DBL(*t); double t_next = GSL_COERCE_DBL((*t) + h0); if (fabs(h0) < fabs(h_old) && t_next != t_curr) { /* Step was decreased. Undo step, and try again with new h0. */ DBL_MEMCPY (y, e->y0, dydt->dimension); e->failed_steps++; goto try_step; } else { h0 = h_old; /* keep current step size */ } } } *h = h0; /* suggest step size for next time-step */ return step_status; }
static int gear2_apply (void *vstate, size_t dim, double t, double h, double y[], double yerr[], const double dydt_in[], double dydt_out[], const gsl_odeiv_system * sys) { gear2_state_t *state = (gear2_state_t *) vstate; state->stutter = 0; if (state->primed == 0 || t == state->t_primed || h != state->last_h) { /* Execute a single-step method to prime the process. Note that * we do this if the step size changes, so frequent step size * changes will cause the method to stutter. * * Note that we reuse this method if the time has not changed, * which can occur when the adaptive driver is attempting to find * an appropriate step-size on its first iteration */ int status; DBL_MEMCPY (state->yim1, y, dim); status = gsl_odeiv_step_apply (state->primer, t, h, y, yerr, dydt_in, dydt_out, sys); /* Make note of step size and indicate readiness for a Gear step. */ state->primed = 1; state->t_primed = t; state->last_h = h; state->stutter = 1; return status; } else { /* We have a previous y value in the buffer, and the step * sizes match, so we go ahead with the Gear step. */ double *const k = state->k; double *const y0 = state->y0; double *const y0_orig = state->y0_orig; double *const yim1 = state->yim1; double *y_onestep = state->y_onestep; int s; size_t i; DBL_MEMCPY (y0, y, dim); /* iterative solution */ if (dydt_out != NULL) { DBL_MEMCPY (k, dydt_out, dim); } /* First traverse h with one step (save to y_onestep) */ DBL_MEMCPY (y_onestep, y, dim); s = gear2_step (y_onestep, state, h, t, dim, sys); if (s != GSL_SUCCESS) { return s; } /* Then with two steps with half step length (save to y) */ s = gear2_step (y, state, h / 2.0, t, dim, sys); if (s != GSL_SUCCESS) { /* Restore original y vector */ DBL_MEMCPY (y, y0_orig, dim); return s; } DBL_MEMCPY (y0, y, dim); s = gear2_step (y, state, h / 2.0, t + h / 2.0, dim, sys); if (s != GSL_SUCCESS) { /* Restore original y vector */ DBL_MEMCPY (y, y0_orig, dim); return s; } /* Cleanup update */ if (dydt_out != NULL) { s = GSL_ODEIV_FN_EVAL (sys, t + h, y, dydt_out); if (s != GSL_SUCCESS) { /* Restore original y vector */ DBL_MEMCPY (y, y0_orig, dim); return s; } } /* Estimate error and update the state buffer. */ for (i = 0; i < dim; i++) { yerr[i] = 4.0 * (y[i] - y_onestep[i]); yim1[i] = y0[i]; } /* Make note of step size. */ state->last_h = h; return 0; } }
/** * Evolves a post-Newtonian orbit using the Taylor T4 method. * * See: * Michael Boyle, Duncan A. Brown, Lawrence E. Kidder, Abdul H. Mroue, * Harald P. Pfeiffer, Mark A. Scheel, Gregory B. Cook, and Saul A. Teukolsky * "High-accuracy comparison of numerical relativity simulations with * post-Newtonian expansions" * <a href="http://arxiv.org/abs/0710.0158v2">arXiv:0710.0158v2</a>. */ int XLALSimInspiralTaylorT4PNEvolveOrbit( REAL8TimeSeries **v, /**< post-Newtonian parameter [returned] */ REAL8TimeSeries **phi, /**< orbital phase [returned] */ REAL8 phiRef, /**< reference orbital phase (rad) */ REAL8 deltaT, /**< sampling interval (s) */ REAL8 m1, /**< mass of companion 1 (kg) */ REAL8 m2, /**< mass of companion 2 (kg) */ REAL8 f_min, /**< start frequency (Hz) */ REAL8 fRef, /**< reference frequency (Hz) */ REAL8 lambda1, /**< (tidal deformability of body 1)/(mass of body 1)^5 */ REAL8 lambda2, /**< (tidal deformability of body 2)/(mass of body 2)^5 */ LALSimInspiralTidalOrder tideO, /**< flag to control spin and tidal effects */ int O /**< twice post-Newtonian order */ ) { const UINT4 blocklen = 1024; const REAL8 visco = 1./sqrt(6.); REAL8 VRef = 0.; XLALSimInspiralTaylorT4PNEvolveOrbitParams params; expnFuncTaylorT4 expnfunc; expnCoeffsTaylorT4 ak; expnCoeffsdEnergyFlux akdEF; if(XLALSimInspiralTaylorT4Setup(&ak,&expnfunc,&akdEF,m1,m2,lambda1,lambda2, tideO,O)) XLAL_ERROR(XLAL_EFUNC); params.func=expnfunc.angacc4; params.ak=ak; REAL8 E; UINT4 j, len, idxRef = 0; LIGOTimeGPS tc = LIGOTIMEGPSZERO; double y[2]; double yerr[2]; const gsl_odeiv_step_type *T = gsl_odeiv_step_rk4; gsl_odeiv_step *s; gsl_odeiv_system sys; /* setup ode system */ sys.function = XLALSimInspiralTaylorT4PNEvolveOrbitIntegrand; sys.jacobian = NULL; sys.dimension = 2; sys.params = ¶ms; /* allocate memory */ *v = XLALCreateREAL8TimeSeries( "ORBITAL_VELOCITY_PARAMETER", &tc, 0., deltaT, &lalDimensionlessUnit, blocklen ); *phi = XLALCreateREAL8TimeSeries( "ORBITAL_PHASE", &tc, 0., deltaT, &lalDimensionlessUnit, blocklen ); if ( !v || !phi ) XLAL_ERROR(XLAL_EFUNC); y[0] = (*v)->data->data[0] = cbrt(LAL_PI*LAL_G_SI*ak.m*f_min)/LAL_C_SI; y[1] = (*phi)->data->data[0] = 0.; E = expnfunc.energy4(y[0],&akdEF); if (XLALIsREAL8FailNaN(E)) XLAL_ERROR(XLAL_EFUNC); j = 0; s = gsl_odeiv_step_alloc(T, 2); while (1) { ++j; gsl_odeiv_step_apply(s, j*deltaT, deltaT, y, yerr, NULL, NULL, &sys); /* ISCO termination condition for quadrupole, 1pN, 2.5pN */ if ( y[0] > visco ) { XLALPrintInfo("XLAL Info - %s: PN inspiral terminated at ISCO\n", __func__); break; } if ( j >= (*v)->data->length ) { if ( ! XLALResizeREAL8TimeSeries(*v, 0, (*v)->data->length + blocklen) ) XLAL_ERROR(XLAL_EFUNC); if ( ! XLALResizeREAL8TimeSeries(*phi, 0, (*phi)->data->length + blocklen) ) XLAL_ERROR(XLAL_EFUNC); } (*v)->data->data[j] = y[0]; (*phi)->data->data[j] = y[1]; } gsl_odeiv_step_free(s); /* make the correct length */ if ( ! XLALResizeREAL8TimeSeries(*v, 0, j) ) XLAL_ERROR(XLAL_EFUNC); if ( ! XLALResizeREAL8TimeSeries(*phi, 0, j) ) XLAL_ERROR(XLAL_EFUNC); /* adjust to correct time */ XLALGPSAdd(&(*v)->epoch, -1.0*j*deltaT); XLALGPSAdd(&(*phi)->epoch, -1.0*j*deltaT); /* Do a constant phase shift to get desired value of phiRef */ len = (*phi)->data->length; /* For fRef==0, phiRef is phase of last sample */ if( fRef == 0. ) phiRef -= (*phi)->data->data[len-1]; /* For fRef==fmin, phiRef is phase of first sample */ else if( fRef == f_min ) phiRef -= (*phi)->data->data[0]; /* phiRef is phase when f==fRef */ else { VRef = pow(LAL_PI * LAL_G_SI*(m1+m2) * fRef, 1./3.) / LAL_C_SI; j = 0; do { idxRef = j; j++; } while ((*v)->data->data[j] <= VRef); phiRef -= (*phi)->data->data[idxRef]; } for (j = 0; j < len; ++j) (*phi)->data->data[j] += phiRef; return (int)(*v)->data->length; }
/* Evolution framework method. * * Uses an adaptive step control object */ int gsl_odeiv_evolve_apply (gsl_odeiv_evolve * e, gsl_odeiv_control * con, gsl_odeiv_step * step, const gsl_odeiv_system * dydt, double *t, double t1, double *h, double y[]) { const double t0 = *t; double h0 = *h; int step_status; int final_step = 0; double dt = t1 - t0; /* remaining time, possibly less than h */ if (e->dimension != step->dimension) { GSL_ERROR ("step dimension must match evolution size", GSL_EINVAL); } if ((dt < 0.0 && h0 > 0.0) || (dt > 0.0 && h0 < 0.0)) { GSL_ERROR ("step direction must match interval direction", GSL_EINVAL); } /* No need to copy if we cannot control the step size. */ if (con != NULL) { DBL_MEMCPY (e->y0, y, e->dimension); } /* Calculate initial dydt once if the method can benefit. */ if (step->type->can_use_dydt_in) { int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in); if (status) { return status; } } try_step: if ((dt >= 0.0 && h0 > dt) || (dt < 0.0 && h0 < dt)) { h0 = dt; final_step = 1; } else { final_step = 0; } if (step->type->can_use_dydt_in) { step_status = gsl_odeiv_step_apply (step, t0, h0, y, e->yerr, e->dydt_in, e->dydt_out, dydt); } else { step_status = gsl_odeiv_step_apply (step, t0, h0, y, e->yerr, NULL, e->dydt_out, dydt); } /* Check for stepper internal failure */ if (step_status != GSL_SUCCESS) { return step_status; } e->count++; e->last_step = h0; if (final_step) { *t = t1; } else { *t = t0 + h0; } if (con != NULL) { /* Check error and attempt to adjust the step. */ const int hadjust_status = gsl_odeiv_control_hadjust (con, step, y, e->yerr, e->dydt_out, &h0); if (hadjust_status == GSL_ODEIV_HADJ_DEC) { /* Step was decreased. Undo and go back to try again. */ DBL_MEMCPY (y, e->y0, dydt->dimension); e->failed_steps++; goto try_step; } } *h = h0; /* suggest step size for next time-step */ return step_status; }
int idmc_traj_ctrajectory_step(idmc_traj_ctrajectory *trajectory) { return gsl_odeiv_step_apply(trajectory->step_function, 0, trajectory->step_size, trajectory->var, trajectory->error, NULL, NULL, &trajectory->system); }
/*This is the main function of the integration program that calls the gsl Runge-Kutta integrator:*/ void integrator(function F, int D, void *params, double x[], double dxdt[], double x0[], double t[], int iters, double s_noise, double abstol, double reltol) { /*Temporary variables*/ double *y = (double*) malloc( sizeof(double)*D ); /*state variable at time t-1 (input) and then at time t(output)*/ double *dydt_in = (double*) malloc( sizeof(double)*D ); /*rate of change at time point t-1*/ double *dydt_out= (double*) malloc( sizeof(double)*D ); /*rate of change at time point t*/ double *yerr = (double*) malloc( sizeof(double)*D );/*error*/ double t0,tf,tc,dt=(t[1]-t[0])/2,noise;/*initial time point, final time point, current time point, current time step, noise*/ int j,ii;/*State variable and iteration indexes*/ int status;/*integrator success flag*/ /*Definitions and initializations of gsl integrator necessary inputs and parameters:*/ /*Prepare noise generator*/ const gsl_rng_type *Q; gsl_rng *r; gsl_rng_env_setup(); Q = gsl_rng_default; r = gsl_rng_alloc(Q); /*Create a stepping function*/ const gsl_odeiv_step_type *T = gsl_odeiv_step_rkf45; gsl_odeiv_step *s = gsl_odeiv_step_alloc(T, D); /*Create an adaptive control function*/ gsl_odeiv_control *c = gsl_odeiv_control_y_new(abstol, reltol); /*Create the system to be integrated (with NULL jacobian)*/ gsl_odeiv_system sys = {F, NULL, D, params}; /*The integration loop:*/ /*Initialize*/ /*Calculate dx/dt for x0*/ tc=t[0]; /* initialise dydt_in from system parameters */ /*GSL_ODEIV_FN_EVAL(&sys, t, y, dydt_in);*/ GSL_ODEIV_FN_EVAL(&sys, tc, x0, dydt_in); for (j=0;j<D;j++) { y[j] = x[j] = x0[j]; } /*Integration*/ for (ii=1; ii<iters; ii++) { /*Call the integrator*/ /*int gsl_odeiv_step_apply(gsl_odeiv_step * s, double t, double h, double y[], double yerr[], const double dydt_in[], double dydt_out[], const gsl_odeiv_system * dydt)*/ t0=t[ii-1]; tf=t[ii]; tc=t0; while (tc<tf) { /*Constraint time step h such as that tc+h<=tf*/ if (tc+dt>tf) dt=tf-tc; /*Advance a h time step*/ status=gsl_odeiv_step_apply(s, tc, dt, y, yerr, dydt_in, dydt_out, &sys); if (status != GSL_SUCCESS) break; /*Modify time sep*/ gsl_odeiv_control_hadjust(c,s,y,yerr,dydt_in,&dt); /*Increase current time*/ tc += dt; /*Add noise*/ for (j=0;j<D;j++) { noise=gsl_ran_gaussian_ziggurat(r, s_noise); y[j] += sqrt(dt)*noise; //dydt_in[j]+=noise; } } /*Unpack and store result for this time point*/ if (status != GSL_SUCCESS) break; for (j=0;j<D;j++) { x[ii*D+j] = y[j]; dxdt[(ii-1)*D+j] = dydt_in[j]; /*Prepare next step*/ dydt_in[j] = dydt_out[j]; } } /*Get dxdt for the last time point*/ for (j=0;j<D;j++) dxdt[(iters-1)*D+j] = dydt_out[j]; /*Free dynamically allocated memory*/ gsl_odeiv_control_free(c); printf("c freed\n"); gsl_odeiv_step_free(s); printf("s freed\n"); gsl_rng_free(r); printf("rng freed\n"); free(yerr); printf("yerr freed\n"); free(dydt_out); printf("dydt_out freed\n"); free(dydt_in); printf("dydt_in freed\n"); free(y); printf("y freed\n"); }