00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cfloat>
00028
00029 #include <sstream>
00030
00031 #include "DASRT.h"
00032 #include "f77-fcn.h"
00033 #include "lo-error.h"
00034 #include "lo-math.h"
00035 #include "quit.h"
00036
00037 typedef octave_idx_type (*dasrt_fcn_ptr) (const double&, const double*,
00038 const double*, double*,
00039 octave_idx_type&, double*,
00040 octave_idx_type*);
00041
00042 typedef octave_idx_type (*dasrt_jac_ptr) (const double&, const double*,
00043 const double*, double*,
00044 const double&, double*,
00045 octave_idx_type*);
00046
00047 typedef octave_idx_type (*dasrt_constr_ptr) (const octave_idx_type&,
00048 const double&, const double*,
00049 const octave_idx_type&,
00050 double*, double*,
00051 octave_idx_type*);
00052
00053 extern "C"
00054 {
00055 F77_RET_T
00056 F77_FUNC (ddasrt, DDASRT) (dasrt_fcn_ptr, const octave_idx_type&,
00057 double&, double*, double*, const double&,
00058 octave_idx_type*, const double*,
00059 const double*, octave_idx_type&, double*,
00060 const octave_idx_type&, octave_idx_type*,
00061 const octave_idx_type&, double*,
00062 octave_idx_type*, dasrt_jac_ptr,
00063 dasrt_constr_ptr, const octave_idx_type&,
00064 octave_idx_type*);
00065 }
00066
00067 static DAEFunc::DAERHSFunc user_fsub;
00068 static DAEFunc::DAEJacFunc user_jsub;
00069 static DAERTFunc::DAERTConstrFunc user_csub;
00070
00071 static octave_idx_type nn;
00072
00073 static octave_idx_type
00074 ddasrt_f (const double& t, const double *state, const double *deriv,
00075 double *delta, octave_idx_type& ires, double *, octave_idx_type *)
00076 {
00077 BEGIN_INTERRUPT_WITH_EXCEPTIONS;
00078
00079 ColumnVector tmp_state (nn);
00080 ColumnVector tmp_deriv (nn);
00081
00082 for (octave_idx_type i = 0; i < nn; i++)
00083 {
00084 tmp_state(i) = state[i];
00085 tmp_deriv(i) = deriv[i];
00086 }
00087
00088 ColumnVector tmp_fval = (*user_fsub) (tmp_state, tmp_deriv, t, ires);
00089
00090 if (tmp_fval.length () == 0)
00091 ires = -2;
00092 else
00093 {
00094 for (octave_idx_type i = 0; i < nn; i++)
00095 delta[i] = tmp_fval(i);
00096 }
00097
00098 END_INTERRUPT_WITH_EXCEPTIONS;
00099
00100 return 0;
00101 }
00102
00103 octave_idx_type
00104 ddasrt_j (const double& time, const double *state, const double *deriv,
00105 double *pd, const double& cj, double *, octave_idx_type *)
00106 {
00107 BEGIN_INTERRUPT_WITH_EXCEPTIONS;
00108
00109
00110
00111 ColumnVector tmp_state (nn);
00112 ColumnVector tmp_deriv (nn);
00113
00114 for (octave_idx_type i = 0; i < nn; i++)
00115 {
00116 tmp_deriv.elem (i) = deriv [i];
00117 tmp_state.elem (i) = state [i];
00118 }
00119
00120 Matrix tmp_pd = (*user_jsub) (tmp_state, tmp_deriv, time, cj);
00121
00122 for (octave_idx_type j = 0; j < nn; j++)
00123 for (octave_idx_type i = 0; i < nn; i++)
00124 pd [nn * j + i] = tmp_pd.elem (i, j);
00125
00126 END_INTERRUPT_WITH_EXCEPTIONS;
00127
00128 return 0;
00129 }
00130
00131 static octave_idx_type
00132 ddasrt_g (const octave_idx_type& neq, const double& t, const double *state,
00133 const octave_idx_type& ng, double *gout, double *, octave_idx_type *)
00134 {
00135 BEGIN_INTERRUPT_WITH_EXCEPTIONS;
00136
00137 octave_idx_type n = neq;
00138
00139 ColumnVector tmp_state (n);
00140 for (octave_idx_type i = 0; i < n; i++)
00141 tmp_state(i) = state[i];
00142
00143 ColumnVector tmp_fval = (*user_csub) (tmp_state, t);
00144
00145 for (octave_idx_type i = 0; i < ng; i++)
00146 gout[i] = tmp_fval(i);
00147
00148 END_INTERRUPT_WITH_EXCEPTIONS;
00149
00150 return 0;
00151 }
00152
00153 void
00154 DASRT::integrate (double tout)
00155 {
00156 DASRT_result retval;
00157
00158
00159
00160
00161
00162 if (! initialized || restart
00163 || DAEFunc::reset || DAERTFunc::reset || DASRT_options::reset)
00164 {
00165 integration_error = false;
00166
00167 initialized = true;
00168
00169 info.resize (dim_vector (15, 1));
00170
00171 for (octave_idx_type i = 0; i < 15; i++)
00172 info(i) = 0;
00173
00174 octave_idx_type n = size ();
00175
00176 nn = n;
00177
00178
00179
00180 user_csub = DAERTFunc::constraint_function ();
00181
00182 if (user_csub)
00183 {
00184 ColumnVector tmp = (*user_csub) (x, t);
00185 ng = tmp.length ();
00186 }
00187 else
00188 ng = 0;
00189
00190 octave_idx_type maxord = maximum_order ();
00191 if (maxord >= 0)
00192 {
00193 if (maxord > 0 && maxord < 6)
00194 {
00195 info(8) = 1;
00196 iwork(2) = maxord;
00197 }
00198 else
00199 {
00200 (*current_liboctave_error_handler)
00201 ("dassl: invalid value for maximum order");
00202 integration_error = true;
00203 return;
00204 }
00205 }
00206
00207 liw = 21 + n;
00208 lrw = 50 + 9*n + n*n + 3*ng;
00209
00210 iwork.resize (dim_vector (liw, 1));
00211 rwork.resize (dim_vector (lrw, 1));
00212
00213 info(0) = 0;
00214
00215 if (stop_time_set)
00216 {
00217 info(3) = 1;
00218 rwork(0) = stop_time;
00219 }
00220 else
00221 info(3) = 0;
00222
00223 restart = false;
00224
00225
00226
00227 user_fsub = DAEFunc::function ();
00228 user_jsub = DAEFunc::jacobian_function ();
00229
00230 if (user_fsub)
00231 {
00232 octave_idx_type ires = 0;
00233
00234 ColumnVector fval = (*user_fsub) (x, xdot, t, ires);
00235
00236 if (fval.length () != x.length ())
00237 {
00238 (*current_liboctave_error_handler)
00239 ("dasrt: inconsistent sizes for state and residual vectors");
00240
00241 integration_error = true;
00242 return;
00243 }
00244 }
00245 else
00246 {
00247 (*current_liboctave_error_handler)
00248 ("dasrt: no user supplied RHS subroutine!");
00249
00250 integration_error = true;
00251 return;
00252 }
00253
00254 info(4) = user_jsub ? 1 : 0;
00255
00256 DAEFunc::reset = false;
00257
00258 jroot.resize (dim_vector (ng, 1), 1);
00259
00260 DAERTFunc::reset = false;
00261
00262
00263
00264 double mss = maximum_step_size ();
00265 if (mss >= 0.0)
00266 {
00267 rwork(1) = mss;
00268 info(6) = 1;
00269 }
00270 else
00271 info(6) = 0;
00272
00273 double iss = initial_step_size ();
00274 if (iss >= 0.0)
00275 {
00276 rwork(2) = iss;
00277 info(7) = 1;
00278 }
00279 else
00280 info(7) = 0;
00281
00282 if (step_limit () >= 0)
00283 {
00284 info(11) = 1;
00285 iwork(20) = step_limit ();
00286 }
00287 else
00288 info(11) = 0;
00289
00290 abs_tol = absolute_tolerance ();
00291 rel_tol = relative_tolerance ();
00292
00293 octave_idx_type abs_tol_len = abs_tol.length ();
00294 octave_idx_type rel_tol_len = rel_tol.length ();
00295
00296 if (abs_tol_len == 1 && rel_tol_len == 1)
00297 {
00298 info.elem (1) = 0;
00299 }
00300 else if (abs_tol_len == n && rel_tol_len == n)
00301 {
00302 info.elem (1) = 1;
00303 }
00304 else
00305 {
00306 (*current_liboctave_error_handler)
00307 ("dasrt: inconsistent sizes for tolerance arrays");
00308
00309 integration_error = true;
00310 return;
00311 }
00312
00313 DASRT_options::reset = false;
00314 }
00315
00316 double *px = x.fortran_vec ();
00317 double *pxdot = xdot.fortran_vec ();
00318
00319 octave_idx_type *pinfo = info.fortran_vec ();
00320
00321 double *prel_tol = rel_tol.fortran_vec ();
00322 double *pabs_tol = abs_tol.fortran_vec ();
00323
00324 double *prwork = rwork.fortran_vec ();
00325 octave_idx_type *piwork = iwork.fortran_vec ();
00326
00327 octave_idx_type *pjroot = jroot.fortran_vec ();
00328
00329 double *dummy = 0;
00330 octave_idx_type *idummy = 0;
00331
00332 F77_XFCN (ddasrt, DDASRT, (ddasrt_f, nn, t, px, pxdot, tout, pinfo,
00333 prel_tol, pabs_tol, istate, prwork, lrw,
00334 piwork, liw, dummy, idummy, ddasrt_j,
00335 ddasrt_g, ng, pjroot));
00336
00337 switch (istate)
00338 {
00339 case 1:
00340
00341 case 2:
00342
00343 case 3:
00344
00345
00346 t = tout;
00347 break;
00348
00349 case 4:
00350
00351 break;
00352
00353 case -1:
00354 case -2:
00355 case -3:
00356
00357
00358
00359
00360 case -6:
00361
00362 case -7:
00363 case -8:
00364 case -9:
00365
00366 case -10:
00367
00368 case -11:
00369
00370 case -12:
00371 case -33:
00372
00373
00374
00375 integration_error = true;
00376 break;
00377
00378 default:
00379 integration_error = true;
00380 (*current_liboctave_error_handler)
00381 ("unrecognized value of istate (= %d) returned from ddasrt",
00382 istate);
00383 break;
00384 }
00385 }
00386
00387 DASRT_result
00388 DASRT::integrate (const ColumnVector& tout)
00389 {
00390 DASRT_result retval;
00391
00392 Matrix x_out;
00393 Matrix xdot_out;
00394 ColumnVector t_out = tout;
00395
00396 octave_idx_type n_out = tout.capacity ();
00397 octave_idx_type n = size ();
00398
00399 if (n_out > 0 && n > 0)
00400 {
00401 x_out.resize (n_out, n);
00402 xdot_out.resize (n_out, n);
00403
00404 for (octave_idx_type i = 0; i < n; i++)
00405 {
00406 x_out(0,i) = x(i);
00407 xdot_out(0,i) = xdot(i);
00408 }
00409
00410 for (octave_idx_type j = 1; j < n_out; j++)
00411 {
00412 integrate (tout(j));
00413
00414 if (integration_error)
00415 {
00416 retval = DASRT_result (x_out, xdot_out, t_out);
00417 return retval;
00418 }
00419
00420 if (istate == 4)
00421 t_out(j) = t;
00422 else
00423 t_out(j) = tout(j);
00424
00425 for (octave_idx_type i = 0; i < n; i++)
00426 {
00427 x_out(j,i) = x(i);
00428 xdot_out(j,i) = xdot(i);
00429 }
00430
00431 if (istate == 4)
00432 {
00433 x_out.resize (j+1, n);
00434 xdot_out.resize (j+1, n);
00435 t_out.resize (j+1);
00436 break;
00437 }
00438 }
00439 }
00440
00441 retval = DASRT_result (x_out, xdot_out, t_out);
00442
00443 return retval;
00444 }
00445
00446 DASRT_result
00447 DASRT::integrate (const ColumnVector& tout, const ColumnVector& tcrit)
00448 {
00449 DASRT_result retval;
00450
00451 Matrix x_out;
00452 Matrix xdot_out;
00453 ColumnVector t_outs = tout;
00454
00455 octave_idx_type n_out = tout.capacity ();
00456 octave_idx_type n = size ();
00457
00458 if (n_out > 0 && n > 0)
00459 {
00460 x_out.resize (n_out, n);
00461 xdot_out.resize (n_out, n);
00462
00463 octave_idx_type n_crit = tcrit.capacity ();
00464
00465 if (n_crit > 0)
00466 {
00467 octave_idx_type i_crit = 0;
00468 octave_idx_type i_out = 1;
00469 double next_crit = tcrit(0);
00470 double next_out;
00471 while (i_out < n_out)
00472 {
00473 bool do_restart = false;
00474
00475 next_out = tout(i_out);
00476 if (i_crit < n_crit)
00477 next_crit = tcrit(i_crit);
00478
00479 octave_idx_type save_output;
00480 double t_out;
00481
00482 if (next_crit == next_out)
00483 {
00484 set_stop_time (next_crit);
00485 t_out = next_out;
00486 save_output = 1;
00487 i_out++;
00488 i_crit++;
00489 do_restart = true;
00490 }
00491 else if (next_crit < next_out)
00492 {
00493 if (i_crit < n_crit)
00494 {
00495 set_stop_time (next_crit);
00496 t_out = next_crit;
00497 save_output = 0;
00498 i_crit++;
00499 do_restart = true;
00500 }
00501 else
00502 {
00503 clear_stop_time ();
00504 t_out = next_out;
00505 save_output = 1;
00506 i_out++;
00507 }
00508 }
00509 else
00510 {
00511 set_stop_time (next_crit);
00512 t_out = next_out;
00513 save_output = 1;
00514 i_out++;
00515 }
00516
00517 integrate (t_out);
00518
00519 if (integration_error)
00520 {
00521 retval = DASRT_result (x_out, xdot_out, t_outs);
00522 return retval;
00523 }
00524
00525 if (istate == 4)
00526 t_out = t;
00527
00528 if (save_output)
00529 {
00530 for (octave_idx_type i = 0; i < n; i++)
00531 {
00532 x_out(i_out-1,i) = x(i);
00533 xdot_out(i_out-1,i) = xdot(i);
00534 }
00535
00536 t_outs(i_out-1) = t_out;
00537
00538 if (istate == 4)
00539 {
00540 x_out.resize (i_out, n);
00541 xdot_out.resize (i_out, n);
00542 t_outs.resize (i_out);
00543 i_out = n_out;
00544 }
00545 }
00546
00547 if (do_restart)
00548 force_restart ();
00549 }
00550
00551 retval = DASRT_result (x_out, xdot_out, t_outs);
00552 }
00553 else
00554 {
00555 retval = integrate (tout);
00556
00557 if (integration_error)
00558 return retval;
00559 }
00560 }
00561
00562 return retval;
00563 }
00564
00565 std::string
00566 DASRT::error_message (void) const
00567 {
00568 std::string retval;
00569
00570 std::ostringstream buf;
00571 buf << t;
00572 std::string t_curr = buf.str ();
00573
00574 switch (istate)
00575 {
00576 case 1:
00577 retval = "a step was successfully taken in intermediate-output mode.";
00578 break;
00579
00580 case 2:
00581 retval = "integration completed by stepping exactly to TOUT";
00582 break;
00583
00584 case 3:
00585 retval = "integration to tout completed by stepping past TOUT";
00586 break;
00587
00588 case 4:
00589 retval = "integration completed by finding one or more roots of G at T";
00590 break;
00591
00592 case -1:
00593 retval = std::string ("a large amount of work has been expended (t =")
00594 + t_curr + ")";
00595 break;
00596
00597 case -2:
00598 retval = "the error tolerances are too stringent";
00599 break;
00600
00601 case -3:
00602 retval = std::string ("error weight became zero during problem. (t = ")
00603 + t_curr
00604 + "; solution component i vanished, and atol or atol(i) == 0)";
00605 break;
00606
00607 case -6:
00608 retval = std::string ("repeated error test failures on the last attempted step (t = ")
00609 + t_curr + ")";
00610 break;
00611
00612 case -7:
00613 retval = std::string ("the corrector could not converge (t = ")
00614 + t_curr + ")";
00615 break;
00616
00617 case -8:
00618 retval = std::string ("the matrix of partial derivatives is singular (t = ")
00619 + t_curr + ")";
00620 break;
00621
00622 case -9:
00623 retval = std::string ("the corrector could not converge (t = ")
00624 + t_curr + "; repeated test failures)";
00625 break;
00626
00627 case -10:
00628 retval = std::string ("corrector could not converge because IRES was -1 (t = ")
00629 + t_curr + ")";
00630 break;
00631
00632 case -11:
00633 retval = std::string ("return requested in user-supplied function (t = ")
00634 + t_curr + ")";
00635 break;
00636
00637 case -12:
00638 retval = "failed to compute consistent initial conditions";
00639 break;
00640
00641 case -33:
00642 retval = "unrecoverable error (see printed message)";
00643 break;
00644
00645 default:
00646 retval = "unknown error state";
00647 break;
00648 }
00649
00650 return retval;
00651 }