NAG CL Interface
d02cjc (ivp_adams_zero_simple)
1
Purpose
d02cjc integrates a system of first order ordinary differential equations over a range with suitable initial conditions, using a variableorder, variablestep Adams' method until a userspecified function, if supplied, of the solution is zero, and returns the solution at specified points, if desired.
2
Specification
void 
d02cjc (Integer neq,
void 
(*fcn)(Integer neq,
double x,
const double y[],
double f[],
Nag_User *comm),


double *x,
double y[],
double xend,
double tol,
Nag_ErrorControl err_c,
double 
(*g)(Integer neq,
double x,
const double y[],
Nag_User *comm),


Nag_User *comm,
NagError *fail) 

The function may be called by the names: d02cjc, nag_ode_ivp_adams_zero_simple or nag_ode_ivp_adams_gen.
3
Description
d02cjc advances the solution of a system of ordinary differential equations
from
$x={\mathbf{x}}$ to
$x={\mathbf{xend}}$ using a variableorder, variablestep Adams' method. The system is defined by
fcn, which evaluates
${f}_{i}$ in terms of
$x$ and
${y}_{1},{y}_{2},\dots ,{y}_{{\mathbf{neq}}}$. The initial values of
${y}_{1},{y}_{2},\dots ,{y}_{{\mathbf{neq}}}$ must be given at
$x={\mathbf{x}}$.
The solution is returned via
output at specified points, if desired: this solution is obtained by
${C}^{1}$ interpolation on solution values produced by the method. As the integration proceeds a check can be made on the userspecified function
$g\left(x,y\right)$ to determine an interval where it changes sign. The position of this sign change is then determined accurately. It is assumed that
$g\left(x,y\right)$ is a continuous function of the variables, so that a solution of
$g\left(x,y\right)=0.0$ can be determined by searching for a change in sign in
$g\left(x,y\right)$. The accuracy of the integration, the interpolation and, indirectly, of the determination of the position where
$g\left(x,y\right)=0.0$, is controlled by the arguments
tol and
err_c.
For a description of Adams' methods and their practical implementation see
Hall and Watt (1976).
4
References
Hall G and Watt J M (ed.) (1976) Modern Numerical Methods for Ordinary Differential Equations Clarendon Press, Oxford
5
Arguments

1:
$\mathbf{neq}$ – Integer
Input

On entry: the number of differential equations.
Constraint:
${\mathbf{neq}}\ge 1$.

2:
$\mathbf{fcn}$ – function, supplied by the user
External Function

fcn must evaluate the first derivatives
${y}_{i}^{\prime}$ (i.e., the functions
${f}_{i}$) for given values of their arguments
$x,{y}_{1},{y}_{2},\dots ,{y}_{{\mathbf{neq}}}$.
The specification of
fcn is:
void 
fcn (Integer neq,
double x,
const double y[],
double f[],
Nag_User *comm)



1:
$\mathbf{neq}$ – Integer
Input

On entry: the number of differential equations.

2:
$\mathbf{x}$ – double
Input

On entry: the value of the independent variable $x$.

3:
$\mathbf{y}\left[{\mathbf{neq}}\right]$ – const double
Input

On entry: ${\mathbf{y}}\left[i1\right]$ holds the value of the variable ${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,{\mathbf{neq}}$.

4:
$\mathbf{f}\left[{\mathbf{neq}}\right]$ – double
Output

On exit: ${\mathbf{f}}\left[i1\right]$ must contain the value of ${f}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,{\mathbf{neq}}$.

5:
$\mathbf{comm}$ – Nag_User *

Pointer to a structure of type Nag_User with the following member:
 p – Pointer

On entry/exit: the pointer
$\mathbf{comm}\mathbf{\to}\mathbf{p}$ should be cast to the required type, e.g.,
struct user *s = (struct user *)comm → p, to obtain the original object's address with appropriate type. (See the argument
comm below.)
Note: fcn should not return floatingpoint NaN (Not a Number) or infinity values, since these are not handled by
d02cjc. If your code inadvertently
does return any NaNs or infinities,
d02cjc is likely to produce unexpected results.

3:
$\mathbf{x}$ – double *
Input/Output

