mrgsolve
Loading...
Searching...
No Matches
lsoda_functions.h
Go to the documentation of this file.
1#include <R.h>
3
4#ifndef LSODA_FUNCTIONS_H
5#define LSODA_FUNCTIONS_H
6#define ETA 2.2204460492503131e-16
7
8void LSODA::hmax_(const double value) {
9 rworks[2] = value;
10 if(value !=0) iopt = 1;
11}
12
13void LSODA::hmin_(const double value) {
14 rworks[3] = value;
15 if(value !=0) iopt = 1;
16}
17
18void LSODA::maxsteps_(const int value) {
19 Maxsteps = value;
20 iworks[3] = value;
21 if(value !=0) iopt=1;
22}
23
24void LSODA::ixpr_(const int value) {
25 iworks[2] = value;
26 if(value!=0) iopt = 1;
27}
28
29void LSODA::mxhnil_(const int value) {
30 iworks[4] = value;
31 if(value!=0) iopt = 1;
32}
33
34void LSODA::setup_tol_vectors(const Rcpp::S4& mod) {
35 Rcpp::NumericVector xatol_ = Rcpp::as<Rcpp::NumericVector>(mod.slot("vec_atol"));
36 Rcpp::NumericVector xrtol_ = Rcpp::as<Rcpp::NumericVector>(mod.slot("vec_rtol"));
37 bool size_error = false;
38 if(static_cast<int>(xatol_.size()) != Neq) {
39 std::string size = std::to_string(xatol_.size());
40 std::string expect = std::to_string(Neq);
41 Rcpp::CharacterVector text =
42 "[lsoda] expecting atol vector with size " + expect + ", but got size " + size + ".";
43 Rcpp::message(text);
44 size_error = true;
45 }
46 if(static_cast<int>(xrtol_.size()) != Neq) {
47 std::string size = std::to_string(xrtol_.size());
48 std::string expect = std::to_string(Neq);
49 Rcpp::CharacterVector text =
50 "[lsoda] expecting rtol vector with size " + expect + ", but got size " + size + ".";
51 Rcpp::message(text);
52 size_error = true;
53 }
54 if(size_error) {
55 Rcpp::stop("itol is > 1, but atol/rtol vector(s) are not the expected size.");
56 }
57 // initialize to the default
58 atol_.assign(Neq+1,1e-8);
59 rtol_.assign(Neq+1,1e-8);
60 for(int i = 0; i < Neq; ++i) {
61 // tolerances in the solver object start at index 1
62 atol_[i+1] = xatol_[i];
63 rtol_[i+1] = xrtol_[i];
64 }
65}
66
67bool LSODA::abs_compare(double a, double b)
68{
69 return (std::abs(a) < std::abs(b));
70}
71
72/* Purpose : Find largest component of double vector dx */
73size_t LSODA::idamax1(const vector<double> &dx, const size_t n, const size_t offset = 0)
74{
75
76 double v = 0, vmax = 0;
77 size_t idmax = 1;
78 for (size_t i = 1; i <= n; ++i)
79 {
80 v = std::fabs(dx[i + offset]);
81 if (v > vmax)
82 {
83 vmax = v;
84 idmax = i;
85 }
86 }
87 return idmax;
88
89 // Following has failed with seg-fault. Probably issue with STL.
90 // return std::max_element( dx.begin()+1+offset, dx.begin()+1+n, LSODA::abs_compare) - dx.begin() - offset;
91}
92
93/* Purpose : scalar vector multiplication
94 dx = da * dx
95*/
96void LSODA::dscal1(const double da, vector<double> &dx, const size_t n,
97 const size_t offset = 0)
98{
99 std::transform(dx.begin() + 1 + offset, dx.end(), dx.begin() + 1 + offset,
100 [&da](double x) -> double { return da * x; });
101}
102
103/* Purpose : Inner product dx . dy */
104double LSODA::ddot1(const vector<double> &a, const vector<double> &b,
105 const size_t n, const size_t offsetA = 0,
106 const size_t offsetB = 0)
107{
108 double sum = 0.0;
109 for (size_t i = 1; i <= n; ++i)
110 sum += a[i + offsetA] * b[i + offsetB];
111 return sum;
112}
113
114void LSODA::daxpy1(const double da, const vector<double> &dx,
115 vector<double> &dy, const size_t n, const size_t offsetX = 0,
116 const size_t offsetY = 0)
117{
118
119 for (size_t i = 1; i <= n; ++i)
120 dy[i + offsetY] = da * dx[i + offsetX] + dy[i + offsetY];
121}
122
123// See BLAS documentation. The first argument has been changed to vector.
124void LSODA::dgesl1(const vector<vector<double>> &a, const size_t n,
125 vector<int> &ipvt, vector<double> &b, const size_t job)
126{
127 size_t k, j;
128 double t;
129
130 /*
131 Job = 0, solve a * x = b.
132 */
133 if (job == 0)
134 {
135 /*
136 First solve L * y = b.
137 */
138 for (k = 1; k <= n; ++k)
139 {
140 t = ddot1(a[k], b, k - 1);
141 b[k] = (b[k] - t) / a[k][k];
142 }
143 /*
144 Now solve U * x = y.
145 */
146 for (k = n - 1; k >= 1; k--)
147 {
148 b[k] = b[k] + ddot1(a[k], b, n - k, k, k);
149 j = ipvt[k];
150 if (j != k)
151 {
152 t = b[j];
153 b[j] = b[k];
154 b[k] = t;
155 }
156 }
157 return;
158 }
159 /*
160 Job = nonzero, solve Transpose(a) * x = b.
161
162 First solve Transpose(U) * y = b.
163 */
164 for (k = 1; k <= n - 1; ++k)
165 {
166 j = ipvt[k];
167 t = b[j];
168 if (j != k)
169 {
170 b[j] = b[k];
171 b[k] = t;
172 }
173 daxpy1(t, a[k], b, n - k, k, k);
174 }
175 /*
176 Now solve Transpose(L) * x = y.
177 */
178 for (k = n; k >= 1; k--)
179 {
180 b[k] = b[k] / a[k][k];
181 t = -b[k];
182 daxpy1(t, a[k], b, k - 1);
183 }
184}
185
186// See BLAS documentation. All double* has been changed to std::vector .
187void LSODA::dgefa1(vector<vector<double>> &a, const size_t n, vector<int> &ipvt,
188 size_t *const info)
189{
190 size_t j = 0, k = 0, i = 0;
191 double t = 0.0;
192
193 /* Gaussian elimination with partial pivoting. */
194
195 *info = 0;
196 for (k = 1; k <= n - 1; ++k)
197 {
198 /*
199 Find j = pivot index. Note that a[k]+k-1 is the address of
200 the 0-th element of the row vector whose 1st element is a[k][k].
201 */
202 j = idamax1(a[k], n - k + 1, k - 1) + k - 1;
203 ipvt[k] = j;
204 /*
205 Zero pivot implies this row already triangularized.
206 */
207 if (a[k][j] == 0.)
208 {
209 *info = k;
210 continue;
211 }
212 /*
213 Interchange if necessary.
214 */
215 if (j != k)
216 {
217 t = a[k][j];
218 a[k][j] = a[k][k];
219 a[k][k] = t;
220 }
221 /*
222 Compute multipliers.
223 */
224 t = -1. / a[k][k];
225 dscal1(t, a[k], n - k, k);
226
227 /*
228 Column elimination with row indexing.
229 */
230 for (i = k + 1; i <= n; ++i)
231 {
232 t = a[i][j];
233 if (j != k)
234 {
235 a[i][j] = a[i][k];
236 a[i][k] = t;
237 }
238 daxpy1(t, a[k], a[i], n - k, k, k);
239 }
240 } /* end k-loop */
241
242 ipvt[n] = n;
243 if (a[n][n] == 0.)
244 *info = n;
245}
246
247/* Terminate lsoda due to illegal input. */
248void LSODA::terminate(int *istate)
249{
250 if (illin == 5) {
251 // cerr << "[lsoda] repeated occurrence of illegal input. run aborted.. "
252 // "apparent infinite loop."
253 // << endl;
254 REprintf("[lsoda] repeated occurrence of illegal input. run aborted;\n");
255 REprintf(" apparent infinite loop.\n");
256 } else
257 {
258 illin++;
259 *istate = -3;
260 }
261 return;
262}
263
264/* Terminate lsoda due to various error conditions. */
265void LSODA::terminate2(vector<double> &y, double *t)
266{
267 for (size_t i = 1; i <= n; ++i)
268 y[i] = yh_[1][i];
269 *t = tn_;
270 illin = 0;
271 return;
272}
273
274/*
275 The following block handles all successful returns from lsoda.
276 If itask != 1, y is loaded from yh_ and t is set accordingly.
277 *Istate is set to 2, the illegal input counter is zeroed, and the
278 optional outputs are loaded into the work arrays before returning.
279*/
280
281void LSODA::successreturn(vector<double> &y, double *t, int itask, int ihit,
282 double tcrit, int *istate)
283{
284 for (size_t i = 1; i <= n; ++i)
285 y[i] = yh_[1][i];
286 *t = tn_;
287 if (itask == 4 || itask == 5)
288 if (ihit)
289 *t = tcrit;
290 *istate = 2;
291 illin = 0;
292}
293
294/*
295c references..
296c 1. alan c. hindmarsh, odepack, a systematized collection of ode
297c solvers, in scientific computing, r. s. stepleman et al. (eds.),
298c north-holland, amsterdam, 1983, pp. 55-64.
299c 2. linda r. petzold, automatic selection of methods for solving
300c stiff and nonstiff systems of ordinary differential equations,
301c siam j. sci. stat. comput. 4 (1983), pp. 136-148.
302c-----------------------------------------------------------------------
303*/
304
305void LSODA::stoda(const size_t neq, vector<double> &y, LSODA_ODE_SYSTEM_TYPE f,
306 dtype _data)
307{
308 //assert(neq + 1 == y.size());
309 if((neq+1) != y.size()) {
310 Rcpp::stop("[lsoda] y is not the right size in stoda.");
311 }
312
313 size_t corflag = 0, orderflag = 0;
314 size_t i = 0, i1 = 0, j = 0, m = 0, ncf = 0;
315 double del = 0.0, delp = 0.0, dsm = 0.0, dup = 0.0, exup = 0.0, r = 0.0,
316 rh = 0.0, rhup = 0.0, told = 0.0;
317 double pdh = 0.0, pnorm = 0.0;
318
319 /*
320 stoda performs one step of the integration of an initial value
321 problem for a system of ordinary differential equations.
322 Note.. stoda is independent of the value of the iteration method
323 indicator miter, when this is != 0, and hence is independent
324 of the type of chord method used, or the Jacobian structure.
325 Communication with stoda is done with the following variables:
326
327 jstart = an integer used for input only, with the following
328 values and meanings:
329
330 0 perform the first step,
331 > 0 take a new step continuing from the last,
332 -1 take the next step with a new value of h_,
333 n, meth_, miter, and/or matrix parameters.
334 -2 take the next step with a new value of h_,
335 but with other inputs unchanged.
336
337 kflag = a completion code with the following meanings:
338
339 0 the step was successful,
340 -1 the requested error could not be achieved,
341 -2 corrector convergence could not be achieved,
342 -3 fatal error in prja or solsy.
343
344 miter = corrector iteration method:
345
346 0 functional iteration,
347 >0 a chord method corresponding to jacobian type jt.
348
349 */
350 kflag = 0;
351 told = tn_;
352 ncf = 0;
353 ierpj = 0;
354 iersl = 0;
355 jcur = 0;
356 delp = 0.;
357
358 /*
359 On the first call, the order is set to 1, and other variables are
360 initialized. rmax is the maximum ratio by which h_ can be increased
361 in a single step. It is initially 1.e4 to compensate for the small
362 initial h_, but then is normally equal to 10. If a filure occurs
363 (in corrector convergence or error test), rmax is set at 2 for
364 the next increase.
365 cfode is called to get the needed coefficients for both methods.
366 */
367 if (jstart == 0)
368 {
369 lmax = maxord + 1;
370 nq = 1;
371 l = 2;
372 ialth = 2;
373 rmax = 10000.;
374 rc = 0.;
375 el0 = 1.;
376 crate = 0.7;
377 hold = h_;
378 nslp = 0;
379 ipup = miter;
380 /*
381 Initialize switching parameters. meth_ = 1 is assumed initially.
382 */
383 icount = 20;
384 irflag = 0;
385 pdest = 0.;
386 pdlast = 0.;
387 ratio = 5.;
388 cfode(2);
389 for (i = 1; i <= 5; ++i)
390 cm2[i] = tesco[i][2] * elco[i][i + 1];
391 cfode(1);
392 for (i = 1; i <= 12; ++i)
393 cm1[i] = tesco[i][2] * elco[i][i + 1];
394 resetcoeff();
395 } /* end if ( jstart == 0 ) */
396 /*
397 The following block handles preliminaries needed when jstart = -1.
398 ipup is set to miter to force a matrix update.
399 If an order increase is about to be considered ( ialth = 1 ),
400 ialth is reset to 2 to postpone consideration one more step.
401 If the caller has changed meth_, cfode is called to reset
402 the coefficients of the method.
403 If h_ is to be changed, yh_ must be rescaled.
404 If h_ or meth_ is being changed, ialth is reset to l = nq + 1
405 to prevent further changes in h_ for that many steps.
406 */
407 if (jstart == -1)
408 {
409 ipup = miter;
410 lmax = maxord + 1;
411 if (ialth == 1)
412 ialth = 2;
413 if (meth_ != mused)
414 {
415 cfode(meth_);
416 ialth = l;
417 resetcoeff();
418 }
419 if (h_ != hold)
420 {
421 rh = h_ / hold;
422 h_ = hold;
423 scaleh(&rh, &pdh);
424 }
425 } /* if ( jstart == -1 ) */
426 if (jstart == -2)
427 {
428 if (h_ != hold)
429 {
430 rh = h_ / hold;
431 h_ = hold;
432 scaleh(&rh, &pdh);
433 }
434 } /* if ( jstart == -2 ) */
435
436 /*
437 Prediction.
438 This section computes the predicted values by effectively
439 multiplying the yh_ array by the pascal triangle matrix.
440 rc is the ratio of new to old values of the coefficient h_ * el[1].
441 When rc differs from 1 by more than ccmax, ipup is set to miter
442 to force pjac to be called, if a jacobian is involved.
443 In any case, prja is called at least every msbp steps.
444 */
445 while (1)
446 {
447 while (1)
448 {
449 if (fabs(rc - 1.) > ccmax)
450 ipup = miter;
451 if (nst >= nslp + msbp)
452 ipup = miter;
453 tn_ += h_;
454 for (size_t j = nq; j >= 1; j--)
455 for (size_t i1 = j; i1 <= nq; ++i1)
456 for (i = 1; i <= n; ++i)
457 yh_[i1][i] += yh_[i1 + 1][i];
458
459 pnorm = vmnorm(n, yh_[1], ewt);
460 correction(neq, y, f, &corflag, pnorm, &del, &delp, &told, &ncf, &rh, &m,
461 _data);
462 if (corflag == 0)
463 break;
464 if (corflag == 1)
465 {
466 rh = max(rh, hmin / fabs(h_));
467 scaleh(&rh, &pdh);
468 continue;
469 }
470 if (corflag == 2)
471 {
472 kflag = -2;
473 hold = h_;
474 jstart = 1;
475 return;
476 }
477 } /* end inner while ( corrector loop ) */
478
479 /*
480 The corrector has converged. jcur is set to 0
481 to signal that the Jacobian involved may need updating later.
482 The local error test is done now.
483 */
484 jcur = 0;
485 if (m == 0)
486 dsm = del / tesco[nq][2];
487 if (m > 0)
488 dsm = vmnorm(n, acor, ewt) / tesco[nq][2];
489
490 if (dsm <= 1.)
491 {
492 /*
493 After a successful step, update the yh_ array.
494 Decrease icount by 1, and if it is -1, consider switching methods.
495 If a method switch is made, reset various parameters,
496 rescale the yh_ array, and exit. If there is no switch,
497 consider changing h_ if ialth = 1. Otherwise decrease ialth by 1.
498 If ialth is then 1 and nq < maxord, then acor is saved for
499 use in a possible order increase on the next step.
500 If a change in h_ is considered, an increase or decrease in order
501 by one is considered also. A change in h_ is made only if it is by
502 a factor of at least 1.1. If not, ialth is set to 3 to prevent
503 testing for that many steps.
504 */
505 kflag = 0;
506 nst++;
507 hu = h_;
508 nqu = nq;
509 mused = meth_;
510 for (size_t j = 1; j <= l; ++j)
511 {
512 r = el[j];
513 for (i = 1; i <= n; ++i)
514 yh_[j][i] += r * acor[i];
515 }
516 icount--;
517 if (icount < 0)
518 {
519 methodswitch(dsm, pnorm, &pdh, &rh);
520 if (meth_ != mused)
521 {
522 rh = max(rh, hmin / fabs(h_));
523 scaleh(&rh, &pdh);
524 rmax = 10.;
525 endstoda();
526 break;
527 }
528 }
529 /*
530 No method switch is being made. Do the usual step/order selection.
531 */
532 ialth--;
533 if (ialth == 0)
534 {
535 rhup = 0.;
536 if (l != lmax)
537 {
538 for (i = 1; i <= n; ++i)
539 savf[i] = acor[i] - yh_[lmax][i];
540 dup = vmnorm(n, savf, ewt) / tesco[nq][3];
541 exup = 1. / (double)(l + 1);
542 rhup = 1. / (1.4 * pow(dup, exup) + 0.0000014);
543 }
544
545 orderswitch(&rhup, dsm, &pdh, &rh, &orderflag);
546
547 /*
548 No change in h_ or nq.
549 */
550 if (orderflag == 0)
551 {
552 endstoda();
553 break;
554 }
555 /*
556 h_ is changed, but not nq.
557 */
558 if (orderflag == 1)
559 {
560 rh = max(rh, hmin / fabs(h_));
561 scaleh(&rh, &pdh);
562 rmax = 10.;
563 endstoda();
564 break;
565 }
566 /*
567 both nq and h_ are changed.
568 */
569 if (orderflag == 2)
570 {
571 resetcoeff();
572 rh = max(rh, hmin / fabs(h_));
573 scaleh(&rh, &pdh);
574 rmax = 10.;
575 endstoda();
576 break;
577 }
578 } /* end if ( ialth == 0 ) */
579 if (ialth > 1 || l == lmax)
580 {
581 endstoda();
582 break;
583 }
584
585 for (size_t i = 1; i <= n; ++i)
586 yh_[lmax][i] = acor[i];
587
588 endstoda();
589 break;
590 }
591 /* end if ( dsm <= 1. ) */
592 /*
593 The error test failed. kflag keeps track of multiple failures.
594 Restore tn_ and the yh_ array to their previous values, and prepare
595 to try the step again. Compute the optimum step size for this or
596 one lower. After 2 or more failures, h_ is forced to decrease
597 by a factor of 0.2 or less.
598 */
599 else
600 {
601 kflag--;
602 tn_ = told;
603 for (j = nq; j >= 1; j--)
604 {
605 for (i1 = j; i1 <= nq; ++i1)
606 for (i = 1; i <= n; ++i)
607 yh_[i1][i] -= yh_[i1 + 1][i];
608 }
609 rmax = 2.;
610 if (fabs(h_) <= hmin * 1.00001)
611 {
612 kflag = -1;
613 hold = h_;
614 jstart = 1;
615 break;
616 }
617 if (kflag > -3)
618 {
619 rhup = 0.;
620 orderswitch(&rhup, dsm, &pdh, &rh, &orderflag);
621 if (orderflag == 1 || orderflag == 0)
622 {
623 if (orderflag == 0)
624 rh = min(rh, 0.2);
625 rh = max(rh, hmin / fabs(h_));
626 scaleh(&rh, &pdh);
627 }
628 if (orderflag == 2)
629 {
630 resetcoeff();
631 rh = max(rh, hmin / fabs(h_));
632 scaleh(&rh, &pdh);
633 }
634 continue;
635 }
636 /* if ( kflag > -3 ) */
637 /*
638 Control reaches this section if 3 or more failures have occurred.
639 If 10 failures have occurred, exit with kflag = -1.
640 It is assumed that the derivatives that have accumulated in the
641 yh_ array have errors of the wrong order. Hence the first
642 derivative is recomputed, and the order is set to 1. Then
643 h_ is reduced by a factor of 10, and the step is retried,
644 until it succeeds or h_ reaches hmin.
645 */
646 else
647 {
648 if (kflag == -10)
649 {
650 kflag = -1;
651 hold = h_;
652 jstart = 1;
653 break;
654 }
655 else
656 {
657 rh = 0.1;
658 rh = max(hmin / fabs(h_), rh);
659 h_ *= rh;
660 for (i = 1; i <= n; ++i)
661 y[i] = yh_[1][i];
662 (*f)(tn_, &y[1], &savf[1], _data);
663 nfe++;
664 for (i = 1; i <= n; ++i)
665 yh_[2][i] = h_ * savf[i];
666 ipup = miter;
667 ialth = 5;
668 if (nq == 1)
669 continue;
670 nq = 1;
671 l = 2;
672 resetcoeff();
673 continue;
674 }
675 } /* end else -- kflag <= -3 */
676 } /* end error failure handling */
677 } /* end outer while */
678
679} /* end stoda */
680
681void LSODA::ewset(const vector<double> &ycur)
682{
683 switch (itol)
684 {
685 case 1:
686 for (size_t i = 1; i <= n; ++i)
687 ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[1];
688 break;
689 case 2:
690 for (size_t i = 1; i <= n; ++i)
691 ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[i];
692 break;
693 case 3:
694 for (size_t i = 1; i <= n; ++i)
695 ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[1];
696 break;
697 case 4:
698 for (size_t i = 1; i <= n; ++i)
699 ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[i];
700 break;
701 }
702
703} /* end ewset */
704
705/*
706 Intdy computes interpolated values of the k-th derivative of the
707 dependent variable vector y, and stores it in dky. This routine
708 is called within the package with k = 0 and *t = tout, but may
709 also be called by the user for any k up to the current order.
710 ( See detailed instructions in the usage documentation. )
711
712 The computed values in dky are gotten by interpolation using the
713 Nordsieck history array yh_. This array corresponds uniquely to a
714 vector-valued polynomial of degree nqcur or less, and dky is set
715 to the k-th derivative of this polynomial at t.
716 The formula for dky is
717
718 q
719 dky[i] = sum c[k][j] * ( t - tn_ )^(j-k) * h_^(-j) * yh_[j+1][i]
720 j=k
721
722 where c[k][j] = j*(j-1)*...*(j-k+1), q = nqcur, tn_ = tcur, h_ = hcur.
723 The quantities nq = nqcur, l = nq+1, n = neq, tn_, and h_ are declared
724 static globally. The above sum is done in reverse order.
725 *iflag is returned negative if either k or t is out of bounds.
726*/
727void LSODA::intdy(double t, int k, vector<double> &dky, int *iflag)
728{
729 int ic, jp1 = 0;
730 double c, r, s, tp;
731
732 *iflag = 0;
733 if (k < 0 || k > (int)nq)
734 {
735 //fprintf(stderr, "[intdy] k = %d illegal\n", k);
736 REprintf("[intdy] k = %d illegal.\n", k);
737 *iflag = -1;
738 return;
739 }
740 tp = tn_ - hu - 100. * ETA * (tn_ + hu);
741 if ((t - tp) * (t - tn_) > 0.)
742 {
743 // fprintf(stderr,
744 // "intdy -- t = %g illegal. t not in interval tcur - hu to tcur\n",
745 // t);
746 REprintf("[intdy] t = %g illegal. t not in interval tcur - hu to tcur.\n\n",t);
747 *iflag = -2;
748 return;
749 }
750 s = (t - tn_) / h_;
751 ic = 1;
752 for (size_t jj = l - k; jj <= nq; ++jj)
753 ic *= jj;
754 c = (double)ic;
755 for (size_t i = 1; i <= n; ++i)
756 dky[i] = c * yh_[l][i];
757
758 for (int j = nq - 1; j >= k; j--)
759 {
760 jp1 = j + 1;
761 ic = 1;
762 for (int jj = jp1 - k; jj <= j; ++jj)
763 ic *= jj;
764 c = (double)ic;
765
766 for (size_t i = 1; i <= n; ++i)
767 dky[i] = c * yh_[jp1][i] + s * dky[i];
768 }
769 if (k == 0)
770 return;
771 r = pow(h_, (double)(-k));
772
773 for (size_t i = 1; i <= n; ++i)
774 dky[i] *= r;
775
776} /* end intdy */
777
779{
780 int i, nq, nqm1, nqp1;
781 double agamq, fnq, fnqm1, pc[13], pint, ragq, rqfac, rq1fac, tsign, xpin;
782 /*
783 cfode is called by the integrator routine to set coefficients
784 needed there. The coefficients for the current method, as
785 given by the value of meth_, are set for all orders and saved.
786 The maximum order assumed here is 12 if meth_ = 1 and 5 if meth_ = 2.
787 ( A smaller value of the maximum order is also allowed. )
788 cfode is called once at the beginning of the problem, and
789 is not called again unless and until meth_ is changed.
790
791 The elco array contains the basic method coefficients.
792 The coefficients el[i], 1 < i < nq+1, for the method of
793 order nq are stored in elco[nq][i]. They are given by a generating
794 polynomial, i.e.,
795
796 l(x) = el[1] + el[2]*x + ... + el[nq+1]*x^nq.
797
798 For the implicit Adams method, l(x) is given by
799
800 dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1), l(-1) = 0.
801
802 For the bdf methods, l(x) is given by
803
804 l(x) = (x+1)*(x+2)*...*(x+nq)/k,
805
806 where k = factorial(nq)*(1+1/2+...+1/nq).
807
808 The tesco array contains test constants used for the
809 local error test and the selection of step size and/or order.
810 At order nq, tesco[nq][k] is used for the selection of step
811 size at order nq-1 if k = 1, at order nq if k = 2, and at order
812 nq+1 if k = 3.
813 */
814 if (meth_ == 1)
815 {
816 elco[1][1] = 1.;
817 elco[1][2] = 1.;
818 tesco[1][1] = 0.;
819 tesco[1][2] = 2.;
820 tesco[2][1] = 1.;
821 tesco[12][3] = 0.;
822 pc[1] = 1.;
823 rqfac = 1.;
824 for (nq = 2; nq <= 12; nq++)
825 {
826 /*
827 The pc array will contain the coefficients of the polynomial
828
829 p(x) = (x+1)*(x+2)*...*(x+nq-1).
830
831 Initially, p(x) = 1.
832 */
833 rq1fac = rqfac;
834 rqfac = rqfac / (double)nq;
835 nqm1 = nq - 1;
836 fnqm1 = (double)nqm1;
837 nqp1 = nq + 1;
838 /*
839 Form coefficients of p(x)*(x+nq-1).
840 */
841 pc[nq] = 0.;
842 for (i = nq; i >= 2; i--)
843 pc[i] = pc[i - 1] + fnqm1 * pc[i];
844 pc[1] = fnqm1 * pc[1];
845 /*
846 Compute integral, -1 to 0, of p(x) and x*p(x).
847 */
848 pint = pc[1];
849 xpin = pc[1] / 2.;
850 tsign = 1.;
851 for (i = 2; i <= nq; ++i)
852 {
853 tsign = -tsign;
854 pint += tsign * pc[i] / (double)i;
855 xpin += tsign * pc[i] / (double)(i + 1);
856 }
857 /*
858 Store coefficients in elco and tesco.
859 */
860 elco[nq][1] = pint * rq1fac;
861 elco[nq][2] = 1.;
862 for (i = 2; i <= nq; ++i)
863 elco[nq][i + 1] = rq1fac * pc[i] / (double)i;
864 agamq = rqfac * xpin;
865 ragq = 1. / agamq;
866 tesco[nq][2] = ragq;
867 if (nq < 12)
868 tesco[nqp1][1] = ragq * rqfac / (double)nqp1;
869 tesco[nqm1][3] = ragq;
870 } /* end for */
871 return;
872 } /* end if ( meth_ == 1 ) */
873
874 /* meth_ = 2. */
875 pc[1] = 1.;
876 rq1fac = 1.;
877
878 /*
879 The pc array will contain the coefficients of the polynomial
880 p(x) = (x+1)*(x+2)*...*(x+nq).
881 Initially, p(x) = 1.
882 */
883 for (nq = 1; nq <= 5; ++nq)
884 {
885 fnq = (double)nq;
886 nqp1 = nq + 1;
887 /*
888 Form coefficients of p(x)*(x+nq).
889 */
890 pc[nqp1] = 0.;
891 for (i = nq + 1; i >= 2; i--)
892 pc[i] = pc[i - 1] + fnq * pc[i];
893 pc[1] *= fnq;
894 /*
895 Store coefficients in elco and tesco.
896 */
897 for (i = 1; i <= nqp1; ++i)
898 elco[nq][i] = pc[i] / pc[2];
899 elco[nq][2] = 1.;
900 tesco[nq][1] = rq1fac;
901 tesco[nq][2] = ((double)nqp1) / elco[nq][1];
902 tesco[nq][3] = ((double)(nq + 2)) / elco[nq][1];
903 rq1fac /= fnq;
904 }
905 return;
906
907} /* end cfode */
908
909void LSODA::scaleh(double *rh, double *pdh)
910{
911 double r;
912 /*
913 If h_ is being changed, the h_ ratio rh is checked against rmax, hmin,
914 and hmxi, and the yh_ array is rescaled. ialth is set to l = nq + 1
915 to prevent a change of h_ for that many steps, unless forced by a
916 convergence or error test failure.
917 */
918 *rh = min(*rh, rmax);
919 *rh = *rh / max(1., fabs(h_) * hmxi * *rh);
920 /*
921 If meth_ = 1, also restrict the new step size by the stability region.
922 If this reduces h_, set irflag to 1 so that if there are roundoff
923 problems later, we can assume that is the cause of the trouble.
924 */
925 if (meth_ == 1)
926 {
927 irflag = 0;
928 *pdh = max(fabs(h_) * pdlast, 0.000001);
929 if ((*rh * *pdh * 1.00001) >= sm1[nq])
930 {
931 *rh = sm1[nq] / *pdh;
932 irflag = 1;
933 }
934 }
935 r = 1.;
936 for (size_t j = 2; j <= l; ++j)
937 {
938 r *= *rh;
939 for (size_t i = 1; i <= n; ++i)
940 yh_[j][i] *= r;
941 }
942 h_ *= *rh;
943 rc *= *rh;
944 ialth = l;
945
946} /* end scaleh */
947
948void LSODA::prja(const size_t neq, vector<double> &y, LSODA_ODE_SYSTEM_TYPE f,
949 dtype _data)
950{
951 size_t i = 0, ier = 0, j = 0;
952 double fac = 0.0, hl0 = 0.0, r = 0.0, r0 = 0.0, yj = 0.0;
953 /*
954 prja is called by stoda to compute and process the matrix
955 P = I - h_ * el[1] * J, where J is an approximation to the Jacobian.
956 Here J is computed by finite differencing.
957 J, scaled by -h_ * el[1], is stored in wm_. Then the norm of J ( the
958 matrix norm consistent with the weighted max-norm on vectors given
959 by vmnorm ) is computed, and J is overwritten by P. P is then
960 subjected to LU decomposition in preparation for later solution
961 of linear systems with p as coefficient matrix. This is done
962 by dgefa1 if miter = 2, and by dgbfa if miter = 5.
963 */
964 nje++;
965 ierpj = 0;
966 jcur = 1;
967 hl0 = h_ * el0;
968 /*
969 If miter = 2, make n calls to f to approximate J.
970 */
971 if (miter != 2)
972 {
973 //fprintf(stderr, "[prja] miter != 2\n");
974 REprintf("[prja] miter != 2.\n");
975 return;
976 }
977 if (miter == 2)
978 {
979 fac = vmnorm(n, savf, ewt);
980 r0 = 1000. * fabs(h_) * ETA * ((double)n) * fac;
981 if (r0 == 0.)
982 r0 = 1.;
983 for (j = 1; j <= n; ++j)
984 {
985 yj = y[j];
986 r = max(sqrteta * fabs(yj), r0 / ewt[j]);
987 y[j] += r;
988 fac = -hl0 / r;
989 (*f)(tn_, &y[1], &acor[1], _data);
990 for (i = 1; i <= n; ++i)
991 wm_[i][j] = (acor[i] - savf[i]) * fac;
992 y[j] = yj;
993 }
994 nfe += n;
995 /*
996 Compute norm of Jacobian.
997 */
998 pdnorm = fnorm(n, wm_, ewt) / fabs(hl0);
999 /*
1000 Add identity matrix.
1001 */
1002 for (i = 1; i <= n; ++i)
1003 wm_[i][i] += 1.;
1004 /*
1005 Do LU decomposition on P.
1006 */
1007 dgefa1(wm_, n, ipvt, &ier);
1008 if (ier != 0)
1009 ierpj = 1;
1010 return;
1011 }
1012} /* end prja */
1013
1014/*
1015 This function routine computes the weighted max-norm
1016 of the vector of length n contained in the array v, with weights
1017 contained in the array w of length n.
1018
1019 vmnorm = max( i = 1, ..., n ) fabs( v[i] ) * w[i].
1020*/
1021double LSODA::vmnorm(const size_t n, const vector<double> &v,
1022 const vector<double> &w)
1023{
1024 double vm = 0.;
1025 for (size_t i = 1; i <= n; ++i)
1026 vm = max(vm, fabs(v[i]) * w[i]);
1027 return vm;
1028}
1029
1030double LSODA::fnorm(int n, const vector<vector<double>> &a,
1031 const vector<double> &w)
1032
1033/*
1034 This subroutine computes the norm of a full n by n matrix,
1035 stored in the array a, that is consistent with the weighted max-norm
1036 on vectors, with weights stored in the array w.
1037
1038 fnorm = max(i=1,...,n) ( w[i] * sum(j=1,...,n) fabs( a[i][j] ) / w[j] )
1039*/
1040
1041{
1042 double an = 0, sum = 0;
1043
1044 for (size_t i = 1; i <= (size_t)n; ++i)
1045 {
1046 sum = 0.;
1047 for (size_t j = 1; j <= (size_t)n; ++j)
1048 sum += fabs(a[i][j]) / w[j];
1049 an = max(an, sum * w[i]);
1050 }
1051 return an;
1052}
1053
1054/*
1055 *corflag = 0 : corrector converged,
10561 : step size to be reduced, redo prediction,
10572 : corrector cannot converge, failure flag.
1058*/
1059void LSODA::correction(const size_t neq, vector<double> &y,
1060 LSODA_ODE_SYSTEM_TYPE f, size_t *corflag, double pnorm,
1061 double *del, double *delp, double *told,size_t *ncf,
1062 double *rh, size_t *m, dtype _data)
1063{
1064 double rm = 0.0, rate = 0.0, dcon = 0.0;
1065
1066 /*
1067 Up to maxcor corrector iterations are taken. A convergence test is
1068 made on the r.m.s. norm of each correction, weighted by the error
1069 weight vector ewt. The sum of the corrections is accumulated in the
1070 vector acor[i]. The yh_ array is not altered in the corrector loop.
1071 */
1072
1073 *m = 0;
1074 *corflag = 0;
1075 *del = 0.;
1076
1077 for (size_t i = 1; i <= n; ++i)
1078 y[i] = yh_[1][i];
1079
1080 (*f)(tn_, &y[1], &savf[1], _data);
1081
1082 nfe++;
1083 /*
1084 If indicated, the matrix P = I - h_ * el[1] * J is reevaluated and
1085 preprocessed before starting the corrector iteration. ipup is set
1086 to 0 as an indicator that this has been done.
1087 */
1088 while (1)
1089 {
1090 if (*m == 0)
1091 {
1092 if (ipup > 0)
1093 {
1094 prja(neq, y, f, _data);
1095 ipup = 0;
1096 rc = 1.;
1097 nslp = nst;
1098 crate = 0.7;
1099 if (ierpj != 0)
1100 {
1101 corfailure(told, rh, ncf, corflag);
1102 return;
1103 }
1104 }
1105 for (size_t i = 1; i <= n; ++i)
1106 acor[i] = 0.;
1107 } /* end if ( *m == 0 ) */
1108 if (miter == 0)
1109 {
1110 /*
1111 In case of functional iteration, update y directly from
1112 the result of the last function evaluation.
1113 */
1114 for (size_t i = 1; i <= n; ++i)
1115 {
1116 savf[i] = h_ * savf[i] - yh_[2][i];
1117 y[i] = savf[i] - acor[i];
1118 }
1119 *del = vmnorm(n, y, ewt);
1120 for (size_t i = 1; i <= n; ++i)
1121 {
1122 y[i] = yh_[1][i] + el[1] * savf[i];
1123 acor[i] = savf[i];
1124 }
1125 }
1126 /* end functional iteration */
1127 /*
1128 In the case of the chord method, compute the corrector error,
1129 and solve the linear system with that as right-hand side and
1130 P as coefficient matrix.
1131 */
1132 else
1133 {
1134 for (size_t i = 1; i <= n; ++i)
1135 y[i] = h_ * savf[i] - (yh_[2][i] + acor[i]);
1136
1137 solsy(y);
1138 *del = vmnorm(n, y, ewt);
1139
1140 for (size_t i = 1; i <= n; ++i)
1141 {
1142 acor[i] += y[i];
1143 y[i] = yh_[1][i] + el[1] * acor[i];
1144 }
1145 } /* end chord method */
1146 /*
1147 Test for convergence. If *m > 0, an estimate of the convergence
1148 rate constant is stored in crate, and this is used in the test.
1149
1150 We first check for a change of iterates that is the size of
1151 roundoff error. If this occurs, the iteration has converged, and a
1152 new rate estimate is not formed.
1153 In all other cases, force at least two iterations to estimate a
1154 local Lipschitz constant estimate for Adams method.
1155 On convergence, form pdest = local maximum Lipschitz constant
1156 estimate. pdlast is the most recent nonzero estimate.
1157 */
1158 if (*del <= 100. * pnorm * ETA)
1159 break;
1160 if (*m != 0 || meth_ != 1)
1161 {
1162 if (*m != 0)
1163 {
1164 rm = 1024.0;
1165 if (*del <= (1024. * *delp))
1166 rm = *del / *delp;
1167 rate = max(rate, rm);
1168 crate = max(0.2 * crate, rm);
1169 }
1170 dcon = *del * min(1., 1.5 * crate) / (tesco[nq][2] * conit);
1171 if (dcon <= 1.)
1172 {
1173 pdest = max(pdest, rate / fabs(h_ * el[1]));
1174 if (pdest != 0.)
1175 pdlast = pdest;
1176 break;
1177 }
1178 }
1179 /*
1180 The corrector iteration failed to converge.
1181 If miter != 0 and the Jacobian is out of date, prja is called for
1182 the next try. Otherwise the yh_ array is retracted to its values
1183 before prediction, and h_ is reduced, if possible. If h_ cannot be
1184 reduced or mxncf failures have occured, exit with corflag = 2.
1185 */
1186 (*m)++;
1187 if (*m == maxcor || (*m >= 2 && *del > 2. * *delp))
1188 {
1189 if (miter == 0 || jcur == 1)
1190 {
1191 corfailure(told, rh, ncf, corflag);
1192 return;
1193 }
1194 ipup = miter;
1195 /*
1196 Restart corrector if Jacobian is recomputed.
1197 */
1198 *m = 0;
1199 rate = 0.;
1200 *del = 0.;
1201 for (size_t i = 1; i <= n; ++i)
1202 y[i] = yh_[1][i];
1203
1204 (*f)(tn_, &y[1], &savf[1], _data);
1205
1206 nfe++;
1207 }
1208 /*
1209 Iterate corrector.
1210 */
1211 else
1212 {
1213 *delp = *del;
1214 (*f)(tn_, &y[1], &savf[1], _data);
1215 nfe++;
1216 }
1217 } /* end while */
1218} /* end correction */
1219
1220void LSODA::corfailure(double *told, double *rh, size_t *ncf, size_t *corflag)
1221{
1222 (*ncf)++;
1223 rmax = 2.;
1224 tn_ = *told;
1225 for (size_t j = nq; j >= 1; j--)
1226 for (size_t i1 = j; i1 <= nq; ++i1)
1227 for (size_t i = 1; i <= n; ++i)
1228 yh_[i1][i] -= yh_[i1 + 1][i];
1229
1230 if (fabs(h_) <= hmin * 1.00001 || *ncf == mxncf)
1231 {
1232 *corflag = 2;
1233 return;
1234 }
1235 *corflag = 1;
1236 *rh = 0.25;
1237 ipup = miter;
1238}
1239
1240/*
1241 This routine manages the solution of the linear system arising from
1242 a chord iteration. It is called if miter != 0.
1243 If miter is 2, it calls dgesl1 to accomplish this.
1244 If miter is 5, it calls dgbsl.
1245
1246 y = the right-hand side vector on input, and the solution vector
1247 on output.
1248*/
1249void LSODA::solsy(vector<double> &y)
1250{
1251 iersl = 0;
1252 if (miter != 2)
1253 {
1254 //printf("solsy -- miter != 2\n");
1255 REprintf("solsy -- miter != 2.\n");
1256 return;
1257 }
1258 if (miter == 2)
1259 dgesl1(wm_, n, ipvt, y, 0);
1260 return;
1261}
1262
1263void LSODA::methodswitch(double dsm, double pnorm, double *pdh, double *rh)
1264{
1265 int lm1, lm1p1, lm2, lm2p1, nqm1, nqm2;
1266 double rh1, rh2, rh1it, exm2, dm2, exm1, dm1, alpha, exsm;
1267
1268 /*
1269 We are current using an Adams method. Consider switching to bdf.
1270 If the current order is greater than 5, assume the problem is
1271 not stiff, and skip this section.
1272 If the Lipschitz constant and error estimate are not polluted
1273 by roundoff, perform the usual test.
1274 Otherwise, switch to the bdf methods if the last step was
1275 restricted to insure stability ( irflag = 1 ), and stay with Adams
1276 method if not. When switching to bdf with polluted error estimates,
1277 in the absence of other information, double the step size.
1278
1279 When the estimates are ok, we make the usual test by computing
1280 the step size we could have (ideally) used on this step,
1281 with the current (Adams) method, and also that for the bdf.
1282 If nq > mxords, we consider changing to order mxords on switching.
1283 Compare the two step sizes to decide whether to switch.
1284 The step size advantage must be at least ratio = 5 to switch.
1285 */
1286 if (meth_ == 1)
1287 {
1288 if (nq > 5)
1289 return;
1290 if (dsm <= (100. * pnorm * ETA) || pdest == 0.)
1291 {
1292 if (irflag == 0)
1293 return;
1294 rh2 = 2.;
1295 nqm2 = min(nq, mxords);
1296 }
1297 else
1298 {
1299 exsm = 1. / (double)l;
1300 rh1 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
1301 rh1it = 2. * rh1;
1302 *pdh = pdlast * fabs(h_);
1303 if ((*pdh * rh1) > 0.00001)
1304 rh1it = sm1[nq] / *pdh;
1305 rh1 = min(rh1, rh1it);
1306 if (nq > mxords)
1307 {
1308 nqm2 = mxords;
1309 lm2 = mxords + 1;
1310 exm2 = 1. / (double)lm2;
1311 lm2p1 = lm2 + 1;
1312 dm2 = vmnorm(n, yh_[lm2p1], ewt) / cm2[mxords];
1313 rh2 = 1. / (1.2 * pow(dm2, exm2) + 0.0000012);
1314 }
1315 else
1316 {
1317 dm2 = dsm * (cm1[nq] / cm2[nq]);
1318 rh2 = 1. / (1.2 * pow(dm2, exsm) + 0.0000012);
1319 nqm2 = nq;
1320 }
1321 if (rh2 < ratio * rh1)
1322 return;
1323 }
1324 /*
1325 The method switch test passed. Reset relevant quantities for bdf.
1326 */
1327 *rh = rh2;
1328 icount = 20;
1329 meth_ = 2;
1330 miter = jtyp;
1331 pdlast = 0.;
1332 nq = nqm2;
1333 l = nq + 1;
1334 return;
1335 } /* end if ( meth_ == 1 ) */
1336
1337 /*
1338 We are currently using a bdf method, considering switching to Adams.
1339 Compute the step size we could have (ideally) used on this step,
1340 with the current (bdf) method, and also that for the Adams.
1341 If nq > mxordn, we consider changing to order mxordn on switching.
1342 Compare the two step sizes to decide whether to switch.
1343 The step size advantage must be at least 5/ratio = 1 to switch.
1344 If the step size for Adams would be so small as to cause
1345 roundoff pollution, we stay with bdf.
1346 */
1347 exsm = 1. / (double)l;
1348 if (mxordn < nq)
1349 {
1350 nqm1 = mxordn;
1351 lm1 = mxordn + 1;
1352 exm1 = 1. / (double)lm1;
1353 lm1p1 = lm1 + 1;
1354 dm1 = vmnorm(n, yh_[lm1p1], ewt) / cm1[mxordn];
1355 rh1 = 1. / (1.2 * pow(dm1, exm1) + 0.0000012);
1356 }
1357 else
1358 {
1359 dm1 = dsm * (cm2[nq] / cm1[nq]);
1360 rh1 = 1. / (1.2 * pow(dm1, exsm) + 0.0000012);
1361 nqm1 = nq;
1362 exm1 = exsm;
1363 }
1364 rh1it = 2. * rh1;
1365 *pdh = pdnorm * fabs(h_);
1366 if ((*pdh * rh1) > 0.00001)
1367 rh1it = sm1[nqm1] / *pdh;
1368 rh1 = min(rh1, rh1it);
1369 rh2 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
1370 if ((rh1 * ratio) < (5. * rh2))
1371 return;
1372 alpha = max(0.001, rh1);
1373 dm1 *= pow(alpha, exm1);
1374 if (dm1 <= 1000. * ETA * pnorm)
1375 return;
1376 /*
1377 The switch test passed. Reset relevant quantities for Adams.
1378 */
1379 *rh = rh1;
1380 icount = 20;
1381 meth_ = 1;
1382 miter = 0;
1383 pdlast = 0.;
1384 nq = nqm1;
1385 l = nq + 1;
1386} /* end methodswitch */
1387
1388/*
1389 This routine returns from stoda to lsoda. Hence freevectors() is
1390 not executed.
1391*/
1393{
1394 double r = 1. / tesco[nqu][2];
1395 for (size_t i = 1; i <= n; ++i)
1396 acor[i] *= r;
1397 hold = h_;
1398 jstart = 1;
1399}
1400
1401/*
1402 Regardless of the success or failure of the step, factors
1403 rhdn, rhsm, and rhup are computed, by which h_ could be multiplied
1404 at order nq - 1, order nq, or order nq + 1, respectively.
1405 In the case of a failure, rhup = 0. to avoid an order increase.
1406 The largest of these is determined and the new order chosen
1407 accordingly. If the order is to be increased, we compute one
1408 additional scaled derivative.
1409
1410 orderflag = 0 : no change in h_ or nq,
1411 1 : change in h_ but not nq,
1412 2 : change in both h_ and nq.
1413*/
1414void LSODA::orderswitch(double *rhup, double dsm, double *pdh, double *rh,
1415 size_t *orderflag)
1416{
1417 size_t newq = 0;
1418 double exsm, rhdn, rhsm, ddn, exdn, r;
1419
1420 *orderflag = 0;
1421
1422 exsm = 1. / (double)l;
1423 rhsm = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
1424
1425 rhdn = 0.;
1426 if (nq != 1)
1427 {
1428 ddn = vmnorm(n, yh_[l], ewt) / tesco[nq][1];
1429 exdn = 1. / (double)nq;
1430 rhdn = 1. / (1.3 * pow(ddn, exdn) + 0.0000013);
1431 }
1432 /*
1433 If meth_ = 1, limit rh accordinfg to the stability region also.
1434 */
1435 if (meth_ == 1)
1436 {
1437 *pdh = max(fabs(h_) * pdlast, 0.000001);
1438 if (l < lmax)
1439 *rhup = min(*rhup, sm1[l] / *pdh);
1440 rhsm = min(rhsm, sm1[nq] / *pdh);
1441 if (nq > 1)
1442 rhdn = min(rhdn, sm1[nq - 1] / *pdh);
1443 pdest = 0.;
1444 }
1445 if (rhsm >= *rhup)
1446 {
1447 if (rhsm >= rhdn)
1448 {
1449 newq = nq;
1450 *rh = rhsm;
1451 }
1452 else
1453 {
1454 newq = nq - 1;
1455 *rh = rhdn;
1456 if (kflag < 0 && *rh > 1.)
1457 *rh = 1.;
1458 }
1459 }
1460 else
1461 {
1462 if (*rhup <= rhdn)
1463 {
1464 newq = nq - 1;
1465 *rh = rhdn;
1466 if (kflag < 0 && *rh > 1.)
1467 *rh = 1.;
1468 }
1469 else
1470 {
1471 *rh = *rhup;
1472 if (*rh >= 1.1)
1473 {
1474 r = el[l] / (double)l;
1475 nq = l;
1476 l = nq + 1;
1477 for (size_t i = 1; i <= n; ++i)
1478 yh_[l][i] = acor[i] * r;
1479
1480 *orderflag = 2;
1481 return;
1482 }
1483 else
1484 {
1485 ialth = 3;
1486 return;
1487 }
1488 }
1489 }
1490 /*
1491 If meth_ = 1 and h_ is restricted by stability, bypass 10 percent test.
1492 */
1493 if (1 == meth_)
1494 {
1495 if ((*rh * *pdh * 1.00001) < sm1[newq])
1496 if (kflag == 0 && *rh < 1.1)
1497 {
1498 ialth = 3;
1499 return;
1500 }
1501 }
1502 else
1503 {
1504 if (kflag == 0 && *rh < 1.1)
1505 {
1506 ialth = 3;
1507 return;
1508 }
1509 }
1510 if (kflag <= -2)
1511 *rh = min(*rh, 0.2);
1512 /*
1513 If there is a change of order, reset nq, l, and the coefficients.
1514 In any case h_ is reset according to rh and the yh_ array is rescaled.
1515 Then exit or redo the step.
1516 */
1517 if (newq == nq)
1518 {
1519 *orderflag = 1;
1520 return;
1521 }
1522 nq = newq;
1523 l = nq + 1;
1524 *orderflag = 2;
1525
1526} /* end orderswitch */
1527
1529/*
1530 The el vector and related constants are reset
1531 whenever the order nq is changed, or at the start of the problem.
1532*/
1533{
1534 array<double, 14> ep1;
1535
1536 ep1 = elco[nq];
1537 for (size_t i = 1; i <= l; ++i)
1538 el[i] = ep1[i];
1539 rc = rc * el[1] / el0;
1540 el0 = el[1];
1541 conit = 0.5 / (double)(nq + 2);
1542}
1543
1544#endif
#define ETA
Definition LSODA.cpp:54
void(* LSODA_ODE_SYSTEM_TYPE)(double t, double *y, double *dydt, dtype _data)
Definition LSODA.h:36
odeproblem * dtype
Definition LSODA.h:19
std::vector< double > rtol_
Definition LSODA.h:184
size_t illin
Definition LSODA.h:164
array< double, 13 > cm1
Definition LSODA.h:151
size_t n
Definition LSODA.h:170
double vmnorm(const size_t n, const vector< double > &v, const vector< double > &w)
Definition lsoda_functions.h:1021
double ddot1(const vector< double > &a, const vector< double > &b, const size_t n, const size_t offsetA, const size_t offsetB)
Definition lsoda_functions.h:104
void dscal1(const double da, vector< double > &dx, const size_t n, const size_t offset)
Definition lsoda_functions.h:96
void cfode(int meth_)
Definition lsoda_functions.h:778
void orderswitch(double *rhup, double dsm, double *pdh, double *rh, size_t *orderflag)
Definition lsoda_functions.h:1414
size_t maxcor
Definition LSODA.h:165
double hmin
Definition LSODA.h:175
double hmxi
Definition LSODA.h:175
std::vector< double > atol_
Definition LSODA.h:185
void endstoda(void)
Definition lsoda_functions.h:1392
size_t miter
Definition LSODA.h:165
int irflag
Definition LSODA.h:182
size_t ialth
Definition LSODA.h:179
int itol
Definition LSODA.h:54
size_t meth_
Definition LSODA.h:168
void intdy(double t, int k, vector< double > &dky, int *iflag)
Definition lsoda_functions.h:727
vector< vector< double > > yh_
Definition LSODA.h:160
double tn_
Definition LSODA.h:175
double sqrteta
Definition LSODA.h:142
double fnorm(int n, const vector< vector< double > > &a, const vector< double > &w)
Definition lsoda_functions.h:1030
array< double, 6 > cm2
Definition LSODA.h:152
void resetcoeff(void)
Definition lsoda_functions.h:1528
int icount
Definition LSODA.h:182
size_t iersl
Definition LSODA.h:164
int Neq
Definition LSODA.h:58
size_t ierpj
Definition LSODA.h:164
void ewset(const vector< double > &ycur)
Definition lsoda_functions.h:681
vector< double > savf
Definition LSODA.h:158
void daxpy1(const double da, const vector< double > &dx, vector< double > &dy, const size_t n, const size_t offsetX, const size_t offsetY)
Definition lsoda_functions.h:114
double hold
Definition LSODA.h:177
size_t msbp
Definition LSODA.h:165
int itask
Definition LSODA.h:53
void prja(const size_t neq, vector< double > &y, LSODA_ODE_SYSTEM_TYPE f, dtype _data)
Definition lsoda_functions.h:948
array< array< double, 14 >, 13 > elco
Definition LSODA.h:154
size_t nslp
Definition LSODA.h:180
double ratio
Definition LSODA.h:181
void maxsteps_(const int value)
Definition lsoda_functions.h:18
array< double, 14 > el
Definition LSODA.h:150
array< array< double, 4 >, 13 > tesco
Definition LSODA.h:155
void dgefa1(vector< vector< double > > &a, const size_t n, vector< int > &ipvt, size_t *const info)
Definition lsoda_functions.h:187
int Maxsteps
Definition LSODA.h:57
static bool abs_compare(double a, double b)
Definition lsoda_functions.h:67
array< double, 13 > sm1
Definition LSODA.h:148
double pdnorm
Definition LSODA.h:176
void successreturn(vector< double > &y, double *t, int itask, int ihit, double tcrit, int *istate)
Definition lsoda_functions.h:281
void solsy(vector< double > &y)
Definition lsoda_functions.h:1249
size_t nqu
Definition LSODA.h:170
array< int, 7 > iworks
Definition LSODA.h:67
size_t mxords
Definition LSODA.h:167
void ixpr_(const int value)
Definition lsoda_functions.h:24
size_t lmax
Definition LSODA.h:179
size_t jcur
Definition LSODA.h:164
void terminate2(vector< double > &y, double *t)
Definition lsoda_functions.h:265
size_t jtyp
Definition LSODA.h:167
size_t nq
Definition LSODA.h:170
double ccmax
Definition LSODA.h:174
void hmax_(const double value)
Definition lsoda_functions.h:8
void hmin_(const double value)
Definition lsoda_functions.h:13
void methodswitch(double dsm, double pnorm, double *pdh, double *rh)
Definition lsoda_functions.h:1263
vector< vector< double > > wm_
Definition LSODA.h:161
void mxhnil_(const int value)
Definition lsoda_functions.h:29
void stoda(const size_t neq, vector< double > &y, LSODA_ODE_SYSTEM_TYPE f, dtype _data)
Definition lsoda_functions.h:305
size_t mxncf
Definition LSODA.h:165
vector< double > acor
Definition LSODA.h:159
double el0
Definition LSODA.h:174
double hu
Definition LSODA.h:175
void setup_tol_vectors(const Rcpp::S4 &mod)
Definition lsoda_functions.h:34
double pdlast
Definition LSODA.h:181
int kflag
Definition LSODA.h:139
void dgesl1(const vector< vector< double > > &a, const size_t n, vector< int > &ipvt, vector< double > &b, const size_t job)
Definition lsoda_functions.h:124
size_t mused
Definition LSODA.h:167
array< double, 4 > rworks
Definition LSODA.h:68
int jstart
Definition LSODA.h:139
vector< int > ipvt
Definition LSODA.h:162
void corfailure(double *told, double *rh, size_t *ncf, size_t *corflag)
Definition lsoda_functions.h:1220
size_t idamax1(const vector< double > &dx, const size_t n, const size_t offset)
Definition lsoda_functions.h:73
void scaleh(double *rh, double *pdh)
Definition lsoda_functions.h:909
double rmax
Definition LSODA.h:177
double rc
Definition LSODA.h:175
double crate
Definition LSODA.h:177
size_t l
Definition LSODA.h:165
double h_
Definition LSODA.h:174
size_t nst
Definition LSODA.h:170
double pdest
Definition LSODA.h:181
void terminate(int *istate)
Definition lsoda_functions.h:248
vector< double > ewt
Definition LSODA.h:157
size_t nje
Definition LSODA.h:170
void correction(const size_t neq, vector< double > &y, LSODA_ODE_SYSTEM_TYPE f, size_t *corflag, double pnorm, double *del, double *delp, double *told, size_t *ncf, double *rh, size_t *m, dtype _data)
Definition lsoda_functions.h:1059
size_t mxordn
Definition LSODA.h:167
double conit
Definition LSODA.h:177
size_t nfe
Definition LSODA.h:170
size_t maxord
Definition LSODA.h:165
int iopt
Definition LSODA.h:51
size_t ipup
Definition LSODA.h:179
Definition odeproblem.h:100