/* nag_ode_ivp_rkts_interp (d02psc) Example Program.
*
* Copyright 2023 Numerical Algorithms Group.
*
* Mark 29.2, 2023.
*/
#include <math.h>
#include <nag.h>
#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 2
int main(void) {
/* Scalars */
double tol0 = 1.0e-3;
Integer npts = 16, exit_status = 0;
Integer liwsav, lrwsav, lwcomm, n;
double hnext, hstart, tend, tgot, tinc, tol, tstart, twant, 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;
double *ywant = 0, *ypwant = 0, *wcomm = 0;
Integer *iwsav = 0;
char nag_enum_arg[40];
/* NAG types */
NagError fail;
Nag_RK_method method;
Nag_ErrorAssess errass;
Nag_SolDeriv reqest = Nag_SolDer;
Nag_Comm comm;
INIT_FAIL(fail);
n = N;
liwsav = 130;
lrwsav = 350 + 32 * n;
lwcomm = 6 * n;
printf("nag_ode_ivp_rkts_interp (d02psc) Example Program Results\n\n");
/* For communication with user-supplied functions: */
comm.user = ruser;
if (!(thresh = NAG_ALLOC(n, double)) || !(ygot = NAG_ALLOC(n, double)) ||
!(yinit = NAG_ALLOC(n, double)) || !(ypgot = NAG_ALLOC(n, double)) ||
!(ywant = NAG_ALLOC(n, double)) || !(ypwant = NAG_ALLOC(n, double)) ||
!(iwsav = NAG_ALLOC(liwsav, Integer)) ||
!(rwsav = NAG_ALLOC(lrwsav, double)) ||
!(wcomm = NAG_ALLOC((lwcomm), 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, &tend);
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 = (tend - tstart) / (double)(npts);
tol = tol0;
for (i = 1; i <= 2; i++) {
tol = tol * 0.1;
/* Initialize Runge-Kutta method for integrating ODE using
* nag_ode_ivp_rkts_setup (d02pqc).
*/
nag_ode_ivp_rkts_setup(n, tstart, tend, 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 y1'\n");
printf("%6.3f", tstart);
for (k = 0; k < n; k++)
printf(" %8.4f", yinit[k]);
printf("\n");
/* Set up first point at which solution is desired. */
twant = tstart + tinc;
tgot = tstart;
/* Integrate by by single steps until tend is reached or error is
* encountered. Solution is required at regular increments, requiring
* interpolation on those steps that pass over the regulat grid values
* of t.
*/
while (tgot < tend) {
/* 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;
}
/* Interpolate onto those grid values passed over in by last step. */
while (twant <= tgot) {
/* Interpolate at t = twant, given solution by
* nag_ode_ivp_rkts_onestep (d02pfc), using
* nag_ode_ivp_rkts_interp (d02psc).
*/
nag_ode_ivp_rkts_interp(n, twant, reqest, n, ywant, ypwant, f, wcomm,
lwcomm, &comm, iwsav, rwsav, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_ode_ivp_rkts_interp (d02psc).\n%s\n",
fail.message);
exit_status = 3;
goto END;
}
printf("%6.3f %8.4f %8.4f\n", twant, ywant[0], ypwant[0]);
/* Set next required solution point. */
twant = twant + tinc;
}
}
/* 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 %6" NAG_IFMT "\n\n",
fevals);
}
END:
NAG_FREE(thresh);
NAG_FREE(yinit);
NAG_FREE(ygot);
NAG_FREE(ypgot);
NAG_FREE(ywant);
NAG_FREE(ypwant);
NAG_FREE(rwsav);
NAG_FREE(iwsav);
NAG_FREE(wcomm);
return exit_status;
}
static void NAG_CALL f(double t, Integer n, const double *y, double *yp,
Nag_Comm *comm) {
if (comm->user[0] == -1.0) {
printf("(User-supplied callback f, first invocation.)\n");
comm->user[0] = 0.0;
}
yp[0] = y[1];
yp[1] = -y[0];
}