Language Reference

ODE Call

CALL ODE (r, "dername", c, t, h <, "jacobian"> <, eps> <, "SAS-data-set"> ) ;

This subroutine is supported by the IML procedure and the iml action.

The ODE subroutine performs numerical integration of first-order vector differential equations of the form

StartFraction d bold y Over d t EndFraction equals f left-parenthesis t comma bold y left-parenthesis t right-parenthesis right-parenthesis with bold y left-parenthesis 0 right-parenthesis equals bold c

The ODE subroutine returns the following values:

r

is a numeric matrix that contains the results of the integration over connected subintervals. The number of columns in r is equal to the number of subintervals of integration as defined by the argument t. In case of any error in the integration on any subinterval, partial results are not reported in r.

The input arguments to the ODE subroutine are as follows:

"dername"

specifies the name of a module used to evaluate the integrand.

c

specifies an initial value vector for the variable y.

t

specifies a sorted vector that describes the limits of integration over connected subintervals. The simplest form of the vector t contains only the limits of the integration on one interval. The first component of t should contain the initial value, and the second component should be the final value of the independent variable. For more advanced usage of the ODE subroutine, the vector t can contain more than two components. The components of the vector must be sorted in ascending order. Two consecutive components of the vector t are interpreted as a subinterval. The ODE subroutine reports the final result of integration at the right endpoint of each subinterval. This information is vital if f left-parenthesis dot right-parenthesis has internal points of discontinuity. To produce accurate solutions, it is essential that you provide the location of these points in the variable t. The continuity of the forcing function is vital to the internal control of error.

h

specifies a numeric vector that contains three components: the minimum allowable step size, hmin; the maximum allowable step size, hmax; and the initial step size to start the integration process, hinit.

"jacobian"

optionally specifies the name of a module that is used to evaluate the Jacobian analytically. The Jacobian is the matrix J, with

upper J Subscript i j Baseline equals StartFraction partial-differential f Subscript i Baseline Over partial-differential y Subscript j Baseline EndFraction

If the "jacobian" module is not specified, the ODE subroutine uses a finite-difference method to approximate the Jacobian. The keyword for this option is J.

eps

specifies a scalar that indicates the required accuracy. It has a default value of 1E–4. The keyword for this option is EPS.

SAS-data-set

is an optional argument that specifies the name of a valid predefined SAS data set name. The data set is used to save the successful independent and dependent variables of the integration at each step. The keyword for this option is DATA.

The ODE subroutine is an adaptive, variable-order, variable-step-size, stiff integrator based on implicit backward-difference methods. See Aiken (1985), Bickart and Picel (1973), Donelson and Hansen (1971), Gaffney (1984), and Shampine (1978). The integrator is an implicit predictor-corrector method that locally attempts to maintain the prescribed precision eps relative to

d equals max Underscript 0 less-than-or-equal-to t less-than-or-equal-to upper T Endscripts left-parenthesis double-vertical-bar y left-parenthesis t right-parenthesis double-vertical-bar Subscript normal infinity Baseline comma 1 right-parenthesis

As you can see from the expression, this quantity is dynamically updated during the integration process and can help you to understand the validity of the results reported by the subroutine.

A Linear Differential Equation

Consider the differential equation

StartFraction d y Over d t EndFraction equals minus t y with y equals 0.5 at t equals 0

The following statements attempt to find the solution at t equals 1:

/* Define the integrand */
start fun(t,y);
   v = -t*y;
   return(v);
finish;

/* Call ODE */
c   = 0.5;
t   = {0 1};
h   = {1E-12 1 1E-5};
call ode(r1, "FUN", c, t, h);
print r1[format=E21.14];

Figure 285: Solution to a Differential Equation at t equals 1

r1
3.03432290135600E-01


In this case, the integration is carried out over left-parenthesis 0 comma 1 right-parenthesis to give the value of y at t equals 1. The optional parameter eps has not been specified, so it is internally set to 1E–4. Also, the optional parameter "jacobian" has not been specified, so finite-difference methods are used to estimate the Jacobian. The accuracy of the answer can be increased by specifying eps. For example, set EPS=1E–7, as follows:

