NAG FL Interface
d02bhf (ivp_rkm_zero_simple)
1
Purpose
d02bhf integrates a system of firstorder ordinary differential equations over an interval with suitable initial conditions, using a Runge–Kutta–Merson method, until a userspecified function of the solution is zero.
2
Specification
Fortran Interface
Subroutine d02bhf ( 
x, xend, n, y, tol, irelab, hmax, fcn, g, w, ifail) 
Integer, Intent (In) 
:: 
n, irelab 
Integer, Intent (Inout) 
:: 
ifail 
Real (Kind=nag_wp), External 
:: 
g 
Real (Kind=nag_wp), Intent (In) 
:: 
xend, hmax 
Real (Kind=nag_wp), Intent (Inout) 
:: 
x, y(n), tol 
Real (Kind=nag_wp), Intent (Out) 
:: 
w(n,7) 
External 
:: 
fcn 

C Header Interface
#include <nag.h>
void 
d02bhf_ (double *x, const double *xend, const Integer *n, double y[], double *tol, const Integer *irelab, const double *hmax, void (NAG_CALL *fcn)(const double *x, const double y[], double f[]), double (NAG_CALL *g)(const double *x, const double y[]), double w[], Integer *ifail) 

C++ Header Interface
#include <nag.h> extern "C" {
void 
d02bhf_ (double &x, const double &xend, const Integer &n, double y[], double &tol, const Integer &irelab, const double &hmax, void (NAG_CALL *fcn)(const double &x, const double y[], double f[]), double (NAG_CALL *g)(const double &x, const double y[]), double w[], Integer &ifail) 
}