On entry: the initial value of the independent variable $x$.
Constraint:
${\mathbf{x}}\ne {\mathbf{xend}}$.
On exit: if
$g$ is supplied,
x contains the point where
$g\left(x,y\right)=0.0$, unless
$g\left(x,y\right)\ne 0.0$ anywhere on the range
x to
xend, in which case,
x will contain
xend. If
$g$ is not supplied
x contains
xend, unless an error has occurred, when it contains the value of
$x$ at the error.

4:
$\mathbf{y}\left[{\mathbf{neq}}\right]$ – double
Input/Output

On entry: the initial values of the solution ${y}_{1},{y}_{2},\dots ,{y}_{{\mathbf{neq}}}$ at $x={\mathbf{x}}$.
On exit: the computed values of the solution at the final point $x={\mathbf{x}}$.

5:
$\mathbf{xend}$ – double
Input

On entry: the final value of the independent variable.
 ${\mathbf{xend}}<{\mathbf{x}}$
 Integration proceeds in the negative direction.
Constraint:
${\mathbf{xend}}\ne {\mathbf{x}}$.

6:
$\mathbf{tol}$ – double
Input

On entry: a positive tolerance for controlling the error in the integration. Hence
tol affects the determination of the position where
$g\left(x,y\right)=0.0$, if
$g$ is supplied.
d02cjc has been designed so that, for most problems, a reduction in
tol leads to an approximately proportional reduction in the error in the solution. However, the actual relation between
tol and the accuracy achieved cannot be guaranteed. You are strongly recommended to call
d02cjc with more than one value for
tol and to compare the results obtained to estimate their accuracy. In the absence of any prior knowledge, you might compare the results obtained by calling
d02cjc with
${\mathbf{tol}}={10.0}^{p}$ and
${\mathbf{tol}}={10.0}^{p1}$ where
$p$ correct decimal digits are required in the solution.
Constraint:
${\mathbf{tol}}>0.0$.

7:
$\mathbf{err\_c}$ – Nag_ErrorControl
Input

On entry: the type of error control. At each step in the numerical solution an estimate of the local error,
est, is made. For the current step to be accepted the following condition must be satisfied:
where
${\tau}_{r}$ and
${\tau}_{a}$ are defined by
err_c 
${\tau}_{r}$ 
${\tau}_{a}$ 
$\mathrm{Nag\_Relative}$ 
tol 
$\epsilon $ 
$\mathrm{Nag\_Absolute}$ 
0.0 
tol 
$\mathrm{Nag\_Mixed}$ 
tol 
tol 
where
$\epsilon $ is a small machinedependent number and
${e}_{i}$ is an estimate of the local error at
${y}_{i}$, computed internally. If the appropriate condition is not satisfied, the step size is reduced and the solution is recomputed on the current step. If you wish to measure the error in the computed solution in terms of the number of correct decimal places, then
err_c should be set to
$\mathrm{Nag\_Absolute}$ on entry, whereas if the error requirement is in terms of the number of correct significant digits, then
err_c should be set to
$\mathrm{Nag\_Relative}$. If you prefer a mixed error test, then
err_c should be set to
$\mathrm{Nag\_Mixed}$. The recommended value for
err_c is
$\mathrm{Nag\_Mixed}$ and this should be chosen unless there are good reasons for a different choice.
Constraint:
${\mathbf{err\_c}}=\mathrm{Nag\_Relative}$, $\mathrm{Nag\_Absolute}$ or $\mathrm{Nag\_Mixed}$.

8:
$\mathbf{output}$ – function, supplied by the user
External Function

output permits access to intermediate values of the computed solution (for example to print or plot them), at successive userspecified points. It is initially called by
d02cjc with
${\mathbf{xsol}}={\mathbf{x}}$ (the initial value of
$x$). You must reset
xsol to the next point (between the current
xsol and
xend) where
output is to be called, and so on at each call to
output. If, after a call to
output, the reset point
xsol is beyond
xend,
d02cjc will integrate to
xend with no further calls to
output; if a call to
output is required at the point
${\mathbf{xsol}}={\mathbf{xend}}$, then
xsol must be given precisely the value
xend.
The specification of
output is:
void 
output (Integer neq,
double *xsol,
const double y[],
Nag_User *comm)



1:
$\mathbf{neq}$ – Integer
Input

On entry: the number of differential equations.

2:
$\mathbf{xsol}$ – double *
Input/Output