call ode(r2, "FUN", c, t, h) eps=1E-7;
print r2[format =E21.14];

Figure 286: A Solution with Increased Accuracy

r2
3.03265687354960E-01


Compare this value to 0.5 e Superscript negative 0.5 Baseline equals 3.03265329856310 normal upper E minus 01 and observe that the result is correct through the sixth decimal digit and has an error relative to 1 that is upper O left-parenthesis 1 normal upper E minus 7 right-parenthesis.

If the solution was desired at 1 and 2 with an accuracy of 1E–7, you would use the following statements:

t   = {0 1 2};
h   = {1E-12 1 1E-5};
call ode(r3, "FUN", c, t, h) eps=1E-7;
print r3[format=E21.14];

Figure 287: A Solution at Two Times

r3
3.03265687354960E-016.76677185425410E-02


Note that r3 contains the solution at t equals 1 in the first column and at t equals 2 in the second column.

A Discontinuous Forcing Function

Now consider the smoothness of the forcing function f left-parenthesis dot right-parenthesis. For the purpose of estimating errors, adaptive methods require some degree of smoothness in the function f left-parenthesis dot right-parenthesis. If this smoothness is not present in f left-parenthesis dot right-parenthesis over the interior and including the left endpoint of the subinterval, the reported result does not have the desired accuracy. The function f left-parenthesis dot right-parenthesis must be at least continuous. If the function does not meet this requirement, you should specify the discontinuity as an intermediate point. For example, consider the differential equation

StartFraction d y Over d t EndFraction equals StartLayout Enlarged left-brace 1st Row 1st Column t 2nd Column if t less-than 1 2nd Row 1st Column 0.5 t squared 2nd Column if t greater-than-or-equal-to 1 EndLayout

To find the solution at t equals 2, use the following statements:

/* Define the integrand */
start fun(t,y);
    if t < 1 then v = t;
    else v = .5*t*t;
    return(v);
finish;

c   = 0;
t   = {0 2};
h   = {1E-12 1. 1E-5};
call ode(r1, "FUN", c, t, h) eps=1E-12;
print r1[format=E21.14];

Figure 288: Numerical Solution Across a Discontinuity

r1
1.66666627900450E+00


In the preceding case, the integration is carried out over a single interval, left-parenthesis 0 comma 2 right-parenthesis. The optional parameter eps is specified to be 1E–12. The optional parameter "jacobian" is not specified, so finite-difference methods are used to estimate the Jacobian.

Note that the value of r1 does not have the required accuracy (it should contain a 12 decimal-place representation of 5/3), although no error message is produced. The reason is that the function is not continuous at the point t equals 1. Even the lowest-order method cannot produce a local reliable error estimate near the point of discontinuity. To avoid this problem, you can create subintervals so that the integration is carried out first over left-parenthesis 0 comma 1 right-parenthesis and then over (1, 2). The following statements implement this method:

c   = 0;
t   = {0 1 2};
h   = {1E-12 1 1E-5};
call ode(r2, "FUN", c, t, h) eps=1E-12;
print r2[format=E21.14];

Figure 289: Numerical Solution on Subintervals

r2
5.00000000003280E-011.66666666667280E+00


The variable r2 contains the solutions at both t equals 1 and t equals 2, and the errors are of the specified order. Although there is no interest in the solution at the point t equals 1, the advantage of specifying subintervals with no discontinuities is that the function f left-parenthesis dot right-parenthesis is infinitely differentiable in each subinterval.

A Piecewise Continuous Forcing Function

When f left-parenthesis dot right-parenthesis is continuous, the ODE subroutine can compute the integration to the specified precision, even if the function is defined piecewise. Consider the differential equation

