```/* nag_pde_dim1_parab_fd (d03pcc) Example Program.
*
* Copyright 2020 Numerical Algorithms Group.
*
* Mark 27.1, 2020.
*/

#include <math.h>
#include <nag.h>
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL pdedef(Integer, double, double, const double[],
const double[], double[], double[], double[],
Integer *, Nag_Comm *);
static void NAG_CALL bndary(Integer, double, const double[], const double[],
Integer, double[], double[], Integer *, Nag_Comm *);
static int NAG_CALL uinit(double *, double *, Integer, Integer, double);
#ifdef __cplusplus
}
#endif

int main(void) {
const Integer npts = 20, npde = 2, neqn = npts * npde, intpts = 6, itype = 1;
const Integer nwk = (10 + 6 * npde) * neqn, lisave = neqn + 24;
const Integer lrsave = nwk + (21 + 3 * npde) * npde + 7 * npts + 54;
static double ruser[2] = {-1.0, -1.0};
Integer exit_status = 0, i, ind, it, itask, itrace, m;
double acc, alpha, hx, piby2, tout, ts;
double xout[6] = {0., .4, .6, .8, .9, 1.};
double *rsave = 0, *u = 0, *uout = 0, *x = 0;
Integer *isave = 0;
NagError fail;
Nag_Comm comm;
Nag_D03_Save saved;

INIT_FAIL(fail);

printf("nag_pde_dim1_parab_fd (d03pcc) Example Program Results\n\n");

/* For communication with user-supplied functions: */
comm.user = ruser;

/* Allocate memory */
if (!(rsave = NAG_ALLOC(lrsave, double)) ||
!(u = NAG_ALLOC(npde * npts, double)) ||
!(uout = NAG_ALLOC(npde * intpts * itype, double)) ||
!(x = NAG_ALLOC(npts, double)) || !(isave = NAG_ALLOC(lisave, Integer))) {
printf("Allocation failure\n");
exit_status = 1;
goto END;
}

acc = 0.001;
m = 1;
itrace = 0;
alpha = 1.0;
comm.p = (Pointer)&alpha;
ind = 0;

/* Set spatial mesh points */

piby2 = 0.5 * nag_math_pi;
hx = piby2 / ((double)(npts - 1));
x[0] = 0.0;
x[npts - 1] = 1.0;
for (i = 1; i < npts - 1; ++i)
x[i] = sin(hx * i);

/* Set initial conditions */

ts = 0.0;
tout = 1e-5;

printf("Accuracy requirement  = %12.5f\n", acc);
printf("Parameter alpha       = %10.3f\n\n", alpha);
printf("   t  /  x  ");

for (i = 0; i < intpts; ++i)
printf("%8.4f", xout[i]);
printf("\n");

/* Set the initial values */

uinit(u, x, npde, npts, alpha);
for (it = 0; it < 5; ++it) {
tout *= 10.0;

/* Solve for next iteration step using
* nag_pde_dim1_parab_fd (d03pcc).
* General system of parabolic PDEs, method of lines, finite
* differences, one space variable
*/
nag_pde_dim1_parab_fd(npde, m, &ts, tout, pdedef, bndary, u, npts, x, acc,
rsave, lrsave, isave, lisave, itask, itrace, 0, &ind,
&comm, &saved, &fail);

if (fail.code != NE_NOERROR) {
printf("Error from nag_pde_dim1_parab_fd (d03pcc).\n%s\n", fail.message);
exit_status = 1;
goto END;
}

/* Interpolate at required spatial points using
* nag_pde_dim1_parab_fd_interp (d03pzc).
* PDEs, spatial interpolation fo use with the suite of routines
* nag_pde_parab_1d (d03p).
*/
nag_pde_dim1_parab_fd_interp(npde, m, u, npts, x, xout, intpts, 1, uout,
&fail);

if (fail.code != NE_NOERROR) {
printf("Error from nag_pde_dim1_parab_fd_interp (d03pzc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}

printf("\n %6.4f u(1)", tout);
for (i = 0; i < intpts; ++i)
printf("%8.4f", uout[npde * i]);

printf("\n %6s u(2)", "");
for (i = 0; i < intpts; ++i)
printf("%8.4f", uout[npde * i + 1]);
printf("\n");
}

/* Print integration statistics */

printf("\n %-55s%4" NAG_IFMT "\n", "Number of integration steps in time",
isave[0]);
printf(" %-55s%4" NAG_IFMT "\n",
"Number of residual evaluations of"
" resulting ODE system",
isave[1]);
printf(" %-55s%4" NAG_IFMT "\n", "Number of Jacobian evaluations", isave[2]);
printf(" %-55s%4" NAG_IFMT "\n", "Number of iterations of nonlinear solver",
isave[4]);

END:
NAG_FREE(rsave);
NAG_FREE(u);
NAG_FREE(uout);
NAG_FREE(x);
NAG_FREE(isave);

return exit_status;
}

static int NAG_CALL uinit(double *u, double *x, Integer npde, Integer npts,
double alpha) {
Integer i;

/* Intial conditions for u1 */
for (i = 0; i < npts; ++i)
u[i * npde] = alpha * 2.0 * x[i];
/* Intial conditions for u2 */
for (i = 0; i < npts; ++i)
u[i * npde + 1] = 1.0;

return 0;
}

static void NAG_CALL pdedef(Integer npde, double t, double x, const double u[],
const double ux[], double p[], double q[],
double r[], Integer *ires, Nag_Comm *comm) {
/* PDE coefficients */

double *alpha = (double *)comm->p;

if (comm->user[0] == -1.0) {
printf("(User-supplied callback pdedef, first invocation.)\n");
comm->user[0] = 0.0;
}
/* Coefficients on first PDE */
q[0] = *alpha * 4.0 * (u[1] + x * ux[1]);
r[0] = x * ux[0];
p[0] = 0.0;
p[npde] = 0.0;
/* Coefficients on first PDE */
q[1] = 0.0;
r[1] = ux[1] - u[0] * u[1];
p[1] = 0.0;
p[1 + npde] = 1.0 - x * x;
return;
}

static void NAG_CALL bndary(Integer npde, double t, const double u[],
const double ux[], Integer ibnd, double beta[],
double gamma[], Integer *ires, Nag_Comm *comm) {
/* Boundary conditions */

if (comm->user[1] == -1.0) {
printf("(User-supplied callback bndary, first invocation.)\n");
comm->user[1] = 0.0;
}
if (ibnd == 0) {
/* u[0] = 0 */
beta[0] = 0.0;
gamma[0] = u[0];
/* ux[1] = 0 ==> 1.0*r[1] = ux[1] - u[0]*u[1] = -u[0]*u[1] */
beta[1] = 1.0;
gamma[1] = -u[0] * u[1];
} else {
/* d(x*u[0])/dx = x*ux[0] + u[0] = 0 */
beta[0] = 1.0;
gamma[0] = -u[0];
/* u[1] = 0 */
beta[1] = 0.0;
gamma[1] = u[1];
}
return;
}
```