3
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
4
2003, 2004, 2005, 2006, 2007 John W. Eaton
6
This file is part of Octave.
8
Octave is free software; you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by the
10
Free Software Foundation; either version 3 of the License, or (at your
11
option) any later version.
13
Octave is distributed in the hope that it will be useful, but WITHOUT
14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18
You should have received a copy of the GNU General Public License
19
along with Octave; see the file COPYING. If not, see
20
<http://www.gnu.org/licenses/>.
38
typedef octave_idx_type (*lsode_fcn_ptr) (const octave_idx_type&, const double&, double*,
39
double*, octave_idx_type&);
41
typedef octave_idx_type (*lsode_jac_ptr) (const octave_idx_type&, const double&, double*,
42
const octave_idx_type&, const octave_idx_type&, double*, const
48
F77_FUNC (dlsode, DLSODE) (lsode_fcn_ptr, octave_idx_type&, double*, double&,
49
double&, octave_idx_type&, double&, const double*, octave_idx_type&,
50
octave_idx_type&, octave_idx_type&, double*, octave_idx_type&, octave_idx_type*, octave_idx_type&,
51
lsode_jac_ptr, octave_idx_type&);
54
static ODEFunc::ODERHSFunc user_fun;
55
static ODEFunc::ODEJacFunc user_jac;
56
static ColumnVector *tmp_x;
58
static octave_idx_type
59
lsode_f (const octave_idx_type& neq, const double& time, double *,
60
double *deriv, octave_idx_type& ierr)
62
BEGIN_INTERRUPT_WITH_EXCEPTIONS;
64
ColumnVector tmp_deriv;
66
// NOTE: this won't work if LSODE passes copies of the state vector.
67
// In that case we have to create a temporary vector object
70
tmp_deriv = (*user_fun) (*tmp_x, time);
72
if (tmp_deriv.length () == 0)
76
for (octave_idx_type i = 0; i < neq; i++)
77
deriv [i] = tmp_deriv.elem (i);
80
END_INTERRUPT_WITH_EXCEPTIONS;
85
static octave_idx_type
86
lsode_j (const octave_idx_type& neq, const double& time, double *,
87
const octave_idx_type&, const octave_idx_type&, double *pd, const octave_idx_type& nrowpd)
89
BEGIN_INTERRUPT_WITH_EXCEPTIONS;
91
Matrix tmp_jac (neq, neq);
93
// NOTE: this won't work if LSODE passes copies of the state vector.
94
// In that case we have to create a temporary vector object
97
tmp_jac = (*user_jac) (*tmp_x, time);
99
for (octave_idx_type j = 0; j < neq; j++)
100
for (octave_idx_type i = 0; i < neq; i++)
101
pd [nrowpd * j + i] = tmp_jac (i, j);
103
END_INTERRUPT_WITH_EXCEPTIONS;
109
LSODE::do_integrate (double tout)
113
static octave_idx_type nn = 0;
115
if (! initialized || restart || ODEFunc::reset || LSODE_options::reset)
117
integration_error = false;
123
octave_idx_type n = size ();
127
octave_idx_type max_maxord = 0;
129
if (integration_method () == "stiff")
139
lrw = 22 + n * (9 + n);
151
maxord = maximum_order ();
155
for (octave_idx_type i = 4; i < 9; i++)
160
for (octave_idx_type i = 4; i < 9; i++)
165
if (maxord > 0 && maxord <= max_maxord)
172
(*current_liboctave_error_handler)
173
("lsode: invalid value for maximum order");
174
integration_error = true;
182
rwork(0) = stop_time;
190
px = x.fortran_vec ();
192
piwork = iwork.fortran_vec ();
193
prwork = rwork.fortran_vec ();
199
// NOTE: this won't work if LSODE passes copies of the state vector.
200
// In that case we have to create a temporary vector object
205
user_fun = function ();
206
user_jac = jacobian_function ();
208
ColumnVector xdot = (*user_fun) (x, t);
210
if (x.length () != xdot.length ())
212
(*current_liboctave_error_handler)
213
("lsode: inconsistent sizes for state and derivative vectors");
215
integration_error = true;
219
ODEFunc::reset = false;
223
rel_tol = relative_tolerance ();
224
abs_tol = absolute_tolerance ();
226
octave_idx_type abs_tol_len = abs_tol.length ();
228
if (abs_tol_len == 1)
230
else if (abs_tol_len == n)
234
(*current_liboctave_error_handler)
235
("lsode: inconsistent sizes for state and absolute tolerance vectors");
237
integration_error = true;
241
double iss = initial_step_size ();
248
double maxss = maximum_step_size ();
255
double minss = minimum_step_size ();
262
octave_idx_type sl = step_limit ();
269
pabs_tol = abs_tol.fortran_vec ();
271
LSODE_options::reset = false;
274
F77_XFCN (dlsode, DLSODE, (lsode_f, nn, px, t, tout, itol, rel_tol,
275
pabs_tol, itask, istate, iopt, prwork, lrw,
276
piwork, liw, lsode_j, method_flag));
278
if (f77_exception_encountered)
280
integration_error = true;
281
(*current_liboctave_error_handler) ("unrecoverable error in lsode");
287
case 1: // prior to initial integration step.
288
case 2: // lsode was successful.
293
case -1: // excess work done on this call (perhaps wrong mf).
294
case -2: // excess accuracy requested (tolerances too small).
295
case -3: // illegal input detected (see printed message).
296
case -4: // repeated error test failures (check all inputs).
297
case -5: // repeated convergence failures (perhaps bad jacobian
298
// supplied or wrong choice of mf or tolerances).
299
case -6: // error weight became zero during problem. (solution
300
// component i vanished, and atol or atol(i) = 0.)
301
case -13: // return requested in user-supplied function.
302
integration_error = true;
306
integration_error = true;
307
(*current_liboctave_error_handler)
308
("unrecognized value of istate (= %d) returned from lsode",
318
LSODE::error_message (void) const
322
std::ostringstream buf;
324
std::string t_curr = buf.str ();
329
retval = "prior to initial integration step";
333
retval = "successful exit";
337
retval = "prior to continuation call with modified parameters";
341
retval = std::string ("excess work on this call (t = ")
342
+ t_curr + "; perhaps wrong integration method)";
346
retval = "excess accuracy requested (tolerances too small)";
350
retval = "invalid input detected (see printed message)";
354
retval = std::string ("repeated error test failures (t = ")
355
+ t_curr + "check all inputs)";
359
retval = std::string ("repeated convergence failures (t = ")
361
+ "perhaps bad jacobian supplied or wrong choice of integration method or tolerances)";
365
retval = std::string ("error weight became zero during problem. (t = ")
367
+ "; solution component i vanished, and atol or atol(i) == 0)";
371
retval = "return requested in user-supplied function (t = "
376
retval = "unknown error state";
384
LSODE::do_integrate (const ColumnVector& tout)
388
octave_idx_type n_out = tout.capacity ();
389
octave_idx_type n = size ();
391
if (n_out > 0 && n > 0)
393
retval.resize (n_out, n);
395
for (octave_idx_type i = 0; i < n; i++)
396
retval.elem (0, i) = x.elem (i);
398
for (octave_idx_type j = 1; j < n_out; j++)
400
ColumnVector x_next = do_integrate (tout.elem (j));
402
if (integration_error)
405
for (octave_idx_type i = 0; i < n; i++)
406
retval.elem (j, i) = x_next.elem (i);
414
LSODE::do_integrate (const ColumnVector& tout, const ColumnVector& tcrit)
418
octave_idx_type n_out = tout.capacity ();
419
octave_idx_type n = size ();
421
if (n_out > 0 && n > 0)
423
retval.resize (n_out, n);
425
for (octave_idx_type i = 0; i < n; i++)
426
retval.elem (0, i) = x.elem (i);
428
octave_idx_type n_crit = tcrit.capacity ();
432
octave_idx_type i_crit = 0;
433
octave_idx_type i_out = 1;
434
double next_crit = tcrit.elem (0);
436
while (i_out < n_out)
438
bool do_restart = false;
440
next_out = tout.elem (i_out);
442
next_crit = tcrit.elem (i_crit);
444
octave_idx_type save_output;
447
if (next_crit == next_out)
449
set_stop_time (next_crit);
456
else if (next_crit < next_out)
460
set_stop_time (next_crit);
476
set_stop_time (next_crit);
482
ColumnVector x_next = do_integrate (t_out);
484
if (integration_error)
489
for (octave_idx_type i = 0; i < n; i++)
490
retval.elem (i_out-1, i) = x_next.elem (i);
499
retval = do_integrate (tout);
501
if (integration_error)
510
;;; Local Variables: ***