Integer type:  int32  int64  nag_int  show int32  show int32  show int64  show int64  show nag_int  show nag_int

Chapter Contents
Chapter Introduction
NAG Toolbox

# NAG Toolbox: nag_ode_ivp_rkm_zero_simple (d02bh)

## Purpose

nag_ode_ivp_rkm_zero_simple (d02bh) integrates a system of first-order ordinary differential equations over an interval with suitable initial conditions, using a Runge–Kutta–Merson method, until a user-specified function of the solution is zero.

## Syntax

[x, y, tol, ifail] = d02bh(x, xend, y, tol, irelab, hmax, fcn, g, 'n', n)
[x, y, tol, ifail] = nag_ode_ivp_rkm_zero_simple(x, xend, y, tol, irelab, hmax, fcn, g, 'n', n)

## Description

nag_ode_ivp_rkm_zero_simple (d02bh) advances the solution of a system of ordinary differential equations
 $yi′=fix,y1,y2,…,yn, i=1,2,…,n,$
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 Arguments), 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).

## References

Hall G and Watt J M (ed.) (1976) Modern Numerical Methods for Ordinary Differential Equations Clarendon Press, Oxford

## Parameters

### Compulsory Input Parameters

1:     $\mathrm{x}$ – double scalar
Must be set to the initial value of the independent variable $x$.
2:     $\mathrm{xend}$ – double scalar
The final value of the independent variable $x$.
If ${\mathbf{xend}}<{\mathbf{x}}$ on entry, integration proceeds in a negative direction.
3:     $\mathrm{y}\left({\mathbf{n}}\right)$ – double array
The initial values of the solution ${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$.
4:     $\mathrm{tol}$ – double scalar
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$.
nag_ode_ivp_rkm_zero_simple (d02bh) 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 nag_ode_ivp_rkm_zero_simple (d02bh) 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 nag_ode_ivp_rkm_zero_simple (d02bh) with ${\mathbf{tol}}={10.0}^{-p}$ and ${\mathbf{tol}}={10.0}^{-p-1}$ if $p$ correct decimal digits in the solution are required.
Constraint: ${\mathbf{tol}}>0.0$.
5:     $\mathrm{irelab}$int64int32nag_int scalar
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}}×\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}}×\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, then set ${\mathbf{irelab}}=1$ on entry, whereas if the error requirement is in terms of the number of correct significant digits, then 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$.
6:     $\mathrm{hmax}$ – double scalar
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, then 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, then the choice ${\mathbf{hmax}}=0.0$ is most appropriate.
7:     $\mathrm{fcn}$ – function handle or string containing name of m-file
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}}$.
[f] = fcn(x, y)

Input Parameters

