GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DASRT.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2002-2017 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <cfloat>
28 
29 #include <sstream>
30 
31 #include "DASRT.h"
32 #include "f77-fcn.h"
33 #include "lo-error.h"
34 #include "lo-math.h"
35 #include "quit.h"
36 
37 typedef octave_idx_type (*dasrt_fcn_ptr) (const double&, const double*,
38  const double*, double*,
39  octave_idx_type&, double*,
41 
42 typedef octave_idx_type (*dasrt_jac_ptr) (const double&, const double*,
43  const double*, double*,
44  const double&, double*,
46 
48  const double&, const double*,
49  const octave_idx_type&,
50  double*, double*,
52 
53 extern "C"
54 {
55  F77_RET_T
56  F77_FUNC (ddasrt, DDASRT) (dasrt_fcn_ptr, const F77_INT&,
57  F77_DBLE&, F77_DBLE*, F77_DBLE*, const F77_DBLE&,
58  F77_INT*, const F77_DBLE*,
59  const F77_DBLE*, F77_INT&, F77_DBLE*,
60  const F77_INT&, F77_INT*,
61  const F77_INT&, F77_DBLE*,
62  F77_INT*, dasrt_jac_ptr,
63  dasrt_constr_ptr, const F77_INT&,
64  F77_INT*);
65 }
66 
70 
72 
73 static octave_idx_type
74 ddasrt_f (const double& t, const double *state, const double *deriv,
75  double *delta, octave_idx_type& ires, double *, octave_idx_type *)
76 {
77  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
78 
79  ColumnVector tmp_state (nn);
80  ColumnVector tmp_deriv (nn);
81 
82  for (octave_idx_type i = 0; i < nn; i++)
83  {
84  tmp_state(i) = state[i];
85  tmp_deriv(i) = deriv[i];
86  }
87 
88  ColumnVector tmp_fval = (*user_fsub) (tmp_state, tmp_deriv, t, ires);
89 
90  if (tmp_fval.is_empty ())
91  ires = -2;
92  else
93  {
94  for (octave_idx_type i = 0; i < nn; i++)
95  delta[i] = tmp_fval(i);
96  }
97 
98  END_INTERRUPT_WITH_EXCEPTIONS;
99 
100  return 0;
101 }
102 
104 ddasrt_j (const double& time, const double *state, const double *deriv,
105  double *pd, const double& cj, double *, octave_idx_type *)
106 {
107  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
108 
109  // FIXME: would be nice to avoid copying the data.
110 
111  ColumnVector tmp_state (nn);
112  ColumnVector tmp_deriv (nn);
113 
114  for (octave_idx_type i = 0; i < nn; i++)
115  {
116  tmp_deriv.elem (i) = deriv[i];
117  tmp_state.elem (i) = state[i];
118  }
119 
120  Matrix tmp_pd = (*user_jsub) (tmp_state, tmp_deriv, time, cj);
121 
122  for (octave_idx_type j = 0; j < nn; j++)
123  for (octave_idx_type i = 0; i < nn; i++)
124  pd[nn * j + i] = tmp_pd.elem (i, j);
125 
126  END_INTERRUPT_WITH_EXCEPTIONS;
127 
128  return 0;
129 }
130 
131 static octave_idx_type
132 ddasrt_g (const octave_idx_type& neq, const double& t, const double *state,
133  const octave_idx_type& ng, double *gout, double *, octave_idx_type *)
134 {
135  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
136 
137  octave_idx_type n = neq;
138 
139  ColumnVector tmp_state (n);
140  for (octave_idx_type i = 0; i < n; i++)
141  tmp_state(i) = state[i];
142 
143  ColumnVector tmp_fval = (*user_csub) (tmp_state, t);
144 
145  for (octave_idx_type i = 0; i < ng; i++)
146  gout[i] = tmp_fval(i);
147 
148  END_INTERRUPT_WITH_EXCEPTIONS;
149 
150  return 0;
151 }
152 
153 void
154 DASRT::integrate (double tout)
155 {
156  // I suppose this is the safe thing to do. If this is the first
157  // call, or if anything about the problem has changed, we should
158  // start completely fresh.
159 
160  if (! initialized || restart
162  {
163  integration_error = false;
164 
165  initialized = true;
166 
167  info.resize (dim_vector (15, 1));
168 
169  for (octave_idx_type i = 0; i < 15; i++)
170  info(i) = 0;
171 
172  octave_idx_type n = size ();
173 
174  nn = n;
175 
176  // DAERTFunc
177 
179 
180  if (user_csub)
181  {
182  ColumnVector tmp = (*user_csub) (x, t);
183  ng = tmp.numel ();
184  }
185  else
186  ng = 0;
187 
188  octave_idx_type maxord = maximum_order ();
189  if (maxord >= 0)
190  {
191  if (maxord > 0 && maxord < 6)
192  {
193  info(8) = 1;
194  iwork(2) = maxord;
195  }
196  else
197  {
198  (*current_liboctave_error_handler)
199  ("dassl: invalid value for maximum order");
200  integration_error = true;
201  return;
202  }
203  }
204 
205  liw = 21 + n;
206  lrw = 50 + 9*n + n*n + 3*ng;
207 
208  iwork.resize (dim_vector (liw, 1));
209  rwork.resize (dim_vector (lrw, 1));
210 
211  info(0) = 0;
212 
213  if (stop_time_set)
214  {
215  info(3) = 1;
216  rwork(0) = stop_time;
217  }
218  else
219  info(3) = 0;
220 
221  restart = false;
222 
223  // DAEFunc
224 
227 
228  if (user_fsub)
229  {
230  octave_idx_type ires = 0;
231 
232  ColumnVector fval = (*user_fsub) (x, xdot, t, ires);
233 
234  if (fval.numel () != x.numel ())
235  {
236  (*current_liboctave_error_handler)
237  ("dasrt: inconsistent sizes for state and residual vectors");
238 
239  integration_error = true;
240  return;
241  }
242  }
243  else
244  {
245  (*current_liboctave_error_handler)
246  ("dasrt: no user supplied RHS subroutine!");
247 
248  integration_error = true;
249  return;
250  }
251 
252  info(4) = user_jsub ? 1 : 0;
253 
254  DAEFunc::reset = false;
255 
256  jroot.resize (dim_vector (ng, 1), 1);
257 
258  DAERTFunc::reset = false;
259 
260  // DASRT_options
261 
262  double mss = maximum_step_size ();
263  if (mss >= 0.0)
264  {
265  rwork(1) = mss;
266  info(6) = 1;
267  }
268  else
269  info(6) = 0;
270 
271  double iss = initial_step_size ();
272  if (iss >= 0.0)
273  {
274  rwork(2) = iss;
275  info(7) = 1;
276  }
277  else
278  info(7) = 0;
279 
280  if (step_limit () >= 0)
281  {
282  info(11) = 1;
283  iwork(20) = step_limit ();
284  }
285  else
286  info(11) = 0;
287 
290 
291  octave_idx_type abs_tol_len = abs_tol.numel ();
292  octave_idx_type rel_tol_len = rel_tol.numel ();
293 
294  if (abs_tol_len == 1 && rel_tol_len == 1)
295  {
296  info.elem (1) = 0;
297  }
298  else if (abs_tol_len == n && rel_tol_len == n)
299  {
300  info.elem (1) = 1;
301  }
302  else
303  {
304  (*current_liboctave_error_handler)
305  ("dasrt: inconsistent sizes for tolerance arrays");
306 
307  integration_error = true;
308  return;
309  }
310 
311  DASRT_options::reset = false;
312  }
313 
314  double *px = x.fortran_vec ();
315  double *pxdot = xdot.fortran_vec ();
316 
317  octave_idx_type *pinfo = info.fortran_vec ();
318 
319  double *prel_tol = rel_tol.fortran_vec ();
320  double *pabs_tol = abs_tol.fortran_vec ();
321 
322  double *prwork = rwork.fortran_vec ();
323  octave_idx_type *piwork = iwork.fortran_vec ();
324 
325  octave_idx_type *pjroot = jroot.fortran_vec ();
326 
327  double *dummy = 0;
328  octave_idx_type *idummy = 0;
329 
330  F77_XFCN (ddasrt, DDASRT, (ddasrt_f, nn, t, px, pxdot, tout, pinfo,
331  prel_tol, pabs_tol, istate, prwork, lrw,
332  piwork, liw, dummy, idummy, ddasrt_j,
333  ddasrt_g, ng, pjroot));
334 
335  switch (istate)
336  {
337  case 1: // A step was successfully taken in intermediate-output
338  // mode. The code has not yet reached TOUT.
339  case 2: // The integration to TOUT was successfully completed
340  // (T=TOUT) by stepping exactly to TOUT.
341  case 3: // The integration to TOUT was successfully completed
342  // (T=TOUT) by stepping past TOUT. Y(*) is obtained by
343  // interpolation. YPRIME(*) is obtained by interpolation.
344  t = tout;
345  break;
346 
347  case 4: // The integration was successfully completed
348  // by finding one or more roots of G at T.
349  break;
350 
351  case -1: // A large amount of work has been expended.
352  case -2: // The error tolerances are too stringent.
353  case -3: // The local error test cannot be satisfied because you
354  // specified a zero component in ATOL and the
355  // corresponding computed solution component is zero.
356  // Thus, a pure relative error test is impossible for
357  // this component.
358  case -6: // DDASRT had repeated error test failures on the last
359  // attempted step.
360  case -7: // The corrector could not converge.
361  case -8: // The matrix of partial derivatives is singular.
362  case -9: // The corrector could not converge. There were repeated
363  // error test failures in this step.
364  case -10: // The corrector could not converge because IRES was
365  // equal to minus one.
366  case -11: // IRES equal to -2 was encountered and control is being
367  // returned to the calling program.
368  case -12: // DASSL failed to compute the initial YPRIME.
369  case -33: // The code has encountered trouble from which it cannot
370  // recover. A message is printed explaining the trouble
371  // and control is returned to the calling program. For
372  // example, this occurs when invalid input is detected.
373  integration_error = true;
374  break;
375 
376  default:
377  integration_error = true;
378  (*current_liboctave_error_handler)
379  ("unrecognized value of istate (= %d) returned from ddasrt",
380  istate);
381  break;
382  }
383 }
384 
387 {
389 
390  Matrix x_out;
391  Matrix xdot_out;
392  ColumnVector t_out = tout;
393 
394  octave_idx_type n_out = tout.numel ();
395  octave_idx_type n = size ();
396 
397  if (n_out > 0 && n > 0)
398  {
399  x_out.resize (n_out, n);
400  xdot_out.resize (n_out, n);
401 
402  for (octave_idx_type i = 0; i < n; i++)
403  {
404  x_out(0,i) = x(i);
405  xdot_out(0,i) = xdot(i);
406  }
407 
408  for (octave_idx_type j = 1; j < n_out; j++)
409  {
410  integrate (tout(j));
411 
412  if (integration_error)
413  {
414  retval = DASRT_result (x_out, xdot_out, t_out);
415  return retval;
416  }
417 
418  if (istate == 4)
419  t_out(j) = t;
420  else
421  t_out(j) = tout(j);
422 
423  for (octave_idx_type i = 0; i < n; i++)
424  {
425  x_out(j,i) = x(i);
426  xdot_out(j,i) = xdot(i);
427  }
428 
429  if (istate == 4)
430  {
431  x_out.resize (j+1, n);
432  xdot_out.resize (j+1, n);
433  t_out.resize (j+1);
434  break;
435  }
436  }
437  }
438 
439  retval = DASRT_result (x_out, xdot_out, t_out);
440 
441  return retval;
442 }
443 
445 DASRT::integrate (const ColumnVector& tout, const ColumnVector& tcrit)
446 {
448 
449  Matrix x_out;
450  Matrix xdot_out;
451  ColumnVector t_outs = tout;
452 
453  octave_idx_type n_out = tout.numel ();
454  octave_idx_type n = size ();
455 
456  if (n_out > 0 && n > 0)
457  {
458  x_out.resize (n_out, n);
459  xdot_out.resize (n_out, n);
460 
461  octave_idx_type n_crit = tcrit.numel ();
462 
463  if (n_crit > 0)
464  {
465  octave_idx_type i_crit = 0;
466  octave_idx_type i_out = 1;
467  double next_crit = tcrit(0);
468  double next_out;
469  while (i_out < n_out)
470  {
471  bool do_restart = false;
472 
473  next_out = tout(i_out);
474  if (i_crit < n_crit)
475  next_crit = tcrit(i_crit);
476 
477  octave_idx_type save_output;
478  double t_out;
479 
480  if (next_crit == next_out)
481  {
482  set_stop_time (next_crit);
483  t_out = next_out;
484  save_output = 1;
485  i_out++;
486  i_crit++;
487  do_restart = true;
488  }
489  else if (next_crit < next_out)
490  {
491  if (i_crit < n_crit)
492  {
493  set_stop_time (next_crit);
494  t_out = next_crit;
495  save_output = 0;
496  i_crit++;
497  do_restart = true;
498  }
499  else
500  {
501  clear_stop_time ();
502  t_out = next_out;
503  save_output = 1;
504  i_out++;
505  }
506  }
507  else
508  {
509  set_stop_time (next_crit);
510  t_out = next_out;
511  save_output = 1;
512  i_out++;
513  }
514 
515  integrate (t_out);
516 
517  if (integration_error)
518  {
519  retval = DASRT_result (x_out, xdot_out, t_outs);
520  return retval;
521  }
522 
523  if (istate == 4)
524  t_out = t;
525 
526  if (save_output)
527  {
528  for (octave_idx_type i = 0; i < n; i++)
529  {
530  x_out(i_out-1,i) = x(i);
531  xdot_out(i_out-1,i) = xdot(i);
532  }
533 
534  t_outs(i_out-1) = t_out;
535 
536  if (istate == 4)
537  {
538  x_out.resize (i_out, n);
539  xdot_out.resize (i_out, n);
540  t_outs.resize (i_out);
541  i_out = n_out;
542  }
543  }
544 
545  if (do_restart)
546  force_restart ();
547  }
548 
549  retval = DASRT_result (x_out, xdot_out, t_outs);
550  }
551  else
552  {
553  retval = integrate (tout);
554 
555  if (integration_error)
556  return retval;
557  }
558  }
559 
560  return retval;
561 }
562 
565 {
567 
568  std::ostringstream buf;
569  buf << t;
570  std::string t_curr = buf.str ();
571 
572  switch (istate)
573  {
574  case 1:
575  retval = "a step was successfully taken in intermediate-output mode.";
576  break;
577 
578  case 2:
579  retval = "integration completed by stepping exactly to TOUT";
580  break;
581 
582  case 3:
583  retval = "integration to tout completed by stepping past TOUT";
584  break;
585 
586  case 4:
587  retval = "integration completed by finding one or more roots of G at T";
588  break;
589 
590  case -1:
591  retval = std::string ("a large amount of work has been expended (t =")
592  + t_curr + ")";
593  break;
594 
595  case -2:
596  retval = "the error tolerances are too stringent";
597  break;
598 
599  case -3:
600  retval = std::string ("error weight became zero during problem. (t = ")
601  + t_curr
602  + "; solution component i vanished, and atol or atol(i) == 0)";
603  break;
604 
605  case -6:
606  retval = std::string ("repeated error test failures on the last attempted step (t = ")
607  + t_curr + ")";
608  break;
609 
610  case -7:
611  retval = std::string ("the corrector could not converge (t = ")
612  + t_curr + ")";
613  break;
614 
615  case -8:
616  retval = std::string ("the matrix of partial derivatives is singular (t = ")
617  + t_curr + ")";
618  break;
619 
620  case -9:
621  retval = std::string ("the corrector could not converge (t = ")
622  + t_curr + "; repeated test failures)";
623  break;
624 
625  case -10:
626  retval = std::string ("corrector could not converge because IRES was -1 (t = ")
627  + t_curr + ")";
628  break;
629 
630  case -11:
631  retval = std::string ("return requested in user-supplied function (t = ")
632  + t_curr + ")";
633  break;
634 
635  case -12:
636  retval = "failed to compute consistent initial conditions";
637  break;
638 
639  case -33:
640  retval = "unrecoverable error (see printed message)";
641  break;
642 
643  default:
644  retval = "unknown error state";
645  break;
646  }
647 
648  return retval;
649 }
Array< octave_idx_type > iwork
Definition: DASRT.h:114
double maximum_step_size(void) const
Definition: DASRT-opts.h:127
bool is_empty(void) const
Definition: Array.h:575
subroutine ddasrt(RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL, IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC, G, NG, JROOT)
Definition: ddasrt.f:1
octave_idx_type size(void) const
Definition: base-de.h:77
ColumnVector xdot
Definition: base-dae.h:77
F77_RET_T F77_FUNC(ddasrt, DDASRT)(dasrt_fcn_ptr
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:145
bool initialized
Definition: DASRT.h:106
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
F77_RET_T const F77_INT F77_DBLE F77_DBLE F77_DBLE const F77_DBLE F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE const F77_INT F77_INT const F77_INT F77_DBLE F77_INT const F77_INT F77_INT *static DAEFunc::DAERHSFunc user_fsub
Definition: DASRT.cc:56
octave_idx_type ng
Definition: DASRT.h:111
DAERTConstrFunc constraint_function(void) const
Definition: DAERTFunc.h:68
static DAERTFunc::DAERTConstrFunc user_csub
Definition: DASRT.cc:69
static octave_idx_type nn
Definition: DASRT.cc:71
bool integration_error
Definition: base-de.h:116
Array< double > rel_tol
Definition: DASRT.h:120
DAERHSFunc function(void) const
Definition: DAEFunc.h:73
octave_idx_type istate
Definition: base-de.h:118
Matrix(* DAEJacFunc)(const ColumnVector &x, const ColumnVector &xdot, double t, double cj)
Definition: DAEFunc.h:44
T & elem(octave_idx_type n)
Definition: Array.h:482
std::string error_message(void) const
Definition: DASRT.cc:564
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:935
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:52
DAEJacFunc jacobian_function(void) const
Definition: DAEFunc.h:82
octave_idx_type ddasrt_j(const double &time, const double *state, const double *deriv, double *pd, const double &cj, double *, octave_idx_type *)
Definition: DASRT.cc:104
octave_idx_type(* dasrt_constr_ptr)(const octave_idx_type &, const double &, const double *, const octave_idx_type &, double *, double *, octave_idx_type *)
Definition: DASRT.cc:47
static octave_idx_type ddasrt_f(const double &t, const double *state, const double *deriv, double *delta, octave_idx_type &ires, double *, octave_idx_type *)
Definition: DASRT.cc:74
bool reset
Definition: DAEFunc.h:101
virtual void force_restart(void)
Definition: base-de.h:96
void set_stop_time(double tt)
Definition: base-de.h:83
double t
Definition: base-de.h:108
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1028
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
ColumnVector(* DAERTConstrFunc)(const ColumnVector &x, double t)
Definition: DAERTFunc.h:35
Definition: dMatrix.h:37
octave_idx_type lrw
Definition: DASRT.h:109
DASRT_result integrate(const ColumnVector &tout)
Definition: DASRT.cc:386
#define F77_INT
Definition: f77-fcn.h:335
void clear_stop_time(void)
Definition: base-de.h:90
static uint32_t state[624]
Definition: randmtzig.cc:184
octave_idx_type step_limit(void) const
Definition: DASRT-opts.h:130
double stop_time
Definition: base-de.h:110
Array< double > relative_tolerance(void) const
Definition: DASRT-opts.h:118
Array< double > rwork
Definition: DASRT.h:117
ColumnVector x
Definition: base-de.h:106
octave_idx_type(* dasrt_fcn_ptr)(const double &, const double *, const double *, double *, octave_idx_type &, double *, octave_idx_type *)
Definition: DASRT.cc:37
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
Array< double > absolute_tolerance(void) const
Definition: DASRT-opts.h:115
Array< octave_idx_type > info
Definition: DASRT.h:113
Array< octave_idx_type > jroot
Definition: DASRT.h:115
octave_idx_type maximum_order(void) const
Definition: DASRT-opts.h:124
bool reset
Definition: DAERTFunc.h:86
static octave_idx_type ddasrt_g(const octave_idx_type &neq, const double &t, const double *state, const octave_idx_type &ng, double *gout, double *, octave_idx_type *)
Definition: DASRT.cc:132
double initial_step_size(void) const
Definition: DASRT-opts.h:121
octave_idx_type liw
Definition: DASRT.h:108
Array< double > abs_tol
Definition: DASRT.h:119
ColumnVector(* DAERHSFunc)(const ColumnVector &x, const ColumnVector &xdot, double t, octave_idx_type &ires)
Definition: DAEFunc.h:36
octave_idx_type(* dasrt_jac_ptr)(const double &, const double *, const double *, double *, const double &, double *, octave_idx_type *)
Definition: DASRT.cc:42
const T * fortran_vec(void) const
Definition: Array.h:584
bool restart
Definition: base-de.h:114
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
static DAEFunc::DAEJacFunc user_jsub
Definition: DASRT.cc:68
#define F77_DBLE
Definition: f77-fcn.h:331
bool stop_time_set
Definition: base-de.h:112
void resize(octave_idx_type n, const double &rfv=0)
Definition: dColVector.h:108
octave_value_list fval
Definition: ov-struct.cc:2060