The routine may be called by the names d02bhf or nagf_ode_ivp_rkm_zero_simple.
3
Description
d02bhf advances the solution of a system of ordinary differential equations
from
$x={\mathbf{x}}$ towards
$x={\mathbf{xend}}$ using a Merson form of the Runge–Kutta method. The system is defined by
fcn, which evaluates
${f}_{i}$ in terms of
$x$ and
${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$ (see
Section 5), and the values of
${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$ must be given at
$x={\mathbf{x}}$.
As the integration proceeds, a check is made on the function $g\left(x,y\right)$ specified by you, to determine an interval where it changes sign. The position of this sign change is then determined accurately by interpolating for the solution and its derivative. 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$ can be determined by searching for a change in sign in $g\left(x,y\right)$.
The accuracy of the integration and, indirectly, of the determination of the position where
$g\left(x,y\right)=0$, is controlled by
tol.
For a description of Runge–Kutta 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{x}$ – Real (Kind=nag_wp)
Input/Output

On entry: must be set to the initial value of the independent variable $x$.
On exit: the point where
$g\left(x,y\right)=0.0$ unless an error has occurred, when it contains the value of
$x$ at the error. In particular, if
$g\left(x,y\right)\ne 0.0$ anywhere on the range
x to
xend, it will contain
xend on exit.

2:
$\mathbf{xend}$ – Real (Kind=nag_wp)
Input

On entry: the final value of the independent variable
$x$.
If ${\mathbf{xend}}<{\mathbf{x}}$ on entry, integration proceeds in a negative direction.

3:
$\mathbf{n}$ – Integer
Input

On entry: $\mathit{n}$, the number of differential equations.
Constraint:
${\mathbf{n}}>0$.

4:
$\mathbf{y}\left({\mathbf{n}}\right)$ – Real (Kind=nag_wp) array
Input/Output

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

5:
$\mathbf{tol}$ – Real (Kind=nag_wp)
Input/Output

On entry: must be set to a
positive tolerance for controlling the error in the integration and in the determination of the position where
$g\left(x,y\right)=0.0$.
d02bhf has been designed so that, for most problems, a reduction in
tol leads to an approximately proportional reduction in the error in the solution obtained in the integration. The relation between changes in
tol and the error in the determination of the position where
$g\left(x,y\right)=0.0$ is less clear, but for
tol small enough the error should be approximately proportional to
tol. However, the actual relation between
tol and the accuracy cannot be guaranteed. You are strongly recommended to call
d02bhf 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 results obtained by calling
d02bhf with
${\mathbf{tol}}={10.0}^{p}$ and
${\mathbf{tol}}={10.0}^{p1}$ if
$p$ correct decimal digits in the solution are required.
Constraint:
${\mathbf{tol}}>0.0$.
On exit: normally unchanged. However if the range from
$x={\mathbf{x}}$ to the position where
$g\left(x,y\right)=0.0$ (or to the final value of
$x$ if an error occurs) is so short that a small change in
tol is unlikely to make any change in the computed solution,
tol is returned with its sign changed. To check results returned with
${\mathbf{tol}}<0.0$,
d02bhf should be called again with a positive value of
tol whose magnitude is considerably smaller than that of the previous call.

6:
$\mathbf{irelab}$ – Integer
Input

On entry: determines the type of error control. At each step in the numerical solution an estimate of the local error,
$\mathit{est}$, is made. For the current step to be accepted the following condition must be satisfied:
 ${\mathbf{irelab}}=0$
 $\mathit{est}\le {\mathbf{tol}}\times \mathrm{max}\phantom{\rule{0.125em}{0ex}}\left\{1.0,\left{y}_{1}\right,\left{y}_{2}\right,\dots ,\left{y}_{\mathit{n}}\right\right\}$;
 ${\mathbf{irelab}}=1$
 $\mathit{est}\le {\mathbf{tol}}$;
 ${\mathbf{irelab}}=2$
 $\mathit{est}\le {\mathbf{tol}}\times \mathrm{max}\phantom{\rule{0.125em}{0ex}}\left\{\epsilon ,\left{y}_{1}\right,\left{y}_{2}\right,\dots ,\left{y}_{\mathit{n}}\right\right\}$, where $\epsilon $ is machine precision.
If the appropriate condition is not satisfied, the step size is reduced and the solution 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, set ${\mathbf{irelab}}=1$ on entry, whereas if the error requirement is in terms of the number of correct significant digits, set ${\mathbf{irelab}}=2$. Where there is no preference in the choice of error test, ${\mathbf{irelab}}=0$ will result in a mixed error test. It should be borne in mind that the computed solution will be used in evaluating $g\left(x,y\right)$.
Constraint:
${\mathbf{irelab}}=0$, $1$ or $2$.

7:
$\mathbf{hmax}$ – Real (Kind=nag_wp)
Input

On entry: if
${\mathbf{hmax}}=0.0$, no special action is taken.
If
${\mathbf{hmax}}\ne 0.0$, a check is made for a change in sign of
$g\left(x,y\right)$ at steps not greater than
$\left{\mathbf{hmax}}\right$. This facility should be used if there is any chance of ‘missing’ the change in sign by checking too infrequently. For example, if two changes of sign of
$g\left(x,y\right)$ are expected within a distance
$h$, say, of each other, a suitable value for
hmax might be
${\mathbf{hmax}}=h/2$. If only one change of sign in
$g\left(x,y\right)$ is expected on the range
x to
xend, the choice
${\mathbf{hmax}}=0.0$ is most appropriate.

8:
$\mathbf{fcn}$ – Subroutine, supplied by the user.
External Procedure

fcn must evaluate the functions
${f}_{i}$ (i.e., the derivatives
${y}_{i}^{\prime}$) for given values of its arguments
$x,{y}_{1},\dots ,{y}_{\mathit{n}}$.
The specification of
fcn is:
Fortran Interface
Subroutine fcn ( 
x, y, f) 
Real (Kind=nag_wp), Intent (In) 
:: 
x, y(*) 
Real (Kind=nag_wp), Intent (Out) 
:: 
f(*) 

C Header Interface
void 
fcn_ (const double *x, const double y[], double f[]) 

C++ Header Interface
#include <nag.h> extern "C" {
void 
fcn_ (const double &x, const double y[], double f[]) 
}

In the description of the arguments of
d02bhf below,
$\mathit{n}$ denotes the value of
n in the call of
d02bhf.

1:
$\mathbf{x}$ – Real (Kind=nag_wp)
Input

On entry: $x$, the value of the argument.

2:
$\mathbf{y}\left(*\right)$ – Real (Kind=nag_wp) array
Input

On entry: ${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$, the value of the argument.

3:
$\mathbf{f}\left(*\right)$ – Real (Kind=nag_wp) array
Output

On exit: the value of
${f}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$.
fcn must either be a module subprogram USEd by, or declared as EXTERNAL in, the (sub)program from which
d02bhf is called. Arguments denoted as
Input must
not be changed by this procedure.
Note: fcn should not return floatingpoint NaN (Not a Number) or infinity values, since these are not handled by
d02bhf. If your code inadvertently
does return any NaNs or infinities,
d02bhf is likely to produce unexpected results.

9:
$\mathbf{g}$ – real (Kind=nag_wp) Function, supplied by the user.
External Procedure

g must evaluate the function
$g\left(x,y\right)$ at a specified point.
The specification of
g is:
Fortran Interface
Real (Kind=nag_wp) 
:: 
g 
Real (Kind=nag_wp), Intent (In) 
:: 
x, y(*) 

C Header Interface
double 
g_ (const double *x, const double y[]) 

C++ Header Interface
#include <nag.h> extern "C" {
double 
g_ (const double &x, const double y[]) 
}

In the description of the arguments of
d02bhf below,
$\mathit{n}$ denotes the value of
n in the call of
d02bhf.

1:
$\mathbf{x}$ – Real (Kind=nag_wp)
Input

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

2:
$\mathbf{y}\left(*\right)$ – Real (Kind=nag_wp) array
Input

On entry: the value of
${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$.
g must either be a module subprogram USEd by, or declared as EXTERNAL in, the (sub)program from which
d02bhf is called. Arguments denoted as
Input must
not be changed by this procedure.
Note: g should not return floatingpoint NaN (Not a Number) or infinity values, since these are not handled by
d02bhf. If your code inadvertently
does return any NaNs or infinities,
d02bhf is likely to produce unexpected results.

10:
$\mathbf{w}\left({\mathbf{n}},7\right)$ – Real (Kind=nag_wp) array
Workspace


11:
$\mathbf{ifail}$ – Integer
Input/Output

On entry:
ifail must be set to
$0$,
$1\text{or}1$. If you are unfamiliar with this argument you should refer to
Section 4 in the Introduction to the NAG Library FL Interface for details.
For environments where it might be inappropriate to halt program execution when an error is detected, the value
$1\text{or}1$ is recommended. If the output of error messages is undesirable, then the value
$1$ is recommended. Otherwise, if you are not familiar with this argument, the recommended value is
$0$.
When the value $\mathbf{1}\text{or}\mathbf{1}$ is used it is essential to test the value of ifail on exit.
On exit:
${\mathbf{ifail}}={\mathbf{0}}$ unless the routine detects an error or a warning has been flagged (see
Section 6).
6
Error Indicators and Warnings
If on entry
${\mathbf{ifail}}=0$ or
$1$, explanatory error messages are output on the current error message unit (as defined by
x04aaf).
Errors or warnings detected by the routine:
 ${\mathbf{ifail}}=1$

On entry, ${\mathbf{irelab}}=\u2329\mathit{\text{value}}\u232a$.
Constraint: $0\le {\mathbf{irelab}}\le 2$.
On entry, ${\mathbf{n}}=\u2329\mathit{\text{value}}\u232a$.
Constraint: ${\mathbf{n}}>0$.
On entry, ${\mathbf{tol}}=\u2329\mathit{\text{value}}\u232a$.
Constraint: ${\mathbf{tol}}>0.0$.
 ${\mathbf{ifail}}=2$

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
$x=\u2329\mathit{\text{value}}\u232a$.
With the given value of
tol, no further progress can be made across the integration range from the current point
$x={\mathbf{x}}$, or dependence of the error on
tol would be lost if further progress across the integration range were attempted (see
Section 9 for a discussion of this error exit). The components
${\mathbf{y}}\left(1\right),{\mathbf{y}}\left(2\right),\dots ,{\mathbf{y}}\left(\mathit{n}\right)$ contain the computed values of the solution at the current point
$x={\mathbf{x}}$. No point at which
$g\left(x,y\right)$ changes sign has been located up to the point
$x={\mathbf{x}}$.
 ${\mathbf{ifail}}=3$

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

No change in sign of the function $g\left(x,y\right)$ was detected in the integration range.
 ${\mathbf{ifail}}=5$

An internal error has occurred in this routine. Check the routine call and any array sizes. If the call is correct then please contact
NAG for assistance.
 ${\mathbf{ifail}}=6$

A serious error occurred in a call to the internal integrator.
The error code internally was
$\u2329\mathit{\text{value}}\u232a$. Please contact
NAG.
 ${\mathbf{ifail}}=7$

Unexpected internal error in call to interpolation routine.
The interpolation routine returned error flag $\u2329\mathit{\text{value}}\u232a$.
 ${\mathbf{ifail}}=99$
An unexpected error has been triggered by this routine. Please
contact
NAG.
See
Section 7 in the Introduction to the NAG Library FL Interface for further information.
 ${\mathbf{ifail}}=399$
Your licence key may have expired or may not have been installed correctly.
See
Section 8 in the Introduction to the NAG Library FL Interface for further information.
 ${\mathbf{ifail}}=999$
Dynamic memory allocation failed.
See
Section 9 in the Introduction to the NAG Library FL Interface for further information.
7
Accuracy
The accuracy depends on
tol, on the mathematical properties of the differential system, on the position where
$g\left(x,y\right)=0.0$ and on the method. It can be controlled by varying
tol but the approximate proportionality of the error to
tol holds only for a restricted range of values of
tol. For
tol too large, the underlying theory may break down and the result of varying
tol may be unpredictable. For
tol too small, rounding error may affect the solution significantly and an error exit with
${\mathbf{ifail}}={\mathbf{2}}$ or
${\mathbf{3}}$ is possible.
The accuracy may also be restricted by the properties of
$g\left(x,y\right)$. You should try to code
g without introducing any unnecessary cancellation errors.
8
Parallelism and Performance
d02bhf is not threaded in any implementation.
The time taken by
d02bhf depends on the complexity and mathematical properties of the system of differential equations defined by
fcn, the complexity of
g, on the range, the position of the solution and the tolerance. There is also an overhead of the form
$a+b\times \mathit{n}$ where
$a$ and
$b$ are machinedependent computing times.
For some problems it is possible that
d02bhf will return
${\mathbf{ifail}}={\mathbf{4}}$ because of inaccuracy of the computed values
y, leading to inaccuracy in the computed values of
$g\left(x,y\right)$ used in the search for the solution of
$g\left(x,y\right)=0.0$. This difficulty can be overcome by reducing
tol sufficiently, and if necessary, by choosing
hmax sufficiently small. If possible, you should choose
xend well beyond the expected point where
$g\left(x,y\right)=0.0$; for example make
$\left{\mathbf{xend}}{\mathbf{x}}\right$ about
$50\%$ larger than the expected range. As a simple check, if, with
xend fixed, a change in
tol does not lead to a significant change in
y at
xend, then inaccuracy is not a likely source of error.
If
d02bhf fails with
${\mathbf{ifail}}={\mathbf{3}}$, then it could 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 routine, the system may be very stiff (see below) or so badly scaled that it cannot be solved to the required accuracy.
If
d02bhf fails with
${\mathbf{ifail}}={\mathbf{2}}$, it is likely 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 routine will usually stop with ${\mathbf{ifail}}={\mathbf{2}}$, unless overflow occurs first. If overflow occurs using d02bhf, d02pff can be used instead to detect the increasing solution, before overflow occurs. In any case, numerical integration cannot be continued through a singularity, and analytical treatment should be considered;

(b)for ‘stiff’ equations, where the solution contains rapidly decaying components, the routine will compute in very small steps in $x$ (internally to d02bhf) to preserve stability. This will usually exhibit itself by making the computing time excessively long, or occasionally by an exit with ${\mathbf{ifail}}={\mathbf{2}}$. Merson's method is not efficient in such cases, and you should try d02ejf which uses a Backward Differentiation Formula method. To determine whether a problem is stiff, d02pef may be used.
For wellbehaved systems with no difficulties such as stiffness or singularities, the Merson method should work well for low accuracy calculations (three or four figures). For high accuracy calculations or where
fcn is costly to evaluate, Merson's method may not be appropriate and a computationally less expensive method may be
d02cjf which uses an Adams' method.
For problems for which
d02bhf is not sufficiently general, you should consider
d02pff.
d02pff is a more general routine with many facilities including a more general error control criterion.
d02pff can be combined with the rootfinder
c05azf and the interpolation routine
d02psf to solve equations involving
${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$ and their derivatives.
d02bhf can also be used to solve an equation involving
$x$,
${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$ and the derivatives of
${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$. For example in
Section 10,
d02bhf is used to find a value of
${\mathbf{x}}>0.0$ where
${\mathbf{y}}\left(1\right)=0.0$. It could instead be used to find a turningpoint of
${y}_{1}$ by replacing the function
$g\left(x,y\right)$ in the program by:
Real (kind=nag_wp) Function g(x,y)
Real (kind=nag_wp) x,y(3),f(3)
Call fcn(x,y,f)
g = f(1)
Return
End
This routine is only intended to locate the
first zero of
$g\left(x,y\right)$. If later zeros are required, you are strongly advised to construct your own more general rootfinding routines as discussed above.
10
Example
This example finds the value
${\mathbf{x}}>0.0$ at which
$y=0.0$, where
$y$,
$v$,
$\varphi $ are defined by
and where at
${\mathbf{x}}=0.0$ we are given
$y=0.5$,
$v=0.5$ and
$\varphi =\pi /5$. We write
$y={\mathbf{y}}\left(1\right)$,
$v={\mathbf{y}}\left(2\right)$ and
$\varphi ={\mathbf{y}}\left(3\right)$ and we set
${\mathbf{tol}}=\text{1.0E\u22124}$ and
${\mathbf{tol}}=\text{1.0E\u22125}$ in turn so that we can compare the solutions. We expect the solution
${\mathbf{x}}\simeq 7.3$ and so we set
${\mathbf{xend}}=10.0$ to avoid determining the solution of
$y=0.0$ too near the end of the range of integration. The initial values and range are read from a data file.
10.1
Program Text
10.2
Program Data
10.3
Program Results