-
Notifications
You must be signed in to change notification settings - Fork 298
/
ddaskr.cpp
9299 lines (7840 loc) · 306 KB
/
ddaskr.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <Solver/CppDASSL/dasslaux.h>
#include <Solver/CppDASSL/dassl.h>
static int c__49 = 49;
static int c__201 = 201;
static int c__0 = 0;
static double c_b38 = 0.;
static int c__47 = 47;
static int c__202 = 202;
static int c__1 = 1;
static int c__41 = 41;
static int c__203 = 203;
static int c__4 = 4;
static double c_b68 = .6667;
static int c__2 = 2;
static int c__56 = 56;
static int c__501 = 501;
static int c__502 = 502;
static int c__503 = 503;
static int c__3 = 3;
static int c__38 = 38;
static int c__610 = 610;
static int c__48 = 48;
static int c__611 = 611;
static int c__620 = 620;
static int c__621 = 621;
static int c__43 = 43;
static int c__622 = 622;
static int c__630 = 630;
static int c__28 = 28;
static int c__631 = 631;
static int c__44 = 44;
static int c__640 = 640;
static int c__57 = 57;
static int c__641 = 641;
static int c__650 = 650;
static int c__651 = 651;
static int c__40 = 40;
static int c__652 = 652;
static int c__655 = 655;
static int c__46 = 46;
static int c__656 = 656;
static int c__660 = 660;
static int c__661 = 661;
static int c__670 = 670;
static int c__45 = 45;
static int c__671 = 671;
static int c__672 = 672;
static int c__675 = 675;
static int c__51 = 51;
static int c__676 = 676;
static int c__677 = 677;
static int c__680 = 680;
static int c__36 = 36;
static int c__681 = 681;
static int c__685 = 685;
static int c__686 = 686;
static int c__690 = 690;
static int c__35 = 35;
static int c__691 = 691;
static int c__695 = 695;
static int c__50 = 50;
static int c__696 = 696;
static int c__25 = 25;
static int c__34 = 34;
static int c__60 = 60;
static int c__5 = 5;
static int c__39 = 39;
static int c__6 = 6;
static int c__7 = 7;
static int c__8 = 8;
static int c__54 = 54;
static int c__9 = 9;
static int c__10 = 10;
static int c__11 = 11;
static int c__29 = 29;
static int c__12 = 12;
static int c__13 = 13;
static int c__14 = 14;
static int c__15 = 15;
static int c__52 = 52;
static int c__17 = 17;
static int c__18 = 18;
static int c__19 = 19;
static int c__20 = 20;
static int c__21 = 21;
static int c__22 = 22;
static int c__58 = 58;
static int c__23 = 23;
static int c__24 = 24;
static int c__26 = 26;
static int c__27 = 27;
static int c__30 = 30;
static int c__31 = 31;
static int c__701 = 701;
static int c__702 = 702;
static double c_b758 = 1.;
static int c__901 = 901;
static int c__902 = 902;
static int c__903 = 903;
static int c__904 = 904;
static int c__905 = 905;
static int c__42 = 42;
static int c__906 = 906;
static double c_b965 = -1.;
static int c__921 = 921;
static int c__922 = 922;
static int c__923 = 923;
static int c__924 = 924;
static int c__925 = 925;
static int c__926 = 926;
/* Subroutine */ int dassl::ddaskr_(S_fp res, int *neq, double *t,
double *y, double *yprime, double *tout, int *info,
double *rtol, double *atol, int *idid, double *rwork,
int *lrw, int *iwork, int *liw, void *par, Ja_fp jac, P_fp psol, UC_fp rt, int *nrt, int *jroot)
{
/* System generated locals */
int i__1, i__2;
double d__1, d__2;
/* Builtin functions */
/* Local variables */
static double h__;
static int i__;
static double r__, h0;
static int le;
static double rh, tn;
static int lr0, lr1, ici, idi, lid, ier;
static char msg[80];
static int lwm, irt, lvt, lwt, lrx, nwt, nli0, nni0;
static int lcfl, lcfn, done;
static double rcfl;
static int nnid;
static int lavl;
static int maxl, iret;
static double hmax;
static int lphi;
static double hmin;
static int lyic, lpwk, nstd;
static double rcfn;
static int ncfl0, ncfn0;
static int lenic, lenid, ncphi, lenpd, lsoff, msave, index, itemp,
leniw, nzflg, mband;
static double atoli;
static int lypic;
static int lwarn;
static int lenwp, lenrw, mxord, nwarn;
static double rtoli;
static int lsavr;
static double tdist, tnext, avlin, fmaxl, tstop;
static int icnflg;
static double tscale, epconi;
static double floatn;
static int nonneg;
static int leniwp;
static double uround, ypnorm;
/* ***BEGIN PROLOGUE DDASKR */
/* ***REVISION HISTORY (YYMMDD) */
/* 020815 DATE WRITTEN */
/* 021105 Changed yprime argument in DRCHEK calls to YPRIME. */
/* 021217 Modified error return for zeros found too close together. */
/* 021217 Added root direction output in JROOT. */
/* 040518 Changed adjustment to X2 in Subr. DROOTS. */
/* 050511 Revised stopping tests in statements 530 - 580; reordered */
/* to test for tn at tstop before testing for tn past tout. */
/* 060712 In DMATD, changed minimum D.Q. increment to 1/EWT(j). */
/* 071003 In DRCHEK, fixed bug in TEMP2 (HMINR) below 110. */
/* 110608 In DRCHEK, fixed bug in setting of T1 at 300. */
/* ***CATEGORY NO. I1A2 */
/* ***KEYWORDS DIFFERENTIAL/ALGEBRAIC, BACKWARD DIFFERENTIATION FORMULAS, */
/* IMPLICIT DIFFERENTIAL SYSTEMS, KRYLOV ITERATION */
/* ***AUTHORS Linda R. Petzold, Peter N. Brown, Alan C. Hindmarsh, and */
/* Clement W. Ulrich */
/* Center for Computational Sciences & Engineering, L-316 */
/* Lawrence Livermore National Laboratory */
/* P.O. Box 808, */
/* Livermore, CA 94551 */
/* ***PURPOSE This code solves a system of differential/algebraic */
/* equations of the form */
/* G(t,y,y') = 0 , */
/* using a combination of Backward Differentiation Formula */
/* (BDF) methods and a choice of two linear system solution */
/* methods: direct (dense or band) or Krylov (iterative). */
/* This version is in double precision. */
/* ----------------------------------------------------------------------- */
/* ***DESCRIPTION */
/* *Usage: */
/* IMPLICIT DOUBLE PRECISION(A-H,O-Z) */
/* int NEQ, INFO(N), IDID, LRW, LIW, IWORK(LIW), IPAR(*) */
/* DOUBLE PRECISION T, Y(*), YPRIME(*), TOUT, RTOL(*), ATOL(*), */
/* RWORK(LRW), RPAR(*) */
/* EXTERNAL RES, JAC, PSOL, RT */
/* CALL DDASKR (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL, */
/* * IDID, RWORK, LRW, IWORK, LIW, par, JAC, PSOL, */
/* * RT, NRT, JROOT) */
/* Quantities which may be altered by the code are: */
/* T, Y(*), YPRIME(*), INFO(1), RTOL, ATOL, IDID, RWORK(*), IWORK(*) */
/* *Arguments: */
/* RES:EXT This is the name of a subroutine which you */
/* provide to define the residual function G(t,y,y') */
/* of the differential/algebraic system. */
/* NEQ:IN This is the number of equations in the system. */
/* T:INOUT This is the current value of the independent */
/* variable. */
/* Y(*):INOUT This array contains the solution components at T. */
/* YPRIME(*):INOUT This array contains the derivatives of the solution */
/* components at T. */
/* TOUT:IN This is a point at which a solution is desired. */
/* INFO(N):IN This is an int array used to communicate details */
/* of how the solution is to be carried out, such as */
/* tolerance type, matrix structure, step size and */
/* order limits, and choice of nonlinear system method. */
/* N must be at least 20. */
/* RTOL,ATOL:INOUT These quantities represent absolute and relative */
/* error tolerances (on local error) which you provide */
/* to indicate how accurately you wish the solution to */
/* be computed. You may choose them to be both scalars */
/* or else both arrays of length NEQ. */
/* IDID:OUT This int scalar is an indicator reporting what */
/* the code did. You must monitor this variable to */
/* decide what action to take next. */
/* RWORK:WORK A real work array of length LRW which provides the */
/* code with needed storage space. */
/* LRW:IN The length of RWORK. */
/* IWORK:WORK An int work array of length LIW which provides */
/* the code with needed storage space. */
/* LIW:IN The length of IWORK. */
/* RPAR,IPAR:IN These are real and int parameter arrays which */
/* you can use for communication between your calling */
/* program and the RES, JAC, and PSOL subroutines. */
/* JAC:EXT This is the name of a subroutine which you may */
/* provide (optionally) for calculating Jacobian */
/* (partial derivative) data involved in solving linear */
/* systems within DDASKR. */
/* PSOL:EXT This is the name of a subroutine which you must */
/* provide for solving linear systems if you selected */
/* a Krylov method. The purpose of PSOL is to solve */
/* linear systems involving a left preconditioner P. */
/* RT:EXT This is the name of the subroutine for defining */
/* constraint functions Ri(T,Y,Y')) whose roots are */
/* desired during the integration. This name must be */
/* declared external in the calling program. */
/* NRT:IN This is the number of constraint functions */
/* Ri(T,Y,Y'). If there are no constraints, set */
/* NRT = 0, and pass a dummy name for RT. */
/* JROOT:OUT This is an int array of length NRT for output */
/* of root information. */
/* *Overview */
/* The DDASKR solver uses the backward differentiation formulas of */
/* orders one through five to solve a system of the form G(t,y,y') = 0 */
/* for y = Y and y' = YPRIME. Values for Y and YPRIME at the initial */
/* time must be given as input. These values should be consistent, */
/* that is, if T, Y, YPRIME are the given initial values, they should */
/* satisfy G(T,Y,YPRIME) = 0. However, if consistent values are not */
/* known, in many cases you can have DDASKR solve for them -- see */
/* INFO(11). (This and other options are described in detail below.) */
/* Normally, DDASKR solves the system from T to TOUT. It is easy to */
/* continue the solution to get results at additional TOUT. This is */
/* the interval mode of operation. Intermediate results can also be */
/* obtained easily by specifying INFO(3). */
/* On each step taken by DDASKR, a sequence of nonlinear algebraic */
/* systems arises. These are solved by one of two types of */
/* methods: */
/* * a Newton iteration with a direct method for the linear */
/* systems involved (INFO(12) = 0), or */
/* * a Newton iteration with a preconditioned Krylov iterative */
/* method for the linear systems involved (INFO(12) = 1). */
/* The direct method choices are dense and band matrix solvers, */
/* with either a user-supplied or an internal difference quotient */
/* Jacobian matrix, as specified by INFO(5) and INFO(6). */
/* In the band case, INFO(6) = 1, you must supply half-bandwidths */
/* in IWORK(1) and IWORK(2). */
/* The Krylov method is the Generalized Minimum Residual (GMRES) */
/* method, in either complete or incomplete form, and with */
/* scaling and preconditioning. The method is implemented */
/* in an algorithm called SPIGMR. Certain options in the Krylov */
/* method case are specified by INFO(13) and INFO(15). */
/* If the Krylov method is chosen, you may supply a pair of routines, */
/* JAC and PSOL, to apply preconditioning to the linear system. */
/* If the system is A*x = b, the matrix is A = dG/dY + CJ*dG/dYPRIME */
/* (of order NEQ). This system can then be preconditioned in the form */
/* (P-inverse)*A*x = (P-inverse)*b, with left preconditioner P. */
/* (DDASKR does not allow right preconditioning.) */
/* Then the Krylov method is applied to this altered, but equivalent, */
/* linear system, hopefully with much better performance than without */
/* preconditioning. (In addition, a diagonal scaling matrix based on */
/* the tolerances is also introduced into the altered system.) */
/* The JAC routine evaluates any data needed for solving systems */
/* with coefficient matrix P, and PSOL carries out that solution. */
/* In any case, in order to improve convergence, you should try to */
/* make P approximate the matrix A as much as possible, while keeping */
/* the system P*x = b reasonably easy and inexpensive to solve for x, */
/* given a vector b. */
/* While integrating the given DAE system, DDASKR also searches for */
/* roots of the given constraint functions Ri(T,Y,Y') given by RT. */
/* If DDASKR detects a sign change in any Ri(T,Y,Y'), it will return */
/* the intermediate value of T and Y for which Ri(T,Y,Y') = 0. */
/* Caution: If some Ri has a root at or very near the initial time, */
/* DDASKR may fail to find it, or may find extraneous roots there, */
/* because it does not yet have a sufficient history of the solution. */
/* *Description */
/* ------INPUT - WHAT TO DO ON THE FIRST CALL TO DDASKR------------------- */
/* The first call of the code is defined to be the start of each new */
/* problem. Read through the descriptions of all the following items, */
/* provide sufficient storage space for designated arrays, set */
/* appropriate variables for the initialization of the problem, and */
/* give information about how you want the problem to be solved. */
/* RES -- Provide a subroutine of the form */
/* SUBROUTINE RES (T, Y, YPRIME, CJ, DELTA, IRES, par) */
/* to define the system of differential/algebraic */
/* equations which is to be solved. For the given values */
/* of T, Y and YPRIME, the subroutine should return */
/* the residual of the differential/algebraic system */
/* DELTA = G(T,Y,YPRIME) */
/* DELTA is a vector of length NEQ which is output from RES. */
/* Subroutine RES must not alter T, Y, YPRIME, or CJ. */
/* You must declare the name RES in an EXTERNAL */
/* statement in your program that calls DDASKR. */
/* You must dimension Y, YPRIME, and DELTA in RES. */
/* The input argument CJ can be ignored, or used to rescale */
/* constraint equations in the system (see Ref. 2, p. 145). */
/* Note: In this respect, DDASKR is not downward-compatible */
/* with DDASSL, which does not have the RES argument CJ. */
/* IRES is an int flag which is always equal to zero */
/* on input. Subroutine RES should alter IRES only if it */
/* encounters an illegal value of Y or a stop condition. */
/* Set IRES = -1 if an input value is illegal, and DDASKR */
/* will try to solve the problem without getting IRES = -1. */
/* If IRES = -2, DDASKR will return control to the calling */
/* program with IDID = -11. */
/* RPAR and IPAR are real and int parameter arrays which */
/* you can use for communication between your calling program */
/* and subroutine RES. They are not altered by DDASKR. If you */
/* do not need RPAR or IPAR, ignore these parameters by treat- */
/* ing them as dummy arguments. If you do choose to use them, */
/* dimension them in your calling program and in RES as arrays */
/* of appropriate length. */
/* NEQ -- Set it to the number of equations in the system (NEQ .GE. 1). */
/* T -- Set it to the initial point of the integration. (T must be */
/* a variable.) */
/* Y(*) -- Set this array to the initial values of the NEQ solution */
/* components at the initial point. You must dimension Y of */
/* length at least NEQ in your calling program. */
/* YPRIME(*) -- Set this array to the initial values of the NEQ first */
/* derivatives of the solution components at the initial */
/* point. You must dimension YPRIME at least NEQ in your */
/* calling program. */
/* TOUT - Set it to the first point at which a solution is desired. */
/* You cannot take TOUT = T. Integration either forward in T */
/* (TOUT .GT. T) or backward in T (TOUT .LT. T) is permitted. */
/* The code advances the solution from T to TOUT using step */
/* sizes which are automatically selected so as to achieve the */
/* desired accuracy. If you wish, the code will return with the */
/* solution and its derivative at intermediate steps (the */
/* intermediate-output mode) so that you can monitor them, */
/* but you still must provide TOUT in accord with the basic */
/* aim of the code. */
/* The first step taken by the code is a critical one because */
/* it must reflect how fast the solution changes near the */
/* initial point. The code automatically selects an initial */
/* step size which is practically always suitable for the */
/* problem. By using the fact that the code will not step past */
/* TOUT in the first step, you could, if necessary, restrict the */
/* length of the initial step. */
/* For some problems it may not be permissible to integrate */
/* past a point TSTOP, because a discontinuity occurs there */
/* or the solution or its derivative is not defined beyond */
/* TSTOP. When you have declared a TSTOP point (see INFO(4) */
/* and RWORK(1)), you have told the code not to integrate past */
/* TSTOP. In this case any tout beyond TSTOP is invalid input. */
/* INFO(*) - Use the INFO array to give the code more details about */
/* how you want your problem solved. This array should be */
/* dimensioned of length 20, though DDASKR uses only the */
/* first 15 entries. You must respond to all of the following */
/* items, which are arranged as questions. The simplest use */
/* of DDASKR corresponds to setting all entries of INFO to 0. */
/* INFO(1) - This parameter enables the code to initialize itself. */
/* You must set it to indicate the start of every new */
/* problem. */
/* **** Is this the first call for this problem ... */
/* yes - set INFO(1) = 0 */
/* no - not applicable here. */
/* See below for continuation calls. **** */
/* INFO(2) - How much accuracy you want of your solution */
/* is specified by the error tolerances RTOL and ATOL. */
/* The simplest use is to take them both to be scalars. */
/* To obtain more flexibility, they can both be arrays. */
/* The code must be told your choice. */
/* **** Are both error tolerances RTOL, ATOL scalars ... */
/* yes - set INFO(2) = 0 */
/* and input scalars for both RTOL and ATOL */
/* no - set INFO(2) = 1 */
/* and input arrays for both RTOL and ATOL **** */
/* INFO(3) - The code integrates from T in the direction of TOUT */
/* by steps. If you wish, it will return the computed */
/* solution and derivative at the next intermediate step */
/* (the intermediate-output mode) or TOUT, whichever comes */
/* first. This is a good way to proceed if you want to */
/* see the behavior of the solution. If you must have */
/* solutions at a great many specific TOUT points, this */
/* code will compute them efficiently. */
/* **** Do you want the solution only at */
/* TOUT (and not at the next intermediate step) ... */
/* yes - set INFO(3) = 0 (interval-output mode) */
/* no - set INFO(3) = 1 (intermediate-output mode) **** */
/* INFO(4) - To handle solutions at a great many specific */
/* values TOUT efficiently, this code may integrate past */
/* TOUT and interpolate to obtain the result at TOUT. */
/* Sometimes it is not possible to integrate beyond some */
/* point TSTOP because the equation changes there or it is */
/* not defined past TSTOP. Then you must tell the code */
/* this stop condition. */
/* **** Can the integration be carried out without any */
/* restrictions on the independent variable T ... */
/* yes - set INFO(4) = 0 */
/* no - set INFO(4) = 1 */
/* and define the stopping point TSTOP by */
/* setting RWORK(1) = TSTOP **** */
/* INFO(5) - used only when INFO(12) = 0 (direct methods). */
/* To solve differential/algebraic systems you may wish */
/* to use a matrix of partial derivatives of the */
/* system of differential equations. If you do not */
/* provide a subroutine to evaluate it analytically (see */
/* description of the item JAC in the call list), it will */
/* be approximated by numerical differencing in this code. */
/* Although it is less trouble for you to have the code */
/* compute partial derivatives by numerical differencing, */
/* the solution will be more reliable if you provide the */
/* derivatives via JAC. Usually numerical differencing is */
/* more costly than evaluating derivatives in JAC, but */
/* sometimes it is not - this depends on your problem. */
/* **** Do you want the code to evaluate the partial deriv- */
/* atives automatically by numerical differences ... */
/* yes - set INFO(5) = 0 */
/* no - set INFO(5) = 1 */
/* and provide subroutine JAC for evaluating the */
/* matrix of partial derivatives **** */
/* INFO(6) - used only when INFO(12) = 0 (direct methods). */
/* DDASKR will perform much better if the matrix of */
/* partial derivatives, dG/dY + CJ*dG/dYPRIME (here CJ is */
/* a scalar determined by DDASKR), is banded and the code */
/* is told this. In this case, the storage needed will be */
/* greatly reduced, numerical differencing will be performed */
/* much cheaper, and a number of important algorithms will */
/* execute much faster. The differential equation is said */
/* to have half-bandwidths ML (lower) and MU (upper) if */
/* equation i involves only unknowns Y(j) with */
/* i-ML .le. j .le. i+MU . */
/* For all i=1,2,...,NEQ. Thus, ML and MU are the widths */
/* of the lower and upper parts of the band, respectively, */
/* with the main diagonal being excluded. If you do not */
/* indicate that the equation has a banded matrix of partial */
/* derivatives the code works with a full matrix of NEQ**2 */
/* elements (stored in the conventional way). Computations */
/* with banded matrices cost less time and storage than with */
/* full matrices if 2*ML+MU .lt. NEQ. If you tell the */
/* code that the matrix of partial derivatives has a banded */
/* structure and you want to provide subroutine JAC to */
/* compute the partial derivatives, then you must be careful */
/* to store the elements of the matrix in the special form */
/* indicated in the description of JAC. */
/* **** Do you want to solve the problem using a full (dense) */
/* matrix (and not a special banded structure) ... */
/* yes - set INFO(6) = 0 */
/* no - set INFO(6) = 1 */
/* and provide the lower (ML) and upper (MU) */
/* bandwidths by setting */
/* IWORK(1)=ML */
/* IWORK(2)=MU **** */
/* INFO(7) - You can specify a maximum (absolute value of) */
/* stepsize, so that the code will avoid passing over very */
/* large regions. */
/* **** Do you want the code to decide on its own the maximum */
/* stepsize ... */
/* yes - set INFO(7) = 0 */
/* no - set INFO(7) = 1 */
/* and define HMAX by setting */
/* RWORK(2) = HMAX **** */
/* INFO(8) - Differential/algebraic problems may occasionally */
/* suffer from severe scaling difficulties on the first */
/* step. If you know a great deal about the scaling of */
/* your problem, you can help to alleviate this problem */
/* by specifying an initial stepsize H0. */
/* **** Do you want the code to define its own initial */
/* stepsize ... */
/* yes - set INFO(8) = 0 */
/* no - set INFO(8) = 1 */
/* and define H0 by setting */
/* RWORK(3) = H0 **** */
/* INFO(9) - If storage is a severe problem, you can save some */
/* storage by restricting the maximum method order MAXORD. */
/* The default value is 5. For each order decrease below 5, */
/* the code requires NEQ fewer locations, but it is likely */
/* to be slower. In any case, you must have */
/* 1 .le. MAXORD .le. 5. */
/* **** Do you want the maximum order to default to 5 ... */
/* yes - set INFO(9) = 0 */
/* no - set INFO(9) = 1 */
/* and define MAXORD by setting */
/* IWORK(3) = MAXORD **** */
/* INFO(10) - If you know that certain components of the */
/* solutions to your equations are always nonnegative */
/* (or nonpositive), it may help to set this */
/* parameter. There are three options that are */
/* available: */
/* 1. To have constraint checking only in the initial */
/* condition calculation. */
/* 2. To enforce nonnegativity in Y during the integration. */
/* 3. To enforce both options 1 and 2. */
/* When selecting option 2 or 3, it is probably best to try */
/* the code without using this option first, and only use */
/* this option if that does not work very well. */
/* **** Do you want the code to solve the problem without */
/* invoking any special inequality constraints ... */
/* yes - set INFO(10) = 0 */
/* no - set INFO(10) = 1 to have option 1 enforced */
/* no - set INFO(10) = 2 to have option 2 enforced */
/* no - set INFO(10) = 3 to have option 3 enforced **** */
/* If you have specified INFO(10) = 1 or 3, then you */
/* will also need to identify how each component of Y */
/* in the initial condition calculation is constrained. */
/* You must set: */
/* IWORK(40+I) = +1 if Y(I) must be .GE. 0, */
/* IWORK(40+I) = +2 if Y(I) must be .GT. 0, */
/* IWORK(40+I) = -1 if Y(I) must be .LE. 0, while */
/* IWORK(40+I) = -2 if Y(I) must be .LT. 0, while */
/* IWORK(40+I) = 0 if Y(I) is not constrained. */
/* INFO(11) - DDASKR normally requires the initial T, Y, and */
/* YPRIME to be consistent. That is, you must have */
/* G(T,Y,YPRIME) = 0 at the initial T. If you do not know */
/* the initial conditions precisely, in some cases */
/* DDASKR may be able to compute it. */
/* Denoting the differential variables in Y by Y_d */
/* and the algebraic variables by Y_a, DDASKR can solve */
/* one of two initialization problems: */
/* 1. Given Y_d, calculate Y_a and Y'_d, or */
/* 2. Given Y', calculate Y. */
/* In either case, initial values for the given */
/* components are input, and initial guesses for */
/* the unknown components must also be provided as input. */
/* **** Are the initial T, Y, YPRIME consistent ... */
/* yes - set INFO(11) = 0 */
/* no - set INFO(11) = 1 to calculate option 1 above, */
/* or set INFO(11) = 2 to calculate option 2 **** */
/* If you have specified INFO(11) = 1, then you */
/* will also need to identify which are the */
/* differential and which are the algebraic */
/* components (algebraic components are components */
/* whose derivatives do not appear explicitly */
/* in the function G(T,Y,YPRIME)). You must set: */
/* IWORK(LID+I) = +1 if Y(I) is a differential variable */
/* IWORK(LID+I) = -1 if Y(I) is an algebraic variable, */
/* where LID = 40 if INFO(10) = 0 or 2 and LID = 40+NEQ */
/* if INFO(10) = 1 or 3. */
/* INFO(12) - Except for the addition of the RES argument CJ, */
/* DDASKR by default is downward-compatible with DDASSL, */
/* which uses only direct (dense or band) methods to solve */
/* the linear systems involved. You must set INFO(12) to */
/* indicate whether you want the direct methods or the */
/* Krylov iterative method. */
/* **** Do you want DDASKR to use standard direct methods */
/* (dense or band) or the Krylov (iterative) method ... */
/* direct methods - set INFO(12) = 0. */
/* Krylov method - set INFO(12) = 1, */
/* and check the settings of INFO(13) and INFO(15). */
/* INFO(13) - used when INFO(12) = 1 (Krylov methods). */
/* DDASKR uses scalars MAXL, KMP, NRMAX, and EPLI for the */
/* iterative solution of linear systems. INFO(13) allows */
/* you to override the default values of these parameters. */
/* These parameters and their defaults are as follows: */
/* MAXL = maximum number of iterations in the SPIGMR */
/* algorithm (MAXL .le. NEQ). The default is */
/* MAXL = MIN(5,NEQ). */
/* KMP = number of vectors on which orthogonalization is */
/* done in the SPIGMR algorithm. The default is */
/* KMP = MAXL, which corresponds to complete GMRES */
/* iteration, as opposed to the incomplete form. */
/* NRMAX = maximum number of restarts of the SPIGMR */
/* algorithm per nonlinear iteration. The default is */
/* NRMAX = 5. */
/* EPLI = convergence test constant in SPIGMR algorithm. */
/* The default is EPLI = 0.05. */
/* Note that the length of RWORK depends on both MAXL */
/* and KMP. See the definition of LRW below. */
/* **** Are MAXL, KMP, and EPLI to be given their */
/* default values ... */
/* yes - set INFO(13) = 0 */
/* no - set INFO(13) = 1, */
/* and set all of the following: */
/* IWORK(24) = MAXL (1 .le. MAXL .le. NEQ) */
/* IWORK(25) = KMP (1 .le. KMP .le. MAXL) */
/* IWORK(26) = NRMAX (NRMAX .ge. 0) */
/* RWORK(10) = EPLI (0 .lt. EPLI .lt. 1.0) **** */
/* INFO(14) - used with INFO(11) > 0 (initial condition */
/* calculation is requested). In this case, you may */
/* request control to be returned to the calling program */
/* immediately after the initial condition calculation, */
/* before proceeding to the integration of the system */
/* (e.g. to examine the computed Y and YPRIME). */
/* If this is done, and if the initialization succeeded */
/* (IDID = 4), you should reset INFO(11) to 0 for the */
/* next call, to prevent the solver from repeating the */
/* initialization (and to avoid an infinite loop). */
/* **** Do you want to proceed to the integration after */
/* the initial condition calculation is done ... */
/* yes - set INFO(14) = 0 */
/* no - set INFO(14) = 1 **** */
/* INFO(15) - used when INFO(12) = 1 (Krylov methods). */
/* When using preconditioning in the Krylov method, */
/* you must supply a subroutine, PSOL, which solves the */
/* associated linear systems using P. */
/* The usage of DDASKR is simpler if PSOL can carry out */
/* the solution without any prior calculation of data. */
/* However, if some partial derivative data is to be */
/* calculated in advance and used repeatedly in PSOL, */
/* then you must supply a JAC routine to do this, */
/* and set INFO(15) to indicate that JAC is to be called */
/* for this purpose. For example, P might be an */
/* approximation to a part of the matrix A which can be */
/* calculated and LU-factored for repeated solutions of */
/* the preconditioner system. The arrays WP and IWP */
/* (described under JAC and PSOL) can be used to */
/* communicate data between JAC and PSOL. */
/* **** Does PSOL operate with no prior preparation ... */
/* yes - set INFO(15) = 0 (no JAC routine) */
/* no - set INFO(15) = 1 */
/* and supply a JAC routine to evaluate and */
/* preprocess any required Jacobian data. **** */
/* INFO(16) - option to exclude algebraic variables from */
/* the error test. */
/* **** Do you wish to control errors locally on */
/* all the variables... */
/* yes - set INFO(16) = 0 */
/* no - set INFO(16) = 1 */
/* If you have specified INFO(16) = 1, then you */
/* will also need to identify which are the */
/* differential and which are the algebraic */
/* components (algebraic components are components */
/* whose derivatives do not appear explicitly */
/* in the function G(T,Y,YPRIME)). You must set: */
/* IWORK(LID+I) = +1 if Y(I) is a differential */
/* variable, and */
/* IWORK(LID+I) = -1 if Y(I) is an algebraic */
/* variable, */
/* where LID = 40 if INFO(10) = 0 or 2 and */
/* LID = 40 + NEQ if INFO(10) = 1 or 3. */
/* INFO(17) - used when INFO(11) > 0 (DDASKR is to do an */
/* initial condition calculation). */
/* DDASKR uses several heuristic control quantities in the */
/* initial condition calculation. They have default values, */
/* but can also be set by the user using INFO(17). */
/* These parameters and their defaults are as follows: */
/* MXNIT = maximum number of Newton iterations */
/* per Jacobian or preconditioner evaluation. */
/* The default is: */
/* MXNIT = 5 in the direct case (INFO(12) = 0), and */
/* MXNIT = 15 in the Krylov case (INFO(12) = 1). */
/* MXNJ = maximum number of Jacobian or preconditioner */
/* evaluations. The default is: */
/* MXNJ = 6 in the direct case (INFO(12) = 0), and */
/* MXNJ = 2 in the Krylov case (INFO(12) = 1). */
/* MXNH = maximum number of values of the artificial */
/* stepsize parameter H to be tried if INFO(11) = 1. */
/* The default is MXNH = 5. */
/* NOTE: the maximum number of Newton iterations */
/* allowed in all is MXNIT*MXNJ*MXNH if INFO(11) = 1, */
/* and MXNIT*MXNJ if INFO(11) = 2. */
/* LSOFF = flag to turn off the linesearch algorithm */
/* (LSOFF = 0 means linesearch is on, LSOFF = 1 means */
/* it is turned off). The default is LSOFF = 0. */
/* STPTOL = minimum scaled step in linesearch algorithm. */
/* The default is STPTOL = (unit roundoff)**(2/3). */
/* EPINIT = swing factor in the Newton iteration convergence */
/* test. The test is applied to the residual vector, */
/* premultiplied by the approximate Jacobian (in the */
/* direct case) or the preconditioner (in the Krylov */
/* case). For convergence, the weighted RMS norm of */
/* this vector (scaled by the error weights) must be */
/* less than EPINIT*EPCON, where EPCON = .33 is the */
/* analogous test constant used in the time steps. */
/* The default is EPINIT = .01. */
/* **** Are the initial condition heuristic controls to be */
/* given their default values... */
/* yes - set INFO(17) = 0 */
/* no - set INFO(17) = 1, */
/* and set all of the following: */
/* IWORK(32) = MXNIT (.GT. 0) */
/* IWORK(33) = MXNJ (.GT. 0) */
/* IWORK(34) = MXNH (.GT. 0) */
/* IWORK(35) = LSOFF ( = 0 or 1) */
/* RWORK(14) = STPTOL (.GT. 0.0) */
/* RWORK(15) = EPINIT (.GT. 0.0) **** */
/* INFO(18) - option to get extra printing in initial condition */
/* calculation. */
/* **** Do you wish to have extra printing... */
/* no - set INFO(18) = 0 */
/* yes - set INFO(18) = 1 for minimal printing, or */
/* set INFO(18) = 2 for full printing. */
/* If you have specified INFO(18) .ge. 1, data */
/* will be printed with the error handler routines. */
/* To print to a non-default unit number L, include */
/* the line CALL XSETUN(L) in your program. **** */
/* RTOL, ATOL -- You must assign relative (RTOL) and absolute (ATOL) */
/* error tolerances to tell the code how accurately you */
/* want the solution to be computed. They must be defined */
/* as variables because the code may change them. */
/* you have two choices -- */
/* Both RTOL and ATOL are scalars (INFO(2) = 0), or */
/* both RTOL and ATOL are vectors (INFO(2) = 1). */
/* In either case all components must be non-negative. */
/* The tolerances are used by the code in a local error */
/* test at each step which requires roughly that */
/* std::abs(local error in Y(i)) .le. EWT(i) , */
/* where EWT(i) = RTOL*std::abs(Y(i)) + ATOL is an error weight */
/* quantity, for each vector component. */
/* (More specifically, a root-mean-square norm is used to */
/* measure the size of vectors, and the error test uses the */
/* magnitude of the solution at the beginning of the step.) */
/* The true (global) error is the difference between the */
/* true solution of the initial value problem and the */
/* computed approximation. Practically all present day */
/* codes, including this one, control the local error at */
/* each step and do not even attempt to control the global */
/* error directly. */
/* Usually, but not always, the true accuracy of */
/* the computed Y is comparable to the error tolerances. */
/* This code will usually, but not always, deliver a more */
/* accurate solution if you reduce the tolerances and */
/* integrate again. By comparing two such solutions you */
/* can get a fairly reliable idea of the true error in the */
/* solution at the larger tolerances. */
/* Setting ATOL = 0. results in a pure relative error test */
/* on that component. Setting RTOL = 0. results in a pure */
/* absolute error test on that component. A mixed test */
/* with non-zero RTOL and ATOL corresponds roughly to a */
/* relative error test when the solution component is */
/* much bigger than ATOL and to an absolute error test */
/* when the solution component is smaller than the */
/* threshold ATOL. */
/* The code will not attempt to compute a solution at an */
/* accuracy unreasonable for the machine being used. It */
/* will advise you if you ask for too much accuracy and */
/* inform you as to the maximum accuracy it believes */
/* possible. */
/* RWORK(*) -- a real work array, which should be dimensioned in your */
/* calling program with a length equal to the value of */
/* LRW (or greater). */
/* LRW -- Set it to the declared length of the RWORK array. The */
/* minimum length depends on the options you have selected, */
/* given by a base value plus additional storage as */
/* described below. */
/* If INFO(12) = 0 (standard direct method), the base value */
/* is BASE = 60 + std::max(MAXORD+4,7)*NEQ + 3*NRT. */
/* The default value is MAXORD = 5 (see INFO(9)). With the */
/* default MAXORD, BASE = 60 + 9*NEQ + 3*NRT. */
/* Additional storage must be added to the base value for */
/* any or all of the following options: */
/* If INFO(6) = 0 (dense matrix), add NEQ**2. */
/* If INFO(6) = 1 (banded matrix), then: */
/* if INFO(5) = 0, add (2*ML+MU+1)*NEQ */
/* + 2*[NEQ/(ML+MU+1) + 1], and */
/* if INFO(5) = 1, add (2*ML+MU+1)*NEQ. */
/* If INFO(16) = 1, add NEQ. */
/* If INFO(12) = 1 (Krylov method), the base value is */
/* BASE = 60 + (MAXORD+5)*NEQ + 3*NRT */
/* + [MAXL + 3 + std::min(1,MAXL-KMP)]*NEQ */
/* + (MAXL+3)*MAXL + 1 + LENWP. */
/* See PSOL for description of LENWP. The default values */
/* are: MAXORD = 5 (see INFO(9)), MAXL = std::min(5,NEQ) and */
/* KMP = MAXL (see INFO(13)). With these default values, */
/* BASE = 101 + 18*NEQ + 3*NRT + LENWP. */
/* Additional storage must be added to the base value for */
/* the following option: */
/* If INFO(16) = 1, add NEQ. */
/* IWORK(*) -- an int work array, which should be dimensioned in */
/* your calling program with a length equal to the value */
/* of LIW (or greater). */
/* LIW -- Set it to the declared length of the IWORK array. The */
/* minimum length depends on the options you have selected, */
/* given by a base value plus additions as described below. */
/* If INFO(12) = 0 (standard direct method), the base value */
/* is BASE = 40 + NEQ. */
/* IF INFO(10) = 1 or 3, add NEQ to the base value. */
/* If INFO(11) = 1 or INFO(16) =1, add NEQ to the base value. */
/* If INFO(12) = 1 (Krylov method), the base value is */
/* BASE = 40 + LENIWP. See PSOL for description of LENIWP. */
/* If INFO(10) = 1 or 3, add NEQ to the base value. */
/* If INFO(11) = 1 or INFO(16) =1, add NEQ to the base value. */
/* par -- These are arrays of double precision and int type, */
/* respectively, which are available for you to use */
/* for communication between your program that calls */
/* DDASKR and the RES subroutine (and the JAC and PSOL */
/* subroutines). They are not altered by DDASKR. */
/* If you do not need RPAR or IPAR, ignore these */
/* parameters by treating them as dummy arguments. */
/* If you do choose to use them, dimension them in */
/* your calling program and in RES (and in JAC and PSOL) */
/* as arrays of appropriate length. */
/* JAC -- This is the name of a routine that you may supply */
/* (optionally) that relates to the Jacobian matrix of the */
/* nonlinear system that the code must solve at each T step. */
/* The role of JAC (and its call sequence) depends on whether */
/* a direct (INFO(12) = 0) or Krylov (INFO(12) = 1) method */
/* is selected. */
/* **** INFO(12) = 0 (direct methods): */
/* If you are letting the code generate partial derivatives */
/* numerically (INFO(5) = 0), then JAC can be absent */
/* (or perhaps a dummy routine to satisfy the loader). */
/* Otherwise you must supply a JAC routine to compute */
/* the matrix A = dG/dY + CJ*dG/dYPRIME. It must have */
/* the form */
/* SUBROUTINE JAC (T, Y, YPRIME, PD, CJ, par) */
/* The JAC routine must dimension Y, YPRIME, and PD (and RPAR */
/* and IPAR if used). CJ is a scalar which is input to JAC. */
/* For the given values of T, Y, and YPRIME, the JAC routine */
/* must evaluate the nonzero elements of the matrix A, and */
/* store these values in the array PD. The elements of PD are */
/* set to zero before each call to JAC, so that only nonzero */
/* elements need to be defined. */
/* The way you store the elements into the PD array depends */
/* on the structure of the matrix indicated by INFO(6). */
/* *** INFO(6) = 0 (full or dense matrix) *** */
/* Give PD a first dimension of NEQ. When you evaluate the */
/* nonzero partial derivatives of equation i (i.e. of G(i)) */
/* with respect to component j (of Y and YPRIME), you must */
/* store the element in PD according to */
/* PD(i,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j). */
/* *** INFO(6) = 1 (banded matrix with half-bandwidths ML, MU */
/* as described under INFO(6)) *** */
/* Give PD a first dimension of 2*ML+MU+1. When you */
/* evaluate the nonzero partial derivatives of equation i */
/* (i.e. of G(i)) with respect to component j (of Y and */
/* YPRIME), you must store the element in PD according to */
/* IROW = i - j + ML + MU + 1 */
/* PD(IROW,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j). */
/* **** INFO(12) = 1 (Krylov method): */
/* If you are not calculating Jacobian data in advance for use */
/* in PSOL (INFO(15) = 0), JAC can be absent (or perhaps a */
/* dummy routine to satisfy the loader). Otherwise, you may */
/* supply a JAC routine to compute and preprocess any parts of */
/* of the Jacobian matrix A = dG/dY + CJ*dG/dYPRIME that are */
/* involved in the preconditioner matrix P. */
/* It is to have the form */
/* SUBROUTINE JAC (RES, IRES, NEQ, T, Y, YPRIME, REWT, SAVR, */
/* WK, H, CJ, WP, IWP, IER, par) */
/* The JAC routine must dimension Y, YPRIME, REWT, SAVR, WK, */
/* and (if used) WP, IWP, RPAR, and IPAR. */
/* The Y, YPRIME, and SAVR arrays contain the current values */
/* of Y, YPRIME, and the residual G, respectively. */
/* The array WK is work space of length NEQ. */
/* H is the step size. CJ is a scalar, input to JAC, that is */
/* normally proportional to 1/H. REWT is an array of */
/* reciprocal error weights, 1/EWT(i), where EWT(i) is */
/* RTOL*std::abs(Y(i)) + ATOL (unless you supplied routine DDAWTS */
/* instead), for use in JAC if needed. For example, if JAC */
/* computes difference quotient approximations to partial */
/* derivatives, the REWT array may be useful in setting the */
/* increments used. The JAC routine should do any */
/* factorization operations called for, in preparation for */
/* solving linear systems in PSOL. The matrix P should */
/* be an approximation to the Jacobian, */
/* A = dG/dY + CJ*dG/dYPRIME. */
/* WP and IWP are real and int work arrays which you may */
/* use for communication between your JAC routine and your */
/* PSOL routine. These may be used to store elements of the */
/* preconditioner P, or related matrix data (such as factored */
/* forms). They are not altered by DDASKR. */
/* If you do not need WP or IWP, ignore these parameters by */
/* treating them as dummy arguments. If you do use them, */
/* dimension them appropriately in your JAC and PSOL routines. */
/* See the PSOL description for instructions on setting */
/* the lengths of WP and IWP. */
/* On return, JAC should set the error flag IER as follows.. */
/* IER = 0 if JAC was successful, */
/* IER .ne. 0 if JAC was unsuccessful (e.g. if Y or YPRIME */
/* was illegal, or a singular matrix is found). */
/* (If IER .ne. 0, a smaller stepsize will be tried.) */
/* IER = 0 on entry to JAC, so need be reset only on a failure. */
/* If RES is used within JAC, then a nonzero value of IRES will */
/* override any nonzero value of IER (see the RES description). */