/* nag_ode_ivp_rkts_reset_tend (d02prc) Example Program. * * Copyright 2013 Numerical Algorithms Group. * * Mark 24, 2013. */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif static void NAG_CALL f(double t, Integer n, const double *y, double *yp, Nag_Comm *comm); #ifdef __cplusplus } #endif #define N 4 int main(void) { /* Scalars */ double tol0 = 1.0e-3; Integer npts = 6, exit_status = 0; Integer liwsav, lrwsav, n; double hnext, hstart, tendnu, tfinal, tinc, tgot, tol, tstart, waste; Integer fevals, i, j, k, stepcost, stepsok; /* Arrays */ static double ruser[1] = {-1.0}; double *rwsav = 0, *thresh = 0, *ygot = 0, *yinit = 0, *ypgot = 0; Integer *iwsav = 0; char nag_enum_arg[40]; /* NAG types */ NagError fail; Nag_RK_method method; Nag_ErrorAssess errass; Nag_Comm comm; INIT_FAIL(fail); printf("nag_ode_ivp_rkts_reset_tend (d02prc) Example Program Results\n\n"); /* For communication with user-supplied functions: */ comm.user = ruser; n = N; liwsav = 130; lrwsav = 350 + 32 * n; if ( !(thresh = NAG_ALLOC(n, double)) || !(ygot = NAG_ALLOC(n, double)) || !(yinit = NAG_ALLOC(n, double)) || !(ypgot = NAG_ALLOC(n, double)) || !(iwsav = NAG_ALLOC(liwsav, Integer)) || !(rwsav = NAG_ALLOC(lrwsav, double)) ) { printf("Allocation failure\n"); exit_status = -1; goto END; } /* Skip heading in data file*/ scanf("%*[^\n] "); /* Set initial conditions for ODE and parameters for the integrator. */ scanf(" %39s%*[^\n] ", nag_enum_arg); /* nag_enum_name_to_value (x04nac) Converts NAG enum member name to value. */ method = (Nag_RK_method) nag_enum_name_to_value(nag_enum_arg); scanf(" %39s%*[^\n] ", nag_enum_arg); errass = (Nag_ErrorAssess) nag_enum_name_to_value(nag_enum_arg); scanf("%lf%lf%*[^\n] ", &tstart, &tfinal); for (j = 0; j < n; j++) scanf("%lf", &yinit[j]); scanf("%*[^\n] "); scanf("%lf%*[^\n] ", &hstart); for (j = 0; j < n; j++) scanf("%lf", &thresh[j]); scanf("%*[^\n] "); tinc = (tfinal - tstart)/(double) (npts); tol = tol0; for (i = 1; i <= 2; i++) { tol = tol * 0.1; tendnu = tstart + tinc; /* Initialize Runge-Kutta method for integrating ODE using * nag_ode_ivp_rkts_setup (d02pqc). */ nag_ode_ivp_rkts_setup(n, tstart, tendnu, yinit, tol, thresh, method, errass, hstart, iwsav, rwsav, &fail); if (fail.code != NE_NOERROR) { printf("Error from nag_ode_ivp_rkts_setup (d02pqc).\n%s\n", fail.message); exit_status = 1; goto END; } printf(" Calculation with tol = %8.1e\n", tol); printf(" t y1 y2 y3 y4\n"); printf("%6.3f", tstart); for (k = 0; k < n; k++) printf(" %7.3f", yinit[k]); printf("\n"); tgot = tstart; while (tgot < tfinal) { /* Solve ODE by Runge-Kutta method by a sequence of single steps using * nag_ode_ivp_rkts_onestep (d02pfc). */ nag_ode_ivp_rkts_onestep(f, n, &tgot, ygot, ypgot, &comm, iwsav, rwsav, &fail); if (fail.code != NE_NOERROR) { printf("Error from nag_ode_ivp_rkts_onestep (d02pfc).\n%s\n", fail.message); exit_status = 2; goto END; } /* When incremental stage in t has been reached: * print solution and reset end time for next stage. */ if (tgot == tendnu) { printf("%6.3f", tgot); for (k = 0; k < n; k++) printf(" %7.3f", ygot[k]); printf("\n"); /* Reset end-time for integration by adding increment tinc using * nag_ode_ivp_rkts_reset_tend (d02prc): resets end of range for * nag_ode_ivp_rkts_onestep (d02pfc). */ tendnu = tendnu + tinc; nag_ode_ivp_rkts_reset_tend(tendnu, iwsav, rwsav, &fail); if (fail.code != NE_NOERROR) { printf( "Error from nag_ode_ivp_rkts_reset_tend (d02prc).\n%s\n", fail.message); exit_status = 3; goto END; } } } /* Get diagnostics on whole integration using * nag_ode_ivp_rkts_diag (d02ptc). */ nag_ode_ivp_rkts_diag(&fevals, &stepcost, &waste, &stepsok, &hnext, iwsav, rwsav, &fail); if (fail.code != NE_NOERROR) { printf("Error from nag_ode_ivp_rkts_diag (d02ptc).\n%s\n", fail.message); exit_status = 4; goto END; } printf("Cost of the integration in evaluations of f is %6ld\n\n", fevals); } END: NAG_FREE(thresh); NAG_FREE(yinit); NAG_FREE(ygot); NAG_FREE(ypgot); NAG_FREE(rwsav); NAG_FREE(iwsav); return exit_status; } static void NAG_CALL f(double t, Integer n, const double *y, double *yp, Nag_Comm *comm) { /* Scalars */ double r; if (comm->user[0] == -1.0) { printf("(User-supplied callback f, first invocation.)\n"); comm->user[0] = 0.0; } r = sqrt(y[0]*y[0] + y[1]*y[1]); yp[0] = y[2]; yp[1] = y[3]; yp[2] = -y[0]/ pow(r, 3); yp[3] = -y[1]/ pow(r, 3); }