On entry: the value of the independent variable $x$.
On exit: you must set
xsol to the next value of
$x$ at which
output is to be called.

3:
$\mathbf{y}\left[{\mathbf{neq}}\right]$ – const double
Input

On entry: the computed solution at the point
xsol.

4:
$\mathbf{comm}$ – Nag_User *

Pointer to a structure of type Nag_User with the following member:
 p – Pointer

On entry/exit: the pointer
$\mathbf{comm}\mathbf{\to}\mathbf{p}$ should be cast to the required type, e.g.,
struct user *s = (struct user *)comm → p, to obtain the original object's address with appropriate type. (See the argument
comm below.)
Note: output should not return floatingpoint NaN (Not a Number) or infinity values, since these are not handled by
d02cjc. If your code inadvertently
does return any NaNs or infinities,
d02cjc is likely to produce unexpected results.
If you do not wish to access intermediate output, the actual argument
output must be the NAG defined null function pointer
NULLFN.

9:
$\mathbf{g}$ – function, supplied by the user
External Function

g must evaluate
$g\left(x,y\right)$ for specified values
$x,y$. It specifies the function
$g$ for which the first position
$x$ where
$g\left(x,y\right)=0$ is to be found.
The specification of
g is:
double 
g (Integer neq,
double x,
const double y[],
Nag_User *comm)



1:
$\mathbf{neq}$ – Integer
Input

On entry: the number of differential equations.

2:
$\mathbf{x}$ – double
Input

On entry: the value of the independent variable $x$.

3:
$\mathbf{y}\left[{\mathbf{neq}}\right]$ – const double
Input

On entry: ${\mathbf{y}}\left[i1\right]$ holds the value of the variable ${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,{\mathbf{neq}}$.

4:
$\mathbf{comm}$ – Nag_User *

Pointer to a structure of type Nag_User with the following member:
 p – Pointer

On entry/exit: the pointer
$\mathbf{comm}\mathbf{\to}\mathbf{p}$ should be cast to the required type, e.g.,
struct user *s = (struct user *)comm → p, to obtain the original object's address with appropriate type. (See the argument
comm below.)
Note: g should not return floatingpoint NaN (Not a Number) or infinity values, since these are not handled by
d02cjc. If your code inadvertently
does return any NaNs or infinities,
d02cjc is likely to produce unexpected results.
If you do not require the root finding option, the actual argument
g must be the NAG defined null double function pointer
NULLDFN.

10:
$\mathbf{comm}$ – Nag_User *

Pointer to a structure of type Nag_User with the following member:
 p – Pointer

On entry/exit: the pointer
$\mathbf{comm}\mathbf{\to}\mathbf{p}$, of type Pointer, allows you to communicate information to and from
fcn,
output and
g. An object of the required type should be declared, e.g., a structure, and its address assigned to the pointer
$\mathbf{comm}\mathbf{\to}\mathbf{p}$ by means of a cast to Pointer in the calling program. E.g.
comm.p = (Pointer)&s. The type pointer will be
void * with a C compiler that defines
void * and
char * otherwise.

11:
$\mathbf{fail}$ – NagError *
Input/Output

The NAG error argument (see
Section 7 in the Introduction to the NAG Library CL Interface).
6
Error Indicators and Warnings
 NE_2_REAL_ARG_EQ

On entry, ${\mathbf{x}}=\u2329\mathit{\text{value}}\u232a$ while ${\mathbf{xend}}=\u2329\mathit{\text{value}}\u232a$. These arguments must satisfy ${\mathbf{x}}\ne {\mathbf{xend}}$.
 NE_ALLOC_FAIL

Dynamic memory allocation failed.
 NE_BAD_PARAM

On entry, argument
err_c had an illegal value.
 NE_INT_ARG_LT

On entry, ${\mathbf{neq}}=\u2329\mathit{\text{value}}\u232a$.
Constraint: ${\mathbf{neq}}\ge 1$.
 NE_INTERNAL_ERROR

An internal error has occurred in this function. Check the function call and any array sizes. If the call is correct then please contact
NAG for assistance.
 NE_NO_SIGN_CHANGE

No change in sign of the function $g\left(x,y\right)$ was detected in the integration range.
 NE_REAL_ARG_LE