1:     $\mathrm{x}$ – double scalar
$x$, the value of the argument.
2:     $\mathrm{y}\left(:\right)$ – double array
${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$, the value of the argument.

Output Parameters

1:     $\mathrm{f}\left(:\right)$ – double array
The value of ${f}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$.
8:     $\mathrm{g}$ – function handle or string containing name of m-file
g must evaluate the function $g\left(x,y\right)$ at a specified point.
[result] = g(x, y)

Input Parameters

1:     $\mathrm{x}$ – double scalar
$x$, the value of the independent variable.
2:     $\mathrm{y}\left(:\right)$ – double array
The value of ${y}_{\mathit{i}}$, for $\mathit{i}=1,2,\dots ,\mathit{n}$.

Output Parameters

1:     $\mathrm{result}$ – double scalar
The value of $g\left(x,y\right)$ at the specified point.

### Optional Input Parameters

1:     $\mathrm{n}$int64int32nag_int scalar
Default: the dimension of the array y.
$\mathit{n}$, the number of differential equations.
Constraint: ${\mathbf{n}}>0$.

### Output Parameters

1:     $\mathrm{x}$ – double scalar
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:     $\mathrm{y}\left({\mathbf{n}}\right)$ – double array
The computed values of the solution at the final point $x={\mathbf{x}}$.
3:     $\mathrm{tol}$ – double scalar
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, then tol is returned with its sign changed. To check results returned with ${\mathbf{tol}}<0.0$, nag_ode_ivp_rkm_zero_simple (d02bh) should be called again with a positive value of tol whose magnitude is considerably smaller than that of the previous call.
4:     $\mathrm{ifail}$int64int32nag_int scalar
${\mathbf{ifail}}={\mathbf{0}}$ unless the function detects an error (see Error Indicators and Warnings).

## Error Indicators and Warnings

Errors or warnings detected by the function:
${\mathbf{ifail}}=1$
 On entry, ${\mathbf{tol}}\le 0.0$, or ${\mathbf{n}}\le 0$, or ${\mathbf{irelab}}\ne 0$, $1$ or $2$.
${\mathbf{ifail}}=2$
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 Further Comments 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$
tol is too small for nag_ode_ivp_rkm_zero_simple (d02bh) to take an initial step (see Further Comments). x and ${\mathbf{y}}\left(1\right),{\mathbf{y}}\left(2\right),\dots ,{\mathbf{y}}\left(\mathit{n}\right)$ retain their initial values.
${\mathbf{ifail}}=4$
At no point in the range x to xend did the function $g\left(x,y\right)$ change sign. It is assumed that $g\left(x,y\right)=0.0$ has no solution.
${\mathbf{ifail}}=5$ (nag_roots_contfn_brent_rcomm (c05az))
A serious error has occurred in an internal call to the specified function. Check all function calls and array dimensions. Seek expert help.
${\mathbf{ifail}}=6$
A serious error has occurred in an internal call to an integration function. Check all function calls and array dimensions. Seek expert help.
${\mathbf{ifail}}=7$
A serious error has occurred in an internal call to an interpolation function. Check all (sub)program calls and array dimensions. Seek expert help.
${\mathbf{ifail}}=-99$
${\mathbf{ifail}}=-399$
Your licence key may have expired or may not have been installed correctly.
${\mathbf{ifail}}=-999$
Dynamic memory allocation failed.

## 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.

The time taken by nag_ode_ivp_rkm_zero_simple (d02bh) 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×\mathit{n}$ where $a$ and $b$ are machine-dependent computing times.
For some problems it is possible that nag_ode_ivp_rkm_zero_simple (d02bh) 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 nag_ode_ivp_rkm_zero_simple (d02bh) 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 function, the system may be very stiff (see below) or so badly scaled that it cannot be solved to the required accuracy.
If nag_ode_ivp_rkm_zero_simple (d02bh) 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 well-behaved 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 ${\mathbf{ifail}}={\mathbf{2}}$, unless overflow occurs first. If overflow occurs using nag_ode_ivp_rkm_zero_simple (d02bh), nag_ode_ivp_rkts_onestep (d02pf) 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 function will compute in very small steps in $x$ (internally to nag_ode_ivp_rkm_zero_simple (d02bh)) 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 nag_ode_ivp_bdf_zero_simple (d02ej) which uses a Backward Differentiation Formula method. To determine whether a problem is stiff, nag_ode_ivp_rkts_range (d02pe) may be used.
For well-behaved 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 nag_ode_ivp_adams_zero_simple (d02cj) which uses an Adams' method.
For problems for which nag_ode_ivp_rkm_zero_simple (d02bh) is not sufficiently general, you should consider nag_ode_ivp_rkts_onestep (d02pf). nag_ode_ivp_rkts_onestep (d02pf) is a more general function with many facilities including a more general error control criterion. nag_ode_ivp_rkts_onestep (d02pf) can be combined with the rootfinder nag_roots_contfn_brent_rcomm (c05az) and the interpolation function nag_ode_ivp_rkts_interp (d02ps) to solve equations involving ${y}_{1},{y}_{2},\dots ,{y}_{\mathit{n}}$ and their derivatives.
nag_ode_ivp_rkm_zero_simple (d02bh) 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 Example, nag_ode_ivp_rkm_zero_simple (d02bh) 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 turning-point of ${y}_{1}$ by replacing the function $g\left(x,y\right)$ in the program by:
```function result = g(x,y)
f = d02bh_f(x,y);
result = f(1);
```
This function 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 root-finding functions as discussed above.

## Example

This example finds the value ${\mathbf{x}}>0.0$ at which $y=0.0$, where $y$, $v$, $\varphi$ are defined by
 $y′ = tan⁡ϕ v′ = -0.032tan⁡ϕv- 0.02v cos⁡ϕ ϕ′ = -0.032v2$
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−4}$ and ${\mathbf{tol}}=\text{1.0e−5}$ 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.
```function d02bh_example

fprintf('d02bh example results\n\n');

% Initial conditions and end of range
x_init = 0;
y_init = [0.5   0.5   pi/5];
xend   = 10;

% Algorithmic parameters
tol = 0.00001;
irelab = int64(0);
hmax = 0;

% Stop when y(1) = 0
m = int64(1);
val = 0;

% Integrate
[xroot, yroot, tol, ifail] = ...
d02bh(...
x_init, xend, y_init, tol, irelab, hmax, @fcn, @g);
fprintf('Root of Y(1) at %8.4f\n',xroot);
fprintf('Solution is     %9.5f %9.5f %9.5f\n',yroot);

function f = fcn(x,y)
f = zeros(3,1);
f(1) = tan(y(3));
f(2) = -0.032*tan(y(3))/y(2) - 0.02*y(2)/cos(y(3));
f(3) = -0.032/y(2)^2;

function result = g(x,y)
result = y(1);
```
```d02bh example results

Root of Y(1) at   7.2883
Solution is      -0.00000   0.47486  -0.76011
```