StartFraction d y Over d t EndFraction equals StartLayout Enlarged left-brace 1st Row 1st Column t 2nd Column if t less-than 1 2nd Row 1st Column t squared 2nd Column if t greater-than-or-equal-to 1 EndLayout

The following statements finds the solution at t equals 2. Since the function f left-parenthesis dot right-parenthesis is continuous, the requirements for error control are satisfied.

/* Define the integrand */
start fun(t,y);
    if t < 1 then v = t;
    else v = t*t;
    return(v);
finish;

c   = 0.5;
t   = {0 2};
h   = {1E-12 1 1E-5};
call ode(r, "FUN", c, t, h) eps=1E-12;
print r[format=E21.14];

Figure 290: Numerical Solution Across a Discontinuity

r
3.33333333334260E+00


Comparing Numerical Integration with an Eigenvalue Decomposition

This example compares the ODE subroutine to an eigenvalue decomposition for stiff-linear systems. In the problem

StartFraction d y Over d t EndFraction equals upper A y with y left-parenthesis 0 right-parenthesis equals c

where A is a symmetric constant matrix, the solution can be written in terms of the eigenvalue decomposition as

y left-parenthesis t right-parenthesis equals upper U e Superscript upper D t Baseline upper U prime c

where U is the matrix of eigenvectors and D is a diagonal matrix with the eigenvalues on its diagonal.

The following statements produce two solutions, one by using the ODE subroutine and the other by using the eigenvalue decomposition:

/* Define the integrand */
start fun(t,x) global(a,count);
   count = count+1;
   v = a*x;
   return(v);
finish;

/* Define the Jacobian */
start jac(t,x) global(a);
   return(a);
finish;

a = {-1000 -1 -2 -3,
        -1 -2  3 -1,
        -2  3 -4 -3,
        -3 -1 -3 -5 };

count = 0;
t = {0 1 2};
h = {1E-12  1 1E-5};
eps = 1E-9;
c = {1, 0, 0, 0 };
call ode(z, "FUN", c, t, h)  eps=eps j="JAC";
print z[format=E21.14];
print count;

Figure 291: Numerical Integration of a Linear System

z
1.85787365333640E-066.58581420034180E-06
-1.76251618648790E-03-6.35540479984040E-03
-1.56685608330670E-03-5.72429355265880E-03
1.01207978487990E-033.73655984591000E-03

count
437


/* Do the eigenvalue decomposition */
start eval(t) global(d,u,c);
   v = u*diag(exp(d*t))*u`*c;
   return(v);
finish;

call eigen(d,u,a);
free z1;
do i = 1 to nrow(t)*ncol(t)-1;
   z1 = z1 || (eval(t[i+1]));
end;
print z1[format=E21.14];

Figure 292: Analytic Solution of a Linear System

z1
1.85787839378790E-066.58580950203100E-06
-1.76251639451240E-03-6.35540294085950E-03
-1.56685625917160E-03-5.72429205508360E-03
1.01207878768820E-033.73655890904710E-03


Is this an upper O left-parenthesis 1 normal upper E minus 9 right-parenthesis result? Note that for the problem

d equals max Underscript 0 less-than-or-equal-to t less-than-or-equal-to upper T Endscripts left-parenthesis double-vertical-bar y left-parenthesis t right-parenthesis double-vertical-bar Subscript normal infinity Baseline comma 1 right-parenthesis equals 1

with the 1E–6 result, the ODE subroutine should attempt to maintain an accuracy of 1E–9 relative to 1. Therefore, the 1E–6 result should have almost three correct decimal places. At t equals 2, the first component of z is 6.58597048842310E–06, while its more accurate value is 6.58580950203220E–06, showing an upper O left-parenthesis 1 normal upper E minus 10 right-parenthesis error.

Troubleshooting

The ODE subroutine can fail for problems with unusual qualitative properties, such as finite escape time in the interval of integration (that is, the solution goes towards infinity at some finite time). In such cases, try testing with different subintervals and different levels of accuracy to gain some qualitative information about the behavior of the solution of the differential equation.

Last updated: May 07, 2026