On entry,
tol must not be less than or equal to 0.0:
${\mathbf{tol}}=\u2329\mathit{\text{value}}\u232a$.
 NE_TOL_PROGRESS

The value of
tol,
$\u2329\mathit{\text{value}}\u232a$, is too small for the function to make any further progress across the integration range. Current value of
${\mathbf{x}}=\u2329\mathit{\text{value}}\u232a$.
 NE_TOL_TOO_SMALL

The value of
tol,
$\u2329\mathit{\text{value}}\u232a$, is too small for the function to take an initial step.
 NE_XSOL_INCONSIST

On call
$\u2329\mathit{\text{value}}\u232a$ to the supplied print function
xsol was set to a value behind the previous value of
xsol in the direction of integration.
Previous
${\mathbf{xsol}}=\u2329\mathit{\text{value}}\u232a$,
${\mathbf{xend}}=\u2329\mathit{\text{value}}\u232a$, new
${\mathbf{xsol}}=\u2329\mathit{\text{value}}\u232a$.
 NE_XSOL_NOT_RESET

On call
$\u2329\mathit{\text{value}}\u232a$ to the supplied print function
xsol was not reset.
 NE_XSOL_SET_WRONG

xsol was set to a value behind
x in the direction of integration by the first call to the supplied print function.
The integration range is
$\left[\u2329\mathit{value1}\u232a,\u2329\mathit{value2}\u232a\right]$,
${\mathbf{xsol}}=\u2329\mathit{\text{value}}\u232a$.
7
Accuracy
The accuracy of the computation of the solution vector
y may be controlled by varying the local error tolerance
tol. In general, a decrease in local error tolerance should lead to an increase in accuracy. You are advised to choose
${\mathbf{err\_c}}=\mathrm{Nag\_Mixed}$ unless you have a good reason for a different choice.
If the problem is a rootfinding one, then the accuracy of the root determined will depend on the properties of
$g\left(x,y\right)$. You should try to code
g without introducing any unnecessary cancellation errors.
8
Parallelism and Performance
d02cjc is not threaded in any implementation.
If more than one root is required then
d02qfc should be used.
If the function fails with error exit of
${\mathbf{fail}}\mathbf{.}\mathbf{code}={\mathbf{NE\_TOL\_TOO\_SMALL}}$, then it can be called again with a larger value of
tol if this has not already been tried. If the accuracy requested is really needed and cannot be obtained with this function, the system may be very stiff (see below) or so badly scaled that it cannot be solved to the required accuracy.
If the function fails with error exit of
${\mathbf{fail}}\mathbf{.}\mathbf{code}={\mathbf{NE\_TOL\_PROGRESS}}$, it is probable that it has been called with a value of
tol which is so small that a solution cannot be obtained on the range
x to
xend. This can happen for wellbehaved systems and very small values of
tol. You should, however, consider whether there is a more fundamental difficulty. For example:

(a)in the region of a singularity (infinite value) of the solution, the function will usually stop with error exit of ${\mathbf{fail}}\mathbf{.}\mathbf{code}={\mathbf{NE\_TOL\_PROGRESS}}$, unless overflow occurs first. Numerical integration cannot be continued through a singularity, and analytic treatment should be considered;

(b)for ‘stiff’ equations where the solution contains rapidly decaying components, the function will use very small steps in $x$ (internally to d02cjc) to preserve stability. This will exhibit itself by making the computing time excessively long, or occasionally by an exit with ${\mathbf{fail}}\mathbf{.}\mathbf{code}={\mathbf{NE\_TOL\_PROGRESS}}$. Adams' methods are not efficient in such cases.
10
Example
We illustrate the solution of four different problems. In each case the differential system (for a projectile) is
over an interval
${\mathbf{x}}=0.0$ to
${\mathbf{xend}}=10.0$ starting with values
$y=0.5$,
$v=0.5$ and
$\varphi =\pi /5$. We solve each of the following problems with local error tolerances
$\text{1.0e\u22124}$ and
$\text{1.0e\u22125}$.

(i)To integrate to $x=10.0$ producing output at intervals of 2.0 until a point is encountered where $y=0.0$.

(ii)As (i) but with no intermediate output.

(iii)As (i) but with no termination on a rootfinding condition.

(iv)As (i) but with no intermediate output and no rootfinding termination condition.
10.1
Program Text
10.2
Program Data
None.
10.3
Program Results