/* nag_pde_parab_1d_cd_ode (d03plc) Example Program.
*
* Copyright 2014 Numerical Algorithms Group.
*
* Mark 7, 2001.
*/
#include <stdio.h>
#include <nag.h>
#include <nag_stdlib.h>
#include <nagd03.h>
#include <nagx01.h>
#include <math.h>
/* Structure to communicate with user-supplied function arguments */
struct user
{
double elo, ero, gamma, rlo, rro;
};
#ifdef __cplusplus
extern "C" {
#endif
static void NAG_CALL pdedef(Integer, double, double, const double[],
const double[], Integer, const double[],
const double[], double[], double[], double[],
double[], Integer *, Nag_Comm *);
static void NAG_CALL bndry1(Integer, Integer, double, const double[],
const double[], Integer, const double[],
const double[], Integer, double[], Integer *,
Nag_Comm *);
static void NAG_CALL bndry2(Integer, Integer, double, const double[],
const double[], Integer, const double[],
const double[], Integer, double[], Integer *,
Nag_Comm *);
static void NAG_CALL nmflx1(Integer, double, double, Integer, const double[],
const double[], const double[], double[],
Integer *, Nag_Comm *, Nag_D03_Save *);
static void NAG_CALL nmflx2(Integer, double, double, Integer, const double[],
const double[], const double[], double[],
Integer *, Nag_Comm *, Nag_D03_Save *);
static void NAG_CALL odedef(Integer, double, Integer, const double[],
const double[], Integer, const double[],
const double[], const double [], const double[],
double[], Integer *, Nag_Comm *);
#ifdef __cplusplus
}
#endif
static void init1(double, double *, Integer, double *, Integer, Integer);
static void init2(Integer, Integer, double *, double *, Nag_Comm *);
static void exact(double, double *, Integer, const double *, Integer);
static int ex1(void);
static int ex2(void);
#define P(I, J) p[npde*((J) -1)+(I) -1]
#define UCP(I, J) ucp[npde*((J) -1)+(I) -1]
#define UE(I, J) ue[npde*((J) -1)+(I) -1]
#define U(I, J) u[npde*((J) -1)+(I) -1]
#define UOUT(I, J) uout[npde*((J) -1)+(I) -1]
int main(void)
{
Integer exit_status_ex1 = 0;
Integer exit_status_ex2 = 0;
printf("nag_pde_parab_1d_cd_ode (d03plc) Example Program Results\n");
exit_status_ex1 = ex1();
exit_status_ex2 = ex2();
return (exit_status_ex1 == 0 && exit_status_ex2 == 0) ? 0: 1;
}
int ex1(void)
{
const Integer npde = 2, npts = 141, ncode = 2, nxi = 2;
const Integer neqn = npde*npts+ncode, outpts = 8, lrsave = 11000;
const Integer lisave = 15700;
static double ruser1[4] = {-1.0, -1.0, -1.0, -1.0};
double tout, ts;
Integer exit_status = 0, i, ii, ind, itask, itol, itrace, j, nop;
double *algopt = 0, *atol = 0, *rsave = 0, *rtol = 0, *u = 0, *ue = 0;
double *uout = 0, *x = 0, *xi = 0, *xout = 0;
Integer *isave = 0;
NagError fail;
Nag_Comm comm;
Nag_D03_Save saved;
INIT_FAIL(fail);
/* For communication with user-supplied functions: */
comm.user = ruser1;
printf("\n\nExample 1\n\n");
/* Allocate memory */
if (!(algopt = NAG_ALLOC(30, double)) ||
!(atol = NAG_ALLOC(1, double)) ||
!(rsave = NAG_ALLOC(lrsave, double)) ||
!(rtol = NAG_ALLOC(1, double)) ||
!(u = NAG_ALLOC(neqn, double)) ||
!(ue = NAG_ALLOC(npde*outpts, double)) ||
!(uout = NAG_ALLOC(npde*outpts, double)) ||
!(x = NAG_ALLOC(npts, double)) ||
!(xi = NAG_ALLOC(nxi, double)) ||
!(xout = NAG_ALLOC(outpts, double)) ||
!(isave = NAG_ALLOC(lisave, Integer)))
{
printf("Allocation failure\n");
exit_status = 1;
goto END;
}
itrace = 0;
itol = 1;
atol[0] = 1e-5;
rtol[0] = 2.5e-4;
printf(" npts = %4ld", npts);
printf(" atol = %12.3e", atol[0]);
printf(" rtol = %12.3e\n\n", rtol[0]);
/* Initialise mesh */
for (i = 0; i < npts; ++i) x[i] = i/(npts-1.0);
xi[0] = 0.0;
xi[1] = 1.0;
/* Set initial values */
ts = 0.0;
init1(ts, u, npde, x, npts, ncode);
ind = 0;
itask = 1;
for (i = 0; i < 30; ++i) algopt[i] = 0.0;
/* Theta integration */
algopt[0] = 1.0;
/* Sparse matrix algebra parameters */
algopt[28] = 0.1;
algopt[29] = 1.1;
tout = 0.5;
/* nag_pde_parab_1d_cd_ode (d03plc).
* General system of convection-diffusion PDEs with source
* terms in conservative form, coupled DAEs, method of
* lines, upwind scheme using numerical flux function based
* on Riemann solver, one space variable
*/
nag_pde_parab_1d_cd_ode(npde, &ts, tout, pdedef, nmflx1, bndry1, u, npts, x,
ncode, odedef, nxi, xi, neqn, rtol, atol, itol,
Nag_OneNorm, Nag_LinAlgSparse, algopt, rsave, lrsave,
isave, lisave, itask, itrace, 0, &ind, &comm,
&saved, &fail);
if (fail.code != NE_NOERROR)
{
printf("Error from nag_pde_parab_1d_cd_ode (d03plc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
/* Set output points */
nop = 0;
for (i = 0; i < npts; i += 20)
{
xout[nop] = x[i];
++nop;
}
printf(" t = %6.3f\n\n", ts);
printf(" x Approx u1 Exact u1");
printf(" Approx u2 Exact u2\n\n");
for (i = 1; i <= nop; ++i)
{
ii = (i-1)*20+1;
j = npde*(ii - 1);
UOUT(1, i) = u[j];
UOUT(2, i) = u[j + 1];
}
/* Check against exact solution */
exact(tout, ue, npde, xout, nop);
for (i = 1; i <= nop; ++i)
{
printf(" %10.4f", xout[i-1]);
printf(" %10.4f", UOUT(1, i));
printf(" %10.4f", UE(1, i));
printf(" %10.4f", UOUT(2, i));
printf(" %10.4f\n", UE(2, i));
}
printf("\n");
printf(" Number of integration steps in time = %6ld\n", isave[0]);
printf(" Number of function evaluations = %6ld\n", isave[1]);
printf(" Number of Jacobian evaluations =%6ld\n", isave[2]);
printf(" Number of iterations = %6ld\n\n", isave[4]);
END:
NAG_FREE(algopt);
NAG_FREE(atol);
NAG_FREE(rsave);
NAG_FREE(rtol);
NAG_FREE(u);
NAG_FREE(ue);
NAG_FREE(uout);
NAG_FREE(x);
NAG_FREE(xi);
NAG_FREE(xout);
NAG_FREE(isave);
return exit_status;
}
static void NAG_CALL pdedef(Integer npde, double t, double x, const double u[],
const double ux[], Integer ncode, const double v[],
const double vdot[], double p[], double c[],
double d[], double s[], Integer *ires,
Nag_Comm *comm)
{
Integer i, j;
if (comm->user[2] == -1.0)
{
printf("(User-supplied callback pdedef, first invocation.)\n");
comm->user[2] = 0.0;
}
for (i = 1; i <= npde; ++i)
{
c[i-1] = 1.0;
d[i-1] = 0.0;
s[i-1] = 0.0;
for (j = 1; j <= npde; ++j)
{
if (i == j)
{
P(i, j) = 1.0;
}
else
{
P(i, j) = 0.0;
}
}
}
return;
}
static void NAG_CALL bndry1(Integer npde, Integer npts, double t,
const double x[], const double u[], Integer ncode,
const double v[], const double vdot[],
Integer ibnd, double g[], Integer *ires,
Nag_Comm *comm)
{
double dudx;
double *ue = 0;
if (comm->user[0] == -1.0)
{
printf("(User-supplied callback bndry1, first invocation.)\n");
comm->user[0] = 0.0;
}
/* Allocate memory */
if (!(ue = NAG_ALLOC(npde, double)))
{
printf("Allocation failure\n");
goto END;
}
if (ibnd == 0)
{
exact(t, ue, npde, &x[0], 1);
g[0] = U(1, 1) + U(2, 1) - UE(1, 1) - UE(2, 1);
dudx = (U(1, 2) - U(2, 2) - U(1, 1) + U(2, 1))/(x[1] - x[0]);
g[1] = vdot[0] - dudx;
}
else
{
exact(t, ue, npde, &x[npts-1], 1);
g[0] = U(1, npts) - U(2, npts) - UE(1, 1) + UE(2, 1);
dudx = (U(1, npts) + U(2, npts) - U(1, npts-1) - U(2, npts-1))/
(x[npts-1] - x[npts-2]);
g[1] = vdot[1] + 3.0*dudx;
}
END:
NAG_FREE(ue);
return;
}
static void NAG_CALL nmflx1(Integer npde, double t, double x, Integer ncode,
const double v[], const double uleft[],
const double uright[], double flux[],
Integer *ires, Nag_Comm *comm,
Nag_D03_Save *saved)
{
if (comm->user[1] == -1.0)
{
printf("(User-supplied callback nmflx1, first invocation.)\n");
comm->user[1] = 0.0;
}
flux[0] = 0.5* (3.0*uleft[0] - uright[0] + 3.0*uleft[1] + uright[1]);
flux[1] = 0.5* (3.0*uleft[0] + uright[0] + 3.0*uleft[1] - uright[1]);
return;
}
static void NAG_CALL odedef(Integer npde, double t, Integer ncode,
const double v[], const double vdot[], Integer nxi,
const double xi[], const double ucp[],
const double ucpx[], const double ucpt[],
double r[], Integer *ires, Nag_Comm *comm)
{
if (comm->user[3] == -1.0)
{
printf("(User-supplied callback odedef, first invocation.)\n");
comm->user[3] = 0.0;
}
if (*ires == -1)
{
r[0] = 0.0;
r[1] = 0.0;
}
else
{
r[0] = v[0] - UCP(1, 1) + UCP(2, 1);
r[1] = v[1] - UCP(1, 2) - UCP(2, 2);
}
return;
}
static void exact(double t, double *u, Integer npde, const double *x,
Integer npts)
{
/* Exact solution (for comparison and b.c. purposes) */
double f, g;
Integer i;
for (i = 1; i <= npts; ++i)
{
f = exp(nag_pi* (x[i- 1] - 3.0*t))*sin(2.0*nag_pi*(x[i-1] - 3.0*t));
g = exp(-2.0*nag_pi* (x[i- 1] + t))*cos(2.0*nag_pi*(x[i-1] + t));
U(1, i) = f + g;
U(2, i) = f - g;
}
return;
}
static void init1(double t, double *u, Integer npde, double *x, Integer npts,
Integer ncode)
{
/* Initial solution */
double f, g;
Integer i, j, neqn;
neqn = npde*npts+ ncode;
j = 0;
for (i = 0; i < npts; ++i)
{
f = exp(nag_pi* (x[i] - 3.0*t))*sin(2.0*nag_pi* (x[i] - 3.0*t));
g = exp(-2.0*nag_pi* (x[i] + t))*cos(2.0*nag_pi* (x[i] + t));
u [j] = f + g;
u [j+1] = f - g;
j += 2;
}
u[neqn-2] = u[0] - u[1];
u[ neqn- 1] = u[neqn-3] + u[neqn-4];
return;
}
int ex2(void)
{
const Integer npde = 3, npts = 141, ncode = 0, nxi = 0;
const Integer neqn = npde*npts+ncode, outpts = 8, lisave = neqn+24;
const Integer lrsave = 16392;
static double ruser[2] = {-1.0, -1.0};
double d, p, tout, ts, v;
Integer exit_status = 0, i, ind, it, itask, itol, itrace, k;
double *algopt = 0, *atol = 0, *rsave = 0, *rtol = 0, *u = 0, *ue = 0;
double *x = 0, *xi = 0;
Integer *isave = 0;
NagError fail;
Nag_Comm comm;
Nag_D03_Save saved;
struct user data;
INIT_FAIL(fail);
/* For communication with user-supplied functions: */
comm.user = ruser;
printf("\n\nExample 2\n\n");
/* Allocate memory */
if (!(algopt = NAG_ALLOC(30, double)) ||
!(atol = NAG_ALLOC(1, double)) ||
!(rsave = NAG_ALLOC(lrsave, double)) ||
!(rtol = NAG_ALLOC(1, double)) ||
!(u = NAG_ALLOC(npde*npts, double)) ||
!(ue = NAG_ALLOC(npde*outpts, double)) ||
!(x = NAG_ALLOC(npts, double)) ||
!(xi = NAG_ALLOC(1, double)) ||
!(isave = NAG_ALLOC(447, Integer)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
/* Skip heading in data file */
scanf("%*[^\n] ");
/* Problem parameters */
data.elo = 2.5;
data.ero = 0.25;
data.gamma = 1.4;
data.rlo = 1.0;
data.rro = 0.125;
comm.p = (Pointer)&data;
itrace = 0;
itol = 1;
atol[0] = 0.005;
rtol[0] = 5e-4;
printf(" gamma =%6.3f", data.gamma);
printf(" elo =%6.3f", data.elo);
printf(" ero =%6.3f", data.ero);
printf(" rlo =%6.3f", data.rlo);
printf(" rro =%6.3f\n\n", data.rro);
printf(" npts = %4ld", npts);
printf(" atol = %12.3e", atol[0]);
printf(" rtol = %12.3e\n\n", rtol[0]);
/* Initialise mesh */
for (i = 0; i < npts; ++i)
x[i] = i/ (npts-1.0);
/* Initial values of variables */
init2(npde, npts, x, u, &comm);
xi [0] = 0.0;
ind = 0;
itask = 1;
for (i = 0; i < 30; ++i)
algopt[ i] = 0.0;
/* Theta integration */
algopt [0] = 2.0;
algopt [5] = 2.0;
algopt [6] = 2.0;
/* Max. time step */
algopt [12] = 0.005;
ts = 0.0;
printf(
" x APPROX d EXACT d APPROX v EXACT v APPROX p EXACT p\n");
for (it = 0; it < 2; ++it)
{
tout = 0.1* (it+1);
/* nag_pde_parab_1d_cd_ode (d03plc), see above. */
nag_pde_parab_1d_cd_ode(npde, &ts, tout, NULLFN, nmflx2, bndry2, u, npts,
x, ncode, NULLFN, nxi, xi, neqn, rtol, atol,
itol, Nag_TwoNorm, Nag_LinAlgBand, algopt, rsave,
lrsave, isave, lisave, itask, itrace, 0,
&ind, &comm, &saved, &fail);
if (fail.code != NE_NOERROR)
{
printf(
"Error from nag_pde_parab_1d_cd_ode (d03plc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}
printf("\n t = %6.3f\n\n", ts);
/* Read exact data at output points */
scanf(" %*[^\n] ");
for (i = 1; i <= 8; ++i)
{
scanf("%lf", &UE(1, i));
scanf("%lf", &UE(2, i));
scanf("%lf", &UE(3, i));
}
/* Calculate density, velocity and pressure */
k = 0;
for (i = 29; i <= npts- 14; i += 14)
{
++k;
d = U(1, i);
v = U(2, i) / d;
p = d* (data.gamma-1.0)*(U(3, i) / d - 0.5*v*v);
printf("%7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f\n",
x[i-1], d, UE(1, k), v, UE(2, k), p, UE(3, k));
}
}
printf("\n");
printf(" Number of integration steps in time = %6ld\n",
isave[0]);
printf(" Number of function evaluations = %6ld\n", isave[1]);
printf(" Number of Jacobian evaluations =%6ld\n", isave[2]);
printf(" Number of iterations = %6ld\n\n", isave[4]);
END:
NAG_FREE(algopt);
NAG_FREE(atol);
NAG_FREE(rsave);
NAG_FREE(rtol);
NAG_FREE(u);
NAG_FREE(ue);
NAG_FREE(x);
NAG_FREE(xi);
NAG_FREE(isave);
return exit_status;
}
static void init2(Integer npde, Integer npts, double *x, double *u,
Nag_Comm *comm)
{
Integer i, j;
struct user *data = (struct user *) comm->p;
j = 0;
for (i = 0; i < npts; ++i)
{
if (x [i] < 0.5)
{
u[j] = data->rlo;
u[j+1] = 0.0;
u[j+ 2] = data->elo;
}
else
if (x[i] == 0.5)
{
u[j] = 0.5*(data->rlo + data->rro);
u[ j+ 1] = 0.0;
u[ j+ 2] = 0.5*(data->elo + data->ero);
}
else
{
u[ j] = data->rro;
u [ j+ 1] = 0.0;
u [ j+ 2] = data->ero;
}
j += 3;
}
return;
}
static void NAG_CALL bndry2(Integer npde, Integer npts, double t,
const double x[], const double u[], Integer ncode,
const double v[], const double vdot[],
Integer ibnd, double g[], Integer *ires,
Nag_Comm *comm)
{
struct user *data = (struct user *) comm->p;
if (comm->user[0] == -1.0)
{
printf("(User-supplied callback bndry2, first invocation.)\n");
comm->user[0] = 0.0;
}
if (ibnd == 0)
{
g[0] = U(1, 1) - data->rlo;
g[1] = U(2, 1);
g[2] = U(3, 1) - data->elo;
}
else
{
g[0] = U(1, npts) - data->rro;
g[1] = U(2, npts);
g[2] = U(3, npts) - data->ero;
}
return;
}
static void NAG_CALL nmflx2(Integer npde, double t, double x, Integer ncode,
const double v[], const double uleft[],
const double uright[], double flux[],
Integer *ires, Nag_Comm *comm,
Nag_D03_Save *saved)
{
char solver;
NagError fail;
struct user *data = (struct user *) comm->p;
if (comm->user[1] == -1.0)
{
printf("(User-supplied callback nmflx2, first invocation.)\n");
comm->user[1] = 0.0;
}
INIT_FAIL(fail);
solver = 'R';
if (solver == 'R')
{
/* ROE SCHEME */
/* nag_pde_parab_1d_euler_roe (d03puc).
* Roe's approximate Riemann solver for Euler equations in
* conservative form, for use with nag_pde_parab_1d_cd
* (d03pfc), nag_pde_parab_1d_cd_ode (d03plc) and
* nag_pde_parab_1d_cd_ode_remesh (d03psc)
*/
nag_pde_parab_1d_euler_roe(uleft, uright, data->gamma, flux, saved,
&fail);
}
else
{
/* OSHER SCHEME */
/* nag_pde_parab_1d_euler_osher (d03pvc).
* Osher's approximate Riemann solver for Euler equations in
* conservative form, for use with nag_pde_parab_1d_cd
* (d03pfc), nag_pde_parab_1d_cd_ode (d03plc) and
* nag_pde_parab_1d_cd_ode_remesh (d03psc)
*/
nag_pde_parab_1d_euler_osher(uleft, uright, data->gamma,
Nag_OsherPhysical, flux, saved, &fail);
}
if (fail.code != NE_NOERROR)
{
printf("Error from nag_pde_parab_1d_euler_osher (d03pvc).\n%s\n",
fail.message);
}
return;
}