@c -*- Mode: texinfo -*-

@menu
* Introduction to ODEPACK::     
* Getting Started with ODEPACK::
* Functions and Variables for odepack::  
@end menu

@node Introduction to ODEPACK, Getting Started with ODEPACK, numericalio-pkg, odepack-pkg
@section Introduction to ODEPACK

@quotation
ODEPACK is a collection of Fortran solvers for the initial value
problem for ordinary differential equation systems.  It consists of nine
solvers, namely a basic solver called LSODE and eight variants of it --
LSODES, LSODA, LSODAR, LSODPK, LSODKR, LSODI, LSOIBT, and LSODIS.
The collection is suitable for both stiff and nonstiff systems.  It
includes solvers for systems given in explicit form, dy/dt = f(t,y),
and also solvers for systems given in linearly implicit form, 
A(t,y) dy/dt = g(t,y).  Two of the solvers use general sparse matrix
solvers for the linear systems that arise.  Two others use iterative
(preconditioned Krylov) methods instead of direct methods for these
linear systems.  The most recent addition is LSODIS, which solves
implicit problems with general sparse treatment of all matrices involved.
@end quotation
@footnote{From @url{http://netlib.org/odepack/opkd-sum}}

References:
[1] Fortran Code is from @url{http://netlib.org/odepack/}

@opencatbox
@category{Numerical methods}
@category{Share packages}
@category{Package odepack}
@closecatbox

@node Getting Started with ODEPACK, Functions and Variables for odepack, Introduction to ODEPACK, odepack-pkg
@subsection Getting Started with ODEPACK

Of the eight variants of the solver, maxima currently only has an
inteface the @code{dlsode}.

Let's say we have this sytem of equations to solve:
@example
  f1 = -.04d0*y1 + 1d4*y2*y3
  f3 = 3d7*y2*y2
  dy1/dt = f1
  dy2/dt = -f1 - f3
  dy3/dt = f3
@end example
The independent variable is t; the  dependent variables are y1, y2,
and y3, 

To start the solution, set up the differential equations to solved:
@example
load("dlsode");
f1: -.04d0*y1 + 1d4*y2*y3$
f3: 3d7*y2*y2$
f2: -f1 - f3$
fex: [f1, f2, f3];
@end example

Initialize the solver, where we have selected method 21
@example
(%i6) state : dlsode_init(fex, ['t,y1,y2,y3], 21);
(%o6) [[f, #<Function "LAMBDA ($T $Y1 $Y2 $Y3)" @{49DAC061@}>], 
[vars, [t, y1, y2, y3]], [mf, 21], [neq, 3], [lrw, 58], [liw, 23], [rwork, @{Li\
sp Array: #(0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
               0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
               0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
               0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0)@}], 
[iwork, @{Lisp Array: #(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)@}], 
[fjac, #<Function "LAMBDA ($T $Y1 $Y2 $Y3)" @{49D52AC9@}>]]
@end example
The arrays rwork and iwork carry state between calls to
@code{dlsode_step}, so they should not be modified by the user.  In
fact, this state should not be modified by the user at all.

Now that the algorithm has been initialized we can compute solutions
to the differential equation, using the @var{state} returned above.

For this example, we want to compute the solution at times
@code{0.4*10^k} for k from 0 to 11, with the initial values of 1, 0, 0
for the dependent variables and with a relative tolerance of 1d-4 and
absolute tolerances of 1e-6, 1e-10, and 1d-6 for the dependent
variables.

Then
@example
y: [1d0, 0d0, 0d0];
t: 0d0;
rtol : 1d-4;
atol: [1d-6, 1d-10, 1d-6];
istate: 1;
t:0d0;
tout:.4d0;

for k : 1 thru 12 do
  block([],
    result: dlsode_step(y, t, tout, rtol, atol, istate, state),
    printf(true, "At t = ~12,4,2e   y = ~@{~14,6,2e~@}~%", result[1], result[2]),
    istate : result[3],
    tout : tout * 10);
@end example

This produces the output:
@example
At t =   4.0000e-01   y =   9.851726e-01  3.386406e-05  1.479357e-02
At t =   4.0000e+00   y =   9.055142e-01  2.240418e-05  9.446344e-02
At t =   4.0000e+01   y =   7.158050e-01  9.184616e-06  2.841858e-01
At t =   4.0000e+02   y =   4.504846e-01  3.222434e-06  5.495122e-01
At t =   4.0000e+03   y =   1.831701e-01  8.940379e-07  8.168290e-01
At t =   4.0000e+04   y =   3.897016e-02  1.621193e-07  9.610297e-01
At t =   4.0000e+05   y =   4.935213e-03  1.983756e-08  9.950648e-01
At t =   4.0000e+06   y =   5.159269e-04  2.064759e-09  9.994841e-01
At t =   4.0000e+07   y =   5.306413e-05  2.122677e-10  9.999469e-01
At t =   4.0000e+08   y =   5.494530e-06  2.197824e-11  9.999945e-01
At t =   4.0000e+09   y =   5.129458e-07  2.051784e-12  9.999995e-01
At t =   4.0000e+10   y =  -7.170563e-08 -2.868225e-13  1.000000e+00
@end example


@node Functions and Variables for odepack, operatingsystem-pkg, Getting Started with ODEPACK, odepack-pkg
@section Functions and Variables for odepack

@deffn {Function} dlsode_init (@var{fex}, @var{vars}, @var{method})

This must be called before running the solver.  This function returns
a state object for use in the solver.  The user must not modify the
state.

The ODE to be solved is given in @var{fex}, which is a list of the
equations.  @var{vars} is a list of independent variable and the
dependent variables.  The list of dependent variables must be in the
same order as the equations if @var{fex}.  Finally, @var{method}
indicates the method to be used by the solver:

@table @code
@item 10
Nonstiff (Adams) method, no Jacobian used.
@item 21
Stiff (BDF) method, user-supplied full Jacobian.
@item 22
Stiff method, internally generated full Jacobian.
@end table

The returned state object is a list of lists.  The sublist is a list
of two elements:
@table @code
@item f
The compiled function for the ODE.
@item vars
The list independent and dependent variables (@var{vars}).
@item mf
The method to be used (@var{method}).
@item neq
The number of equations.
@item lrw
Length of the work vector for real values.
@item liw
Length of the work vector for integer values.
@item rwork
Lisp array holding the real-valued work vector.
@item iwork
Lisp array holding the integer-valued work vector.
@item fjac
Compiled analytical Jacobian of the eqations
@end table

@end deffn

@deffn {Function} dlsode_step (@var{inity}, @var{t}, @var{tout}, @var{rtol}, @var{atol}, @var{istate}, @var{state})

Performs one step of the solver, returning the values of the
independent and dependent variables, a succes or error code.

@table @code
@item inity
For the first call (when istate = 1), the initial values
@item t
Current value of the independent value
@item tout
Next point where output is desired which must not be equal to @var{t}.
@item rtol
relative tolerance parameter
@item atol
Absolute tolerance parameter, scalar of vector.  If
scalar, it applies to all dependent variables.
Otherwise it must be the tolerance for each dependent
variable.

Use @var{rtol} = 0 for pure absolute error and use @var{atol} = 0
for pure relative error.
         
@item istate
1 for the first call to dlsode, 2 for subsequent calls.
@item state
state returned by dlsode_init.
@end table

The output is a list of the following items:
@table @code
@item t
independent variable value
@item y
list of values of the dependent variables at time t.
@item istate
Integration status:
@table @code
@item 1 
no work because tout = tt
@item 2
successful result
@item -1
Excess work done on this call
@item -2
Excess accuracy requested
@item -3
Illegal input detected
@item -4
 Repeated error test failures
@item -5
Repeated convergence failures (perhaps bad Jacobian or wrong choice of
mf or tolerances)
@item -6
Error weight becase zero during problem (solution component i
vanishded and atol(i) = 0.
@end table
@item info
association list of various bits of information:
@table @code
@item n_steps
total steps taken thus far
@item n_f_eval
total number of function evals
@item n_j_eval
total number of Jacobian evals
@item method_order
method order
@item len_rwork
Actual length used for real work array
@item len_iwork
Actual length used for integer work array
@end table
@end table


@end deffn
