1 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
2 ! LSODE - Stiff method based on backward differentiation formulas (BDF) !
3 ! By default the code employs the KPP sparse linear algebra routines !
4 ! Compile with -DFULL_ALGEBRA to use full linear algebra (LAPACK) !
5 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
6 ! A. Sandu - version of July 2005
8 MODULE KPP_ROOT_Integrator
10 USE KPP_ROOT_Precision
11 USE KPP_ROOT_Global
, ONLY
: FIX
, RCONST
, TIME
, ATOL
, RTOL
12 USE KPP_ROOT_Parameters
, ONLY
: NVAR
, NSPEC
, NFIX
, LU_NONZERO
13 USE KPP_ROOT_JacobianSP
, ONLY
: LU_DIAG
14 USE KPP_ROOT_LinearAlgebra
, ONLY
: KppDecomp
, KppSolve
, &
21 !~~~> Statistics on the work performed by the LSODE method
22 INTEGER :: Nfun
,Njac
,Nstp
,Nacc
,Nrej
,Ndec
,Nsol
,Nsng
23 INTEGER, PARAMETER :: ifun
=1, ijac
=2, istp
=3, iacc
=4, &
24 irej
=5, idec
=6, isol
=7, isng
=8, itexit
=1, ihexit
=2
25 ! SDIRK method coefficients
26 KPP_REAL
:: rkAlpha(5,4), rkBeta(5,4), rkD(4,5), &
27 rkGamma
, rkA(5,5), rkB(5), rkC(5)
29 ! mz_rs_20050717: TODO: use strings of IERR_NAMES for error messages
30 ! description of the error numbers IERR
31 CHARACTER(LEN
=50), PARAMETER, DIMENSION(-8:1) :: IERR_NAMES
= (/ &
32 'Matrix is repeatedly singular ', & ! -8
33 'Step size too small ', & ! -7
34 'No of steps exceeds maximum bound ', & ! -6
35 'Improper tolerance values ', & ! -5
36 'FacMin/FacMax/FacRej must be positive ', & ! -4
37 'Hmin/Hmax/Hstart must be positive ', & ! -3
38 'Improper value for maximal no of Newton iterations', & ! -2
39 'Improper value for maximal no of steps ', & ! -1
45 SUBROUTINE INTEGRATE( TIN
, TOUT
, &
46 ICNTRL_U
, RCNTRL_U
, ISTATUS_U
, RSTATUS_U
, IERR_U
)
48 USE KPP_ROOT_Parameters
52 KPP_REAL
, INTENT(IN
) :: TIN
! Start Time
53 KPP_REAL
, INTENT(IN
) :: TOUT
! End Time
54 ! Optional input parameters and statistics
55 INTEGER, INTENT(IN
), OPTIONAL
:: ICNTRL_U(20)
56 KPP_REAL
, INTENT(IN
), OPTIONAL
:: RCNTRL_U(20)
57 INTEGER, INTENT(OUT
), OPTIONAL
:: ISTATUS_U(20)
58 KPP_REAL
, INTENT(OUT
), OPTIONAL
:: RSTATUS_U(20)
59 INTEGER, INTENT(OUT
), OPTIONAL
:: IERR_U
61 KPP_REAL
:: RCNTRL(20), RSTATUS(20)
62 INTEGER :: ICNTRL(20), ISTATUS(20), IERR
63 !!$ INTEGER, SAVE :: Ntotal = 0
70 ICNTRL(5) = 2 ! maximal order
72 ! If optional parameters are given, and if they are >0,
73 ! then they overwrite default settings.
74 IF (PRESENT(ICNTRL_U
)) THEN
75 WHERE(ICNTRL_U(:) > 0) ICNTRL(:) = ICNTRL_U(:)
77 IF (PRESENT(RCNTRL_U
)) THEN
78 WHERE(RCNTRL_U(:) > 0) RCNTRL(:) = RCNTRL_U(:)
81 CALL KppLsode( TIN
,TOUT
,VAR
,RTOL
,ATOL
, &
82 RCNTRL
,ICNTRL
,RSTATUS
,ISTATUS
,IERR
)
84 ! mz_rs_20050716: IERR and ISTATUS are returned to the user who then
85 ! decides what to do about it, i.e. either stop the run or ignore it.
86 !!$ IF (IERR < 0) THEN
87 !!$ PRINT*,'LSODE: Unsuccessful exit at T=',TIN,' (IERR=',IERR,')'
90 !!$ Ntotal = Ntotal + ISTATUS(3)
91 !!$ PRINT*,'Nsteps = ', ISTATUS(3),' (',Ntotal,')'
93 STEPMIN
= RSTATUS(ihexit
) ! Save last step
95 ! if optional parameters are given for output they to return information
96 IF (PRESENT(ISTATUS_U
)) ISTATUS_U(:) = ISTATUS(1:20)
97 IF (PRESENT(RSTATUS_U
)) RSTATUS_U(:) = RSTATUS(1:20)
98 IF (PRESENT(IERR_U
)) IERR_U
= IERR
100 END SUBROUTINE INTEGRATE
102 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
103 SUBROUTINE KppLsode( TIN
,TOUT
,Y
,RelTol
,AbsTol
, &
104 RCNTRL
,ICNTRL
,RSTATUS
,ISTATUS
,IERR
)
105 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107 !~~~> INPUT PARAMETERS:
109 ! Note: For input parameters equal to zero the default values of the
110 ! corresponding variables are used.
112 ! Note: For input parameters equal to zero the default values of the
113 ! corresponding variables are used.
115 ! ICNTRL(1) = not used
117 ! ICNTRL(2) = 0: AbsTol, RelTol are NVAR-dimensional vectors
118 ! = 1: AbsTol, RelTol are scalars
120 ! ICNTRL(3) = not used
122 ! ICNTRL(4) -> maximum number of integration steps
123 ! For ICNTRL(4)=0 the default value of 100000 is used
125 ! ICNTRL(5) -> maximum order of the integration formula allowed
127 !~~~> Real parameters
129 ! RCNTRL(1) -> Hmin, lower bound for the integration step size
130 ! It is strongly recommended to keep Hmin = ZERO
131 ! RCNTRL(2) -> Hmax, upper bound for the integration step size
132 ! RCNTRL(3) -> Hstart, starting value for the integration step size
134 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
136 !~~~> OUTPUT PARAMETERS:
138 ! Note: each call to Rosenbrock adds the current no. of fcn calls
139 ! to previous value of ISTATUS(1), and similar for the other params.
140 ! Set ISTATUS(1:10) = 0 before call to avoid this accumulation.
142 ! ISTATUS(1) = No. of function calls
143 ! ISTATUS(2) = No. of jacobian calls
144 ! ISTATUS(3) = No. of steps
146 ! RSTATUS(1) -> Texit, the time corresponding to the
147 ! computed Y upon return
148 ! RSTATUS(2) -> Hexit, last predicted step before exit
149 ! For multiple restarts, use Hexit as Hstart in the following run
151 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154 KPP_REAL
:: Y(NVAR
), AbsTol(NVAR
), RelTol(NVAR
), TIN
, TOUT
155 KPP_REAL
:: RCNTRL(20), RSTATUS(20)
156 INTEGER :: ICNTRL(20), ISTATUS(20)
157 INTEGER, PARAMETER :: LRW
= 25 + 9*NVAR
+2*NVAR
*NVAR
, &
159 KPP_REAL
:: RWORK(LRW
), RPAR(1)
160 INTEGER :: IWORK(LIW
), IPAR(1), ITOL
, ITASK
, &
163 !~~~> NORMAL COMPUTATION
166 IOPT
= 1 ! 0=no/1=use optional input
171 IF (ICNTRL(2)==0) THEN
172 ITOL
= 4 ! Abs/RelTol are both vectors
174 ITOL
= 1 ! Abs/RelTol are both scalars
176 IWORK(6) = ICNTRL(4) ! max number of internal steps
177 IWORK(5) = ICNTRL(5) ! maximal order
179 MF
= 21 !~~~> stiff case, analytic full Jacobian
181 RWORK(5) = RCNTRL(3) ! Hstart
182 RWORK(6) = RCNTRL(2) ! Hmax
183 RWORK(7) = RCNTRL(1) ! Hmin
185 CALL DLSODE ( FUN_CHEM
, NVAR
, Y
, TIN
, TOUT
, ITOL
, RelTol
, AbsTol
, ITASK
,&
186 IERR
, IOPT
, RWORK
, LRW
, IWORK
, LIW
, JAC_CHEM
, MF
)
188 ISTATUS(1) = IWORK(12) ! Number of function evaluations
189 ISTATUS(2) = IWORK(13) ! Number of Jacobian evaluations
190 ISTATUS(3) = IWORK(11) ! Number of steps
192 RSTATUS(1) = TOUT
! mz_rs_20050717
193 RSTATUS(2) = RWORK(11) ! mz_rs_20050717
195 END SUBROUTINE KppLsode
196 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
199 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201 SUBROUTINE DLSODE (F
, NEQ
, Y
, T
, TOUT
, ITOL
, RelTol
, AbsTol
, ITASK
, &
202 ISTATE
, IOPT
, RWORK
, LRW
, IWORK
, LIW
, JAC
, MF
)
204 INTEGER NEQ
, ITOL
, ITASK
, ISTATE
, IOPT
, LRW
, LIW
, IWORK(LIW
), MF
205 KPP_REAL
Y(*), T
, TOUT
, RelTol(*), AbsTol(*), RWORK(LRW
)
206 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207 !***BEGIN PROLOGUE DLSODE
208 !***PURPOSE Livermore Solver for Ordinary Differential Equations.
209 ! DLSODE solves the initial-value problem for stiff or
210 ! nonstiff systems of first-order ODE's,
211 ! dy/dt = f(t,y), or, in component form,
212 ! dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(N)), i=1,...,N.
214 !***TYPE KPP_REAL (SLSODE-S, DLSODE-D)
215 !***KEYWORDS ORDINARY DIFFERENTIAL EQUATIONS, INITIAL VALUE PROBLEM,
217 !***AUTHOR Hindmarsh, Alan C., (LLNL)
218 ! Center for Applied Scientific Computing, L-561
219 ! Lawrence Livermore National Laboratory
220 ! Livermore, CA 94551.
223 ! NOTE: The "Usage" and "Arguments" sections treat only a subset of
224 ! available options, in condensed fashion. The options
225 ! covered and the information supplied will support most
226 ! standard uses of DLSODE.
228 ! For more sophisticated uses, full details on all options are
229 ! given in the concluding section, headed "Long Description."
230 ! A synopsis of the DLSODE Long Description is provided at the
231 ! beginning of that section; general topics covered are:
232 ! - Elements of the call sequence; optional input and output
233 ! - Optional supplemental routines in the DLSODE package
234 ! - internal COMMON block
237 ! Communication between the user and the DLSODE package, for normal
238 ! situations, is summarized here. This summary describes a subset
239 ! of the available options. See "Long Description" for complete
240 ! details, including optional communication, nonstandard options,
241 ! and instructions for special situations.
243 ! A sample program is given in the "Examples" section.
245 ! Refer to the argument descriptions for the definitions of the
246 ! quantities that appear in the following sample declarations.
249 ! PARAMETER (LRW = 20 + 16*NEQ, LIW = 20)
251 ! PARAMETER (LRW = 22 + 9*NEQ + NEQ**2, LIW = 20 + NEQ)
253 ! PARAMETER (LRW = 22 + 10*NEQ + (2*ML+MU)*NEQ,
257 ! INTEGER NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK(LIW),
259 ! KPP_REAL Y(NEQ), T, TOUT, RelTol, AbsTol(ntol), RWORK(LRW)
261 ! CALL DLSODE (F, NEQ, Y, T, TOUT, ITOL, RelTol, AbsTol, ITASK,
262 ! * ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF)
265 ! F :EXT Name of subroutine for right-hand-side vector f.
266 ! This name must be declared EXTERNAL in calling
267 ! program. The form of F must be:
269 ! SUBROUTINE F (NEQ, T, Y, YDOT)
271 ! KPP_REAL T, Y(*), YDOT(*)
273 ! The inputs are NEQ, T, Y. F is to set
275 ! YDOT(i) = f(i,T,Y(1),Y(2),...,Y(NEQ)),
278 ! NEQ :IN Number of first-order ODE's.
280 ! Y :INOUT Array of values of the y(t) vector, of length NEQ.
281 ! Input: For the first call, Y should contain the
282 ! values of y(t) at t = T. (Y is an input
283 ! variable only if ISTATE = 1.)
284 ! Output: On return, Y will contain the values at the
287 ! T :INOUT Value of the independent variable. On return it
288 ! will be the current value of t (normally TOUT).
290 ! TOUT :IN Next point where output is desired (.NE. T).
292 ! ITOL :IN 1 or 2 according as AbsTol (below) is a scalar or
295 ! RelTol :IN Relative tolerance parameter (scalar).
297 ! AbsTol :IN Absolute tolerance parameter (scalar or array).
298 ! If ITOL = 1, AbsTol need not be dimensioned.
299 ! If ITOL = 2, AbsTol must be dimensioned at least NEQ.
301 ! The estimated local error in Y(i) will be controlled
302 ! so as to be roughly less (in magnitude) than
304 ! EWT(i) = RelTol*ABS(Y(i)) + AbsTol if ITOL = 1, or
305 ! EWT(i) = RelTol*ABS(Y(i)) + AbsTol(i) if ITOL = 2.
307 ! Thus the local error test passes if, in each
308 ! component, either the absolute error is less than
309 ! AbsTol (or AbsTol(i)), or the relative error is less
312 ! Use RelTol = 0.0 for pure absolute error control, and
313 ! use AbsTol = 0.0 (or AbsTol(i) = 0.0) for pure relative
314 ! error control. Caution: Actual (global) errors may
315 ! exceed these local tolerances, so choose them
318 ! ITASK :IN Flag indicating the task DLSODE is to perform.
319 ! Use ITASK = 1 for normal computation of output
320 ! values of y at t = TOUT.
322 ! ISTATE:INOUT Index used for input and output to specify the state
323 ! of the calculation.
325 ! 1 This is the first call for a problem.
326 ! 2 This is a subsequent call.
328 ! 1 Nothing was done, because TOUT was equal to T.
329 ! 2 DLSODE was successful (otherwise, negative).
330 ! Note that ISTATE need not be modified after a
332 ! -1 Excess work done on this call (perhaps wrong
334 ! -2 Excess accuracy requested (tolerances too
336 ! -3 Illegal input detected (see printed message).
337 ! -4 Repeated error test failures (check all
339 ! -5 Repeated convergence failures (perhaps bad
340 ! Jacobian supplied or wrong choice of MF or
342 ! -6 Error weight became zero during problem
343 ! (solution component i vanished, and AbsTol or
346 ! IOPT :IN Flag indicating whether optional inputs are used:
348 ! 1 Yes. (See "Optional inputs" under "Long
349 ! Description," Part 1.)
351 ! RWORK :WORK Real work array of length at least:
352 ! 20 + 16*NEQ for MF = 10,
353 ! 22 + 9*NEQ + NEQ**2 for MF = 21 or 22,
354 ! 22 + 10*NEQ + (2*ML + MU)*NEQ for MF = 24 or 25.
356 ! LRW :IN Declared length of RWORK (in user's DIMENSION
359 ! IWORK :WORK Integer work array of length at least:
361 ! 20 + NEQ for MF = 21, 22, 24, or 25.
363 ! If MF = 24 or 25, input in IWORK(1),IWORK(2) the
364 ! lower and upper Jacobian half-bandwidths ML,MU.
366 ! On return, IWORK contains information that may be
367 ! of interest to the user:
369 ! Name Location Meaning
370 ! ----- --------- -----------------------------------------
371 ! NST IWORK(11) Number of steps taken for the problem so
373 ! NFE IWORK(12) Number of f evaluations for the problem
375 ! NJE IWORK(13) Number of Jacobian evaluations (and of
376 ! matrix LU decompositions) for the problem
378 ! NQU IWORK(14) Method order last used (successfully).
379 ! LENRW IWORK(17) Length of RWORK actually required. This
380 ! is defined on normal returns and on an
381 ! illegal input return for insufficient
383 ! LENIW IWORK(18) Length of IWORK actually required. This
384 ! is defined on normal returns and on an
385 ! illegal input return for insufficient
388 ! LIW :IN Declared length of IWORK (in user's DIMENSION
391 ! JAC :EXT Name of subroutine for Jacobian matrix (MF =
392 ! 21 or 24). If used, this name must be declared
393 ! EXTERNAL in calling program. If not used, pass a
394 ! dummy name. The form of JAC must be:
396 ! SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)
397 ! INTEGER NEQ, ML, MU, NROWPD
398 ! KPP_REAL T, Y(*), PD(NROWPD,*)
400 ! See item c, under "Description" below for more
401 ! information about JAC.
403 ! MF :IN Method flag. Standard values are:
404 ! 10 Nonstiff (Adams) method, no Jacobian used.
405 ! 21 Stiff (BDF) method, user-supplied full Jacobian.
406 ! 22 Stiff method, internally generated full
408 ! 24 Stiff method, user-supplied banded Jacobian.
409 ! 25 Stiff method, internally generated banded
413 ! DLSODE solves the initial value problem for stiff or nonstiff
414 ! systems of first-order ODE's,
418 ! or, in component form,
420 ! dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ))
421 ! (i = 1, ..., NEQ) .
423 ! DLSODE is a package based on the GEAR and GEARB packages, and on
424 ! the October 23, 1978, version of the tentative ODEPACK user
425 ! interface standard, with minor modifications.
427 ! The steps in solving such a problem are as follows.
429 ! a. First write a subroutine of the form
431 ! SUBROUTINE F (NEQ, T, Y, YDOT)
433 ! KPP_REAL T, Y(*), YDOT(*)
435 ! which supplies the vector function f by loading YDOT(i) with
438 ! b. Next determine (or guess) whether or not the problem is stiff.
439 ! Stiffness occurs when the Jacobian matrix df/dy has an
440 ! eigenvalue whose real part is negative and large in magnitude
441 ! compared to the reciprocal of the t span of interest. If the
442 ! problem is nonstiff, use method flag MF = 10. If it is stiff,
443 ! there are four standard choices for MF, and DLSODE requires the
444 ! Jacobian matrix in some form. This matrix is regarded either
445 ! as full (MF = 21 or 22), or banded (MF = 24 or 25). In the
446 ! banded case, DLSODE requires two half-bandwidth parameters ML
447 ! and MU. These are, respectively, the widths of the lower and
448 ! upper parts of the band, excluding the main diagonal. Thus the
449 ! band consists of the locations (i,j) with
451 ! i - ML <= j <= i + MU ,
453 ! and the full bandwidth is ML + MU + 1 .
455 ! c. If the problem is stiff, you are encouraged to supply the
456 ! Jacobian directly (MF = 21 or 24), but if this is not feasible,
457 ! DLSODE will compute it internally by difference quotients (MF =
458 ! 22 or 25). If you are supplying the Jacobian, write a
459 ! subroutine of the form
461 ! SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)
462 ! INTEGER NEQ, ML, MU, NRWOPD
463 ! KPP_REAL T, Y(*), PD(NROWPD,*)
465 ! which provides df/dy by loading PD as follows:
466 ! - For a full Jacobian (MF = 21), load PD(i,j) with df(i)/dy(j),
467 ! the partial derivative of f(i) with respect to y(j). (Ignore
468 ! the ML and MU arguments in this case.)
469 ! - For a banded Jacobian (MF = 24), load PD(i-j+MU+1,j) with
470 ! df(i)/dy(j); i.e., load the diagonal lines of df/dy into the
471 ! rows of PD from the top down.
472 ! - In either case, only nonzero elements need be loaded.
474 ! d. Write a main program that calls subroutine DLSODE once for each
475 ! point at which answers are desired. This should also provide
476 ! for possible use of logical unit 6 for output of error messages
479 ! Before the first call to DLSODE, set ISTATE = 1, set Y and T to
480 ! the initial values, and set TOUT to the first output point. To
481 ! continue the integration after a successful return, simply
482 ! reset TOUT and call DLSODE again. No other parameters need be
486 ! The following is a simple example problem, with the coding needed
487 ! for its solution by DLSODE. The problem is from chemical kinetics,
488 ! and consists of the following three rate equations:
490 ! dy1/dt = -.04*y1 + 1.E4*y2*y3
491 ! dy2/dt = .04*y1 - 1.E4*y2*y3 - 3.E7*y2**2
492 ! dy3/dt = 3.E7*y2**2
494 ! on the interval from t = 0.0 to t = 4.E10, with initial conditions
495 ! y1 = 1.0, y2 = y3 = 0. The problem is stiff.
497 ! The following coding solves this problem with DLSODE, using
498 ! MF = 21 and printing results at t = .4, 4., ..., 4.E10. It uses
499 ! ITOL = 2 and AbsTol much smaller for y2 than for y1 or y3 because y2
500 ! has much smaller values. At the end of the run, statistical
501 ! quantities of interest are printed.
504 ! INTEGER IOPT, IOUT, ISTATE, ITASK, ITOL, IWORK(23), LIW, LRW,
506 ! KPP_REAL AbsTol(3), RelTol, RWORK(58), T, TOUT, Y(3)
525 ! CALL DLSODE (FEX, NEQ, Y, T, TOUT, ITOL, RelTol, AbsTol, ITASK,
526 ! * ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JEX, MF)
527 ! WRITE(6,20) T, Y(1), Y(2), Y(3)
528 ! 20 FORMAT(' At t =',D12.4,' y =',3D14.6)
529 ! IF (ISTATE .LT. 0) GO TO 80
530 ! 40 TOUT = TOUT*10.D0
531 ! WRITE(6,60) IWORK(11), IWORK(12), IWORK(13)
532 ! 60 FORMAT(/' No. steps =',i4,', No. f-s =',i4,', No. J-s =',i4)
534 ! 80 WRITE(6,90) ISTATE
535 ! 90 FORMAT(///' Error halt.. ISTATE =',I3)
539 ! SUBROUTINE FEX (NEQ, T, Y, YDOT)
541 ! KPP_REAL T, Y(3), YDOT(3)
542 ! YDOT(1) = -.04D0*Y(1) + 1.D4*Y(2)*Y(3)
543 ! YDOT(3) = 3.D7*Y(2)*Y(2)
544 ! YDOT(2) = -YDOT(1) - YDOT(3)
548 ! SUBROUTINE JEX (NEQ, T, Y, ML, MU, PD, NRPD)
549 ! INTEGER NEQ, ML, MU, NRPD
550 ! KPP_REAL T, Y(3), PD(NRPD,3)
552 ! PD(1,2) = 1.D4*Y(3)
553 ! PD(1,3) = 1.D4*Y(2)
556 ! PD(3,2) = 6.D7*Y(2)
557 ! PD(2,2) = -PD(1,2) - PD(3,2)
561 ! The output from this program (on a Cray-1 in single precision)
564 ! At t = 4.0000e-01 y = 9.851726e-01 3.386406e-05 1.479357e-02
565 ! At t = 4.0000e+00 y = 9.055142e-01 2.240418e-05 9.446344e-02
566 ! At t = 4.0000e+01 y = 7.158050e-01 9.184616e-06 2.841858e-01
567 ! At t = 4.0000e+02 y = 4.504846e-01 3.222434e-06 5.495122e-01
568 ! At t = 4.0000e+03 y = 1.831701e-01 8.940379e-07 8.168290e-01
569 ! At t = 4.0000e+04 y = 3.897016e-02 1.621193e-07 9.610297e-01
570 ! At t = 4.0000e+05 y = 4.935213e-03 1.983756e-08 9.950648e-01
571 ! At t = 4.0000e+06 y = 5.159269e-04 2.064759e-09 9.994841e-01
572 ! At t = 4.0000e+07 y = 5.306413e-05 2.122677e-10 9.999469e-01
573 ! At t = 4.0000e+08 y = 5.494530e-06 2.197825e-11 9.999945e-01
574 ! At t = 4.0000e+09 y = 5.129458e-07 2.051784e-12 9.999995e-01
575 ! At t = 4.0000e+10 y = -7.170603e-08 -2.868241e-13 1.000000e+00
577 ! No. steps = 330, No. f-s = 405, No. J-s = 69
580 ! The accuracy of the solution depends on the choice of tolerances
581 ! RelTol and AbsTol. Actual (global) errors may exceed these local
582 ! tolerances, so choose them conservatively.
585 ! The work arrays should not be altered between calls to DLSODE for
586 ! the same problem, except possibly for the conditional and optional
590 ! Since NEQ is dimensioned inside DLSODE, some compilers may object
591 ! to a call to DLSODE with NEQ a scalar variable. In this event,
592 ! use DIMENSION NEQ. Similar remarks apply to RelTol and AbsTol.
594 ! Note to Cray users:
595 ! For maximum efficiency, use the CFT77 compiler. Appropriate
596 ! compiler optimization directives have been inserted for CFT77.
599 ! Alan C. Hindmarsh, "ODEPACK, A Systematized Collection of ODE
600 ! Solvers," in Scientific Computing, R. S. Stepleman, et al., Eds.
601 ! (North-Holland, Amsterdam, 1983), pp. 55-64.
604 ! The following complete description of the user interface to
605 ! DLSODE consists of four parts:
607 ! 1. The call sequence to subroutine DLSODE, which is a driver
608 ! routine for the solver. This includes descriptions of both
609 ! the call sequence arguments and user-supplied routines.
610 ! Following these descriptions is a description of optional
611 ! inputs available through the call sequence, and then a
612 ! description of optional outputs in the work arrays.
614 ! 2. Descriptions of other routines in the DLSODE package that may
615 ! be (optionally) called by the user. These provide the ability
616 ! to alter error message handling, save and restore the internal
617 ! COMMON, and obtain specified derivatives of the solution y(t).
619 ! 3. Descriptions of COMMON block to be declared in overlay or
620 ! similar environments, or to be saved when doing an interrupt
621 ! of the problem and continued solution later.
623 ! 4. Description of two routines in the DLSODE package, either of
624 ! which the user may replace with his own version, if desired.
625 ! These relate to the measurement of errors.
628 ! Part 1. Call Sequence
629 ! ----------------------
633 ! The call sequence parameters used for input only are
635 ! F, NEQ, TOUT, ITOL, RelTol, AbsTol, ITASK, IOPT, LRW, LIW, JAC, MF,
637 ! and those used for both input and output are
641 ! The work arrays RWORK and IWORK are also used for conditional and
642 ! optional inputs and optional outputs. (The term output here
643 ! refers to the return from subroutine DLSODE to the user's calling
646 ! The legality of input parameters will be thoroughly checked on the
647 ! initial call for the problem, but not checked thereafter unless a
648 ! change in input parameters is flagged by ISTATE = 3 on input.
650 ! The descriptions of the call arguments are as follows.
652 ! F The name of the user-supplied subroutine defining the ODE
653 ! system. The system must be put in the first-order form
654 ! dy/dt = f(t,y), where f is a vector-valued function of
655 ! the scalar t and the vector y. Subroutine F is to compute
656 ! the function f. It is to have the form
658 ! SUBROUTINE F (NEQ, T, Y, YDOT)
659 ! KPP_REAL T, Y(*), YDOT(*)
661 ! where NEQ, T, and Y are input, and the array YDOT =
662 ! f(T,Y) is output. Y and YDOT are arrays of length NEQ.
663 ! Subroutine F should not alter Y(1),...,Y(NEQ). F must be
664 ! declared EXTERNAL in the calling program.
666 ! Subroutine F may access user-defined quantities in
667 ! NEQ(2),... and/or in Y(NEQ+1),..., if NEQ is an array
668 ! (dimensioned in F) and/or Y has length exceeding NEQ.
669 ! See the descriptions of NEQ and Y below.
671 ! If quantities computed in the F routine are needed
672 ! externally to DLSODE, an extra call to F should be made
673 ! for this purpose, for consistent and accurate results.
674 ! If only the derivative dy/dt is needed, use DINTDY
677 ! NEQ The size of the ODE system (number of first-order
678 ! ordinary differential equations). Used only for input.
679 ! NEQ may be decreased, but not increased, during the
680 ! problem. If NEQ is decreased (with ISTATE = 3 on input),
681 ! the remaining components of Y should be left undisturbed,
682 ! if these are to be accessed in F and/or JAC.
684 ! Normally, NEQ is a scalar, and it is generally referred
685 ! to as a scalar in this user interface description.
686 ! However, NEQ may be an array, with NEQ set to the
687 ! system size. (The DLSODE package accesses only NEQ.)
688 ! In either case, this parameter is passed as the NEQ
689 ! argument in all calls to F and JAC. Hence, if it is an
690 ! array, locations NEQ(2),... may be used to store other
691 ! integer data and pass it to F and/or JAC. Subroutines
692 ! F and/or JAC must include NEQ in a DIMENSION statement
695 ! Y A real array for the vector of dependent variables, of
696 ! length NEQ or more. Used for both input and output on
697 ! the first call (ISTATE = 1), and only for output on
698 ! other calls. On the first call, Y must contain the
699 ! vector of initial values. On output, Y contains the
700 ! computed solution vector, evaluated at T. If desired,
701 ! the Y array may be used for other purposes between
702 ! calls to the solver.
704 ! This array is passed as the Y argument in all calls to F
705 ! and JAC. Hence its length may exceed NEQ, and locations
706 ! Y(NEQ+1),... may be used to store other real data and
707 ! pass it to F and/or JAC. (The DLSODE package accesses
708 ! only Y(1),...,Y(NEQ).)
710 ! T The independent variable. On input, T is used only on
711 ! the first call, as the initial point of the integration.
712 ! On output, after each call, T is the value at which a
713 ! computed solution Y is evaluated (usually the same as
714 ! TOUT). On an error return, T is the farthest point
717 ! TOUT The next value of T at which a computed solution is
718 ! desired. Used only for input.
720 ! When starting the problem (ISTATE = 1), TOUT may be equal
721 ! to T for one call, then should not equal T for the next
722 ! call. For the initial T, an input value of TOUT .NE. T
723 ! is used in order to determine the direction of the
724 ! integration (i.e., the algebraic sign of the step sizes)
725 ! and the rough scale of the problem. Integration in
726 ! either direction (forward or backward in T) is permitted.
728 ! If ITASK = 2 or 5 (one-step modes), TOUT is ignored
729 ! after the first call (i.e., the first call with
730 ! TOUT .NE. T). Otherwise, TOUT is required on every call.
732 ! If ITASK = 1, 3, or 4, the values of TOUT need not be
733 ! monotone, but a value of TOUT which backs up is limited
734 ! to the current internal T interval, whose endpoints are
735 ! TCUR - HU and TCUR. (See "Optional Outputs" below for
739 ! ITOL An indicator for the type of error control. See
740 ! description below under AbsTol. Used only for input.
742 ! RelTol A relative error tolerance parameter, either a scalar or
743 ! an array of length NEQ. See description below under
744 ! AbsTol. Input only.
746 ! AbsTol An absolute error tolerance parameter, either a scalar or
747 ! an array of length NEQ. Input only.
749 ! The input parameters ITOL, RelTol, and AbsTol determine the
750 ! error control performed by the solver. The solver will
751 ! control the vector e = (e(i)) of estimated local errors
752 ! in Y, according to an inequality of the form
754 ! rms-norm of ( e(i)/EWT(i) ) <= 1,
758 ! EWT(i) = RelTol(i)*ABS(Y(i)) + AbsTol(i),
760 ! and the rms-norm (root-mean-square norm) here is
762 ! rms-norm(v) = SQRT(sum v(i)**2 / NEQ).
764 ! Here EWT = (EWT(i)) is a vector of weights which must
765 ! always be positive, and the values of RelTol and AbsTol
766 ! should all be nonnegative. The following table gives the
767 ! types (scalar/array) of RelTol and AbsTol, and the
768 ! corresponding form of EWT(i).
770 ! ITOL RelTol AbsTol EWT(i)
771 ! ---- ------ ------ -----------------------------
772 ! 1 scalar scalar RelTol*ABS(Y(i)) + AbsTol
773 ! 2 scalar array RelTol*ABS(Y(i)) + AbsTol(i)
774 ! 3 array scalar RelTol(i)*ABS(Y(i)) + AbsTol
775 ! 4 array array RelTol(i)*ABS(Y(i)) + AbsTol(i)
777 ! When either of these parameters is a scalar, it need not
778 ! be dimensioned in the user's calling program.
780 ! If none of the above choices (with ITOL, RelTol, and AbsTol
781 ! fixed throughout the problem) is suitable, more general
782 ! error controls can be obtained by substituting
783 ! user-supplied routines for the setting of EWT and/or for
784 ! the norm calculation. See Part 4 below.
786 ! If global errors are to be estimated by making a repeated
787 ! run on the same problem with smaller tolerances, then all
788 ! components of RelTol and AbsTol (i.e., of EWT) should be
789 ! scaled down uniformly.
791 ! ITASK An index specifying the task to be performed. Input
792 ! only. ITASK has the following values and meanings:
793 ! 1 Normal computation of output values of y(t) at
794 ! t = TOUT (by overshooting and interpolating).
795 ! 2 Take one step only and return.
796 ! 3 Stop at the first internal mesh point at or beyond
797 ! t = TOUT and return.
798 ! 4 Normal computation of output values of y(t) at
799 ! t = TOUT but without overshooting t = TCRIT. TCRIT
800 ! must be input as RWORK(1). TCRIT may be equal to or
801 ! beyond TOUT, but not behind it in the direction of
802 ! integration. This option is useful if the problem
803 ! has a singularity at or beyond t = TCRIT.
804 ! 5 Take one step, without passing TCRIT, and return.
805 ! TCRIT must be input as RWORK(1).
807 ! Note: If ITASK = 4 or 5 and the solver reaches TCRIT
808 ! (within roundoff), it will return T = TCRIT (exactly) to
809 ! indicate this (unless ITASK = 4 and TOUT comes before
810 ! TCRIT, in which case answers at T = TOUT are returned
813 ! ISTATE An index used for input and output to specify the state
814 ! of the calculation.
816 ! On input, the values of ISTATE are as follows:
817 ! 1 This is the first call for the problem
818 ! (initializations will be done). See "Note" below.
819 ! 2 This is not the first call, and the calculation is to
820 ! continue normally, with no change in any input
821 ! parameters except possibly TOUT and ITASK. (If ITOL,
822 ! RelTol, and/or AbsTol are changed between calls with
823 ! ISTATE = 2, the new values will be used but not
824 ! tested for legality.)
825 ! 3 This is not the first call, and the calculation is to
826 ! continue normally, but with a change in input
827 ! parameters other than TOUT and ITASK. Changes are
828 ! allowed in NEQ, ITOL, RelTol, AbsTol, IOPT, LRW, LIW, MF,
829 ! ML, MU, and any of the optional inputs except H0.
830 ! (See IWORK description for ML and MU.)
832 ! Note: A preliminary call with TOUT = T is not counted as
833 ! a first call here, as no initialization or checking of
834 ! input is done. (Such a call is sometimes useful for the
835 ! purpose of outputting the initial conditions.) Thus the
836 ! first call for which TOUT .NE. T requires ISTATE = 1 on
839 ! On output, ISTATE has the following values and meanings:
840 ! 1 Nothing was done, as TOUT was equal to T with
841 ! ISTATE = 1 on input.
842 ! 2 The integration was performed successfully.
843 ! -1 An excessive amount of work (more than MXSTEP steps)
844 ! was done on this call, before completing the
845 ! requested task, but the integration was otherwise
846 ! successful as far as T. (MXSTEP is an optional input
847 ! and is normally 500.) To continue, the user may
848 ! simply reset ISTATE to a value >1 and call again (the
849 ! excess work step counter will be reset to 0). In
850 ! addition, the user may increase MXSTEP to avoid this
851 ! error return; see "Optional Inputs" below.
852 ! -2 Too much accuracy was requested for the precision of
853 ! the machine being used. This was detected before
854 ! completing the requested task, but the integration
855 ! was successful as far as T. To continue, the
856 ! tolerance parameters must be reset, and ISTATE must
857 ! be set to 3. The optional output TOLSF may be used
858 ! for this purpose. (Note: If this condition is
859 ! detected before taking any steps, then an illegal
860 ! input return (ISTATE = -3) occurs instead.)
861 ! -3 Illegal input was detected, before taking any
862 ! integration steps. See written message for details.
863 ! (Note: If the solver detects an infinite loop of
864 ! calls to the solver with illegal input, it will cause
866 ! -4 There were repeated error-test failures on one
867 ! attempted step, before completing the requested task,
868 ! but the integration was successful as far as T. The
869 ! problem may have a singularity, or the input may be
871 ! -5 There were repeated convergence-test failures on one
872 ! attempted step, before completing the requested task,
873 ! but the integration was successful as far as T. This
874 ! may be caused by an inaccurate Jacobian matrix, if
876 ! -6 EWT(i) became zero for some i during the integration.
877 ! Pure relative error control (AbsTol(i)=0.0) was
878 ! requested on a variable which has now vanished. The
879 ! integration was successful as far as T.
881 ! Note: Since the normal output value of ISTATE is 2, it
882 ! does not need to be reset for normal continuation. Also,
883 ! since a negative input value of ISTATE will be regarded
884 ! as illegal, a negative output value requires the user to
885 ! change it, and possibly other inputs, before calling the
888 ! IOPT An integer flag to specify whether any optional inputs
889 ! are being used on this call. Input only. The optional
890 ! inputs are listed under a separate heading below.
891 ! 0 No optional inputs are being used. Default values
892 ! will be used in all cases.
893 ! 1 One or more optional inputs are being used.
895 ! RWORK A real working array (double precision). The length of
896 ! RWORK must be at least
898 ! 20 + NYH*(MAXORD + 1) + 3*NEQ + LWM
901 ! NYH = the initial value of NEQ,
902 ! MAXORD = 12 (if METH = 1) or 5 (if METH = 2) (unless a
903 ! smaller value is given as an optional input),
904 ! LWM = 0 if MITER = 0,
905 ! LWM = NEQ**2 + 2 if MITER = 1 or 2,
906 ! LWM = NEQ + 2 if MITER = 3, and
907 ! LWM = (2*ML + MU + 1)*NEQ + 2
909 ! (See the MF description below for METH and MITER.)
911 ! Thus if MAXORD has its default value and NEQ is constant,
913 ! 20 + 16*NEQ for MF = 10,
914 ! 22 + 16*NEQ + NEQ**2 for MF = 11 or 12,
915 ! 22 + 17*NEQ for MF = 13,
916 ! 22 + 17*NEQ + (2*ML + MU)*NEQ for MF = 14 or 15,
917 ! 20 + 9*NEQ for MF = 20,
918 ! 22 + 9*NEQ + NEQ**2 for MF = 21 or 22,
919 ! 22 + 10*NEQ for MF = 23,
920 ! 22 + 10*NEQ + (2*ML + MU)*NEQ for MF = 24 or 25.
922 ! The first 20 words of RWORK are reserved for conditional
923 ! and optional inputs and optional outputs.
925 ! The following word in RWORK is a conditional input:
926 ! RWORK(1) = TCRIT, the critical value of t which the
927 ! solver is not to overshoot. Required if ITASK
928 ! is 4 or 5, and ignored otherwise. See ITASK.
930 ! LRW The length of the array RWORK, as declared by the user.
931 ! (This will be checked by the solver.)
933 ! IWORK An integer work array. Its length must be at least
934 ! 20 if MITER = 0 or 3 (MF = 10, 13, 20, 23), or
935 ! 20 + NEQ otherwise (MF = 11, 12, 14, 15, 21, 22, 24, 25).
936 ! (See the MF description below for MITER.) The first few
937 ! words of IWORK are used for conditional and optional
938 ! inputs and optional outputs.
940 ! The following two words in IWORK are conditional inputs:
941 ! IWORK(1) = ML These are the lower and upper half-
942 ! IWORK(2) = MU bandwidths, respectively, of the banded
943 ! Jacobian, excluding the main diagonal.
944 ! The band is defined by the matrix locations
945 ! (i,j) with i - ML <= j <= i + MU. ML and MU
946 ! must satisfy 0 <= ML,MU <= NEQ - 1. These are
947 ! required if MITER is 4 or 5, and ignored
948 ! otherwise. ML and MU may in fact be the band
949 ! parameters for a matrix to which df/dy is only
950 ! approximately equal.
952 ! LIW The length of the array IWORK, as declared by the user.
953 ! (This will be checked by the solver.)
955 ! Note: The work arrays must not be altered between calls to DLSODE
956 ! for the same problem, except possibly for the conditional and
957 ! optional inputs, and except for the last 3*NEQ words of RWORK.
958 ! The latter space is used for internal scratch space, and so is
959 ! available for use by the user outside DLSODE between calls, if
960 ! desired (but not for use by F or JAC).
962 ! JAC The name of the user-supplied routine (MITER = 1 or 4) to
963 ! compute the Jacobian matrix, df/dy, as a function of the
964 ! scalar t and the vector y. (See the MF description below
965 ! for MITER.) It is to have the form
967 ! SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD)
968 ! KPP_REAL T, Y(*), PD(NROWPD,*)
970 ! where NEQ, T, Y, ML, MU, and NROWPD are input and the
971 ! array PD is to be loaded with partial derivatives
972 ! (elements of the Jacobian matrix) on output. PD must be
973 ! given a first dimension of NROWPD. T and Y have the same
974 ! meaning as in subroutine F.
976 ! In the full matrix case (MITER = 1), ML and MU are
977 ! ignored, and the Jacobian is to be loaded into PD in
978 ! columnwise manner, with df(i)/dy(j) loaded into PD(i,j).
980 ! In the band matrix case (MITER = 4), the elements within
981 ! the band are to be loaded into PD in columnwise manner,
982 ! with diagonal lines of df/dy loaded into the rows of PD.
983 ! Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j). ML
984 ! and MU are the half-bandwidth parameters (see IWORK).
985 ! The locations in PD in the two triangular areas which
986 ! correspond to nonexistent matrix elements can be ignored
987 ! or loaded arbitrarily, as they are overwritten by DLSODE.
989 ! JAC need not provide df/dy exactly. A crude approximation
990 ! (possibly with a smaller bandwidth) will do.
992 ! In either case, PD is preset to zero by the solver, so
993 ! that only the nonzero elements need be loaded by JAC.
994 ! Each call to JAC is preceded by a call to F with the same
995 ! arguments NEQ, T, and Y. Thus to gain some efficiency,
996 ! intermediate quantities shared by both calculations may
997 ! be saved in a user COMMON block by F and not recomputed
998 ! by JAC, if desired. Also, JAC may alter the Y array, if
999 ! desired. JAC must be declared EXTERNAL in the calling
1002 ! Subroutine JAC may access user-defined quantities in
1003 ! NEQ(2),... and/or in Y(NEQ+1),... if NEQ is an array
1004 ! (dimensioned in JAC) and/or Y has length exceeding
1005 ! NEQ. See the descriptions of NEQ and Y above.
1007 ! MF The method flag. Used only for input. The legal values
1008 ! of MF are 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24,
1009 ! and 25. MF has decimal digits METH and MITER:
1010 ! MF = 10*METH + MITER .
1012 ! METH indicates the basic linear multistep method:
1013 ! 1 Implicit Adams method.
1014 ! 2 Method based on backward differentiation formulas
1017 ! MITER indicates the corrector iteration method:
1018 ! 0 Functional iteration (no Jacobian matrix is
1020 ! 1 Chord iteration with a user-supplied full (NEQ by
1022 ! 2 Chord iteration with an internally generated
1023 ! (difference quotient) full Jacobian (using NEQ
1024 ! extra calls to F per df/dy value).
1025 ! 3 Chord iteration with an internally generated
1026 ! diagonal Jacobian approximation (using one extra call
1027 ! to F per df/dy evaluation).
1028 ! 4 Chord iteration with a user-supplied banded Jacobian.
1029 ! 5 Chord iteration with an internally generated banded
1030 ! Jacobian (using ML + MU + 1 extra calls to F per
1031 ! df/dy evaluation).
1033 ! If MITER = 1 or 4, the user must supply a subroutine JAC
1034 ! (the name is arbitrary) as described above under JAC.
1035 ! For other values of MITER, a dummy argument can be used.
1039 ! The following is a list of the optional inputs provided for in the
1040 ! call sequence. (See also Part 2.) For each such input variable,
1041 ! this table lists its name as used in this documentation, its
1042 ! location in the call sequence, its meaning, and the default value.
1043 ! The use of any of these inputs requires IOPT = 1, and in that case
1044 ! all of these inputs are examined. A value of zero for any of
1045 ! these optional inputs will cause the default value to be used.
1046 ! Thus to use a subset of the optional inputs, simply preload
1047 ! locations 5 to 10 in RWORK and IWORK to 0.0 and 0 respectively,
1048 ! and then set those of interest to nonzero values.
1050 ! Name Location Meaning and default value
1051 ! ------ --------- -----------------------------------------------
1052 ! H0 RWORK(5) Step size to be attempted on the first step.
1053 ! The default value is determined by the solver.
1054 ! HMAX RWORK(6) Maximum absolute step size allowed. The
1055 ! default value is infinite.
1056 ! HMIN RWORK(7) Minimum absolute step size allowed. The
1057 ! default value is 0. (This lower bound is not
1058 ! enforced on the final step before reaching
1059 ! TCRIT when ITASK = 4 or 5.)
1060 ! MAXORD IWORK(5) Maximum order to be allowed. The default value
1061 ! is 12 if METH = 1, and 5 if METH = 2. (See the
1062 ! MF description above for METH.) If MAXORD
1063 ! exceeds the default value, it will be reduced
1064 ! to the default value. If MAXORD is changed
1065 ! during the problem, it may cause the current
1066 ! order to be reduced.
1067 ! MXSTEP IWORK(6) Maximum number of (internally defined) steps
1068 ! allowed during one call to the solver. The
1069 ! default value is 500.
1070 ! MXHNIL IWORK(7) Maximum number of messages printed (per
1071 ! problem) warning that T + H = T on a step
1072 ! (H = step size). This must be positive to
1073 ! result in a nondefault value. The default
1078 ! As optional additional output from DLSODE, the variables listed
1079 ! below are quantities related to the performance of DLSODE which
1080 ! are available to the user. These are communicated by way of the
1081 ! work arrays, but also have internal mnemonic names as shown.
1082 ! Except where stated otherwise, all of these outputs are defined on
1083 ! any successful return from DLSODE, and on any return with ISTATE =
1084 ! -1, -2, -4, -5, or -6. On an illegal input return (ISTATE = -3),
1085 ! they will be unchanged from their existing values (if any), except
1086 ! possibly for TOLSF, LENRW, and LENIW. On any error return,
1087 ! outputs relevant to the error will be defined, as noted below.
1089 ! Name Location Meaning
1090 ! ----- --------- ------------------------------------------------
1091 ! HU RWORK(11) Step size in t last used (successfully).
1092 ! HCUR RWORK(12) Step size to be attempted on the next step.
1093 ! TCUR RWORK(13) Current value of the independent variable which
1094 ! the solver has actually reached, i.e., the
1095 ! current internal mesh point in t. On output,
1096 ! TCUR will always be at least as far as the
1097 ! argument T, but may be farther (if interpolation
1099 ! TOLSF RWORK(14) Tolerance scale factor, greater than 1.0,
1100 ! computed when a request for too much accuracy
1101 ! was detected (ISTATE = -3 if detected at the
1102 ! start of the problem, ISTATE = -2 otherwise).
1103 ! If ITOL is left unaltered but RelTol and AbsTol are
1104 ! uniformly scaled up by a factor of TOLSF for the
1105 ! next call, then the solver is deemed likely to
1106 ! succeed. (The user may also ignore TOLSF and
1107 ! alter the tolerance parameters in any other way
1109 ! NST IWORK(11) Number of steps taken for the problem so far.
1110 ! NFE IWORK(12) Number of F evaluations for the problem so far.
1111 ! NJE IWORK(13) Number of Jacobian evaluations (and of matrix LU
1112 ! decompositions) for the problem so far.
1113 ! NQU IWORK(14) Method order last used (successfully).
1114 ! NQCUR IWORK(15) Order to be attempted on the next step.
1115 ! IMXER IWORK(16) Index of the component of largest magnitude in
1116 ! the weighted local error vector ( e(i)/EWT(i) ),
1117 ! on an error return with ISTATE = -4 or -5.
1118 ! LENRW IWORK(17) Length of RWORK actually required. This is
1119 ! defined on normal returns and on an illegal
1120 ! input return for insufficient storage.
1121 ! LENIW IWORK(18) Length of IWORK actually required. This is
1122 ! defined on normal returns and on an illegal
1123 ! input return for insufficient storage.
1125 ! The following two arrays are segments of the RWORK array which may
1126 ! also be of interest to the user as optional outputs. For each
1127 ! array, the table below gives its internal name, its base address
1128 ! in RWORK, and its description.
1130 ! Name Base address Description
1131 ! ---- ------------ ----------------------------------------------
1132 ! YH 21 The Nordsieck history array, of size NYH by
1133 ! (NQCUR + 1), where NYH is the initial value of
1134 ! NEQ. For j = 0,1,...,NQCUR, column j + 1 of
1135 ! YH contains HCUR**j/factorial(j) times the jth
1136 ! derivative of the interpolating polynomial
1137 ! currently representing the solution, evaluated
1139 ! ACOR LENRW-NEQ+1 Array of size NEQ used for the accumulated
1140 ! corrections on each step, scaled on output to
1141 ! represent the estimated local error in Y on
1142 ! the last step. This is the vector e in the
1143 ! description of the error control. It is
1144 ! defined only on successful return from DLSODE.
1147 ! Part 2. Other Callable Routines
1148 ! --------------------------------
1150 ! The following are optional calls which the user may make to gain
1151 ! additional capabilities in conjunction with DLSODE.
1153 ! Form of call Function
1154 ! ------------------------ ----------------------------------------
1155 ! CALL XSETUN(LUN) Set the logical unit number, LUN, for
1156 ! output of messages from DLSODE, if the
1157 ! default is not desired. The default
1158 ! value of LUN is 6. This call may be made
1159 ! at any time and will take effect
1161 ! CALL XSETF(MFLAG) Set a flag to control the printing of
1162 ! messages by DLSODE. MFLAG = 0 means do
1163 ! not print. (Danger: this risks losing
1164 ! valuable information.) MFLAG = 1 means
1165 ! print (the default). This call may be
1166 ! made at any time and will take effect
1168 ! CALL DSRCOM(RSAV,ISAV,JOB) Saves and restores the contents of the
1169 ! internal COMMON blocks used by DLSODE
1170 ! (see Part 3 below). RSAV must be a
1171 ! real array of length 218 or more, and
1172 ! ISAV must be an integer array of length
1173 ! 37 or more. JOB = 1 means save COMMON
1174 ! into RSAV/ISAV. JOB = 2 means restore
1175 ! COMMON from same. DSRCOM is useful if
1176 ! one is interrupting a run and restarting
1177 ! later, or alternating between two or
1178 ! more problems solved with DLSODE.
1179 ! CALL DINTDY(,,,,,) Provide derivatives of y, of various
1180 ! (see below) orders, at a specified point t, if
1181 ! desired. It may be called only after a
1182 ! successful return from DLSODE. Detailed
1183 ! instructions follow.
1185 ! Detailed instructions for using DINTDY
1186 ! --------------------------------------
1187 ! The form of the CALL is:
1189 ! CALL DINTDY (T, K, RWORK(21), NYH, DKY, IFLAG)
1191 ! The input parameters are:
1193 ! T Value of independent variable where answers are
1194 ! desired (normally the same as the T last returned by
1195 ! DLSODE). For valid results, T must lie between
1196 ! TCUR - HU and TCUR. (See "Optional Outputs" above
1198 ! K Integer order of the derivative desired. K must
1199 ! satisfy 0 <= K <= NQCUR, where NQCUR is the current
1200 ! order (see "Optional Outputs"). The capability
1201 ! corresponding to K = 0, i.e., computing y(t), is
1202 ! already provided by DLSODE directly. Since
1203 ! NQCUR >= 1, the first derivative dy/dt is always
1204 ! available with DINTDY.
1205 ! RWORK(21) The base address of the history array YH.
1206 ! NYH Column length of YH, equal to the initial value of NEQ.
1208 ! The output parameters are:
1210 ! DKY Real array of length NEQ containing the computed value
1211 ! of the Kth derivative of y(t).
1212 ! IFLAG Integer flag, returned as 0 if K and T were legal,
1213 ! -1 if K was illegal, and -2 if T was illegal.
1214 ! On an error return, a message is also written.
1217 ! Part 3. Common Blocks
1218 ! ----------------------
1220 ! If DLSODE is to be used in an overlay situation, the user must
1221 ! declare, in the primary overlay, the variables in:
1222 ! (1) the call sequence to DLSODE,
1223 ! (2) the internal COMMON block /DLS001/, of length 255
1224 ! (218 double precision words followed by 37 integer words).
1226 ! If DLSODE is used on a system in which the contents of internal
1227 ! COMMON blocks are not preserved between calls, the user should
1228 ! declare the above COMMON block in his main program to insure that
1229 ! its contents are preserved.
1231 ! If the solution of a given problem by DLSODE is to be interrupted
1232 ! and then later continued, as when restarting an interrupted run or
1233 ! alternating between two or more problems, the user should save,
1234 ! following the return from the last DLSODE call prior to the
1235 ! interruption, the contents of the call sequence variables and the
1236 ! internal COMMON block, and later restore these values before the
1237 ! next DLSODE call for that problem. In addition, if XSETUN and/or
1238 ! XSETF was called for non-default handling of error messages, then
1239 ! these calls must be repeated. To save and restore the COMMON
1240 ! block, use subroutine DSRCOM (see Part 2 above).
1243 ! Part 4. Optionally Replaceable Solver Routines
1244 ! -----------------------------------------------
1246 ! Below are descriptions of two routines in the DLSODE package which
1247 ! relate to the measurement of errors. Either routine can be
1248 ! replaced by a user-supplied version, if desired. However, since
1249 ! such a replacement may have a major impact on performance, it
1250 ! should be done only when absolutely necessary, and only with great
1251 ! caution. (Note: The means by which the package version of a
1252 ! routine is superseded by the user's version may be system-
1257 ! The following subroutine is called just before each internal
1258 ! integration step, and sets the array of error weights, EWT, as
1259 ! described under ITOL/RelTol/AbsTol above:
1261 ! SUBROUTINE DEWSET (NEQ, ITOL, RelTol, AbsTol, YCUR, EWT)
1263 ! where NEQ, ITOL, RelTol, and AbsTol are as in the DLSODE call
1264 ! sequence, YCUR contains the current dependent variable vector,
1265 ! and EWT is the array of weights set by DEWSET.
1267 ! If the user supplies this subroutine, it must return in EWT(i)
1268 ! (i = 1,...,NEQ) a positive quantity suitable for comparing errors
1269 ! in Y(i) to. The EWT array returned by DEWSET is passed to the
1270 ! DVNORM routine (see below), and also used by DLSODE in the
1271 ! computation of the optional output IMXER, the diagonal Jacobian
1272 ! approximation, and the increments for difference quotient
1275 ! In the user-supplied version of DEWSET, it may be desirable to use
1276 ! the current values of derivatives of y. Derivatives up to order NQ
1277 ! are available from the history array YH, described above under
1278 ! optional outputs. In DEWSET, YH is identical to the YCUR array,
1279 ! extended to NQ + 1 columns with a column length of NYH and scale
1280 ! factors of H**j/factorial(j). On the first call for the problem,
1281 ! given by NST = 0, NQ is 1 and H is temporarily set to 1.0.
1282 ! NYH is the initial value of NEQ. The quantities NQ, H, and NST
1283 ! can be obtained by including in SEWSET the statements:
1285 ! COMMON /DLS001/ RLS(218),ILS(37)
1289 ! Thus, for example, the current value of dy/dt can be obtained as
1290 ! YCUR(NYH+i)/H (i=1,...,NEQ) (and the division by H is unnecessary
1295 ! DVNORM is a real function routine which computes the weighted
1296 ! root-mean-square norm of a vector v:
1298 ! d = DVNORM (n, v, w)
1301 ! n = the length of the vector,
1302 ! v = real array of length n containing the vector,
1303 ! w = real array of length n containing weights,
1304 ! d = SQRT( (1/n) * sum(v(i)*w(i))**2 ).
1306 ! DVNORM is called with n = NEQ and with w(i) = 1.0/EWT(i), where
1307 ! EWT is as set by subroutine DEWSET.
1309 ! If the user supplies this function, it should return a nonnegative
1310 ! value of DVNORM suitable for use in the error control in DLSODE.
1311 ! None of the arguments should be altered by DVNORM. For example, a
1312 ! user-supplied DVNORM routine might:
1313 ! - Substitute a max-norm of (v(i)*w(i)) for the rms-norm, or
1314 ! - Ignore some components of v in the norm, with the effect of
1315 ! suppressing the error control on those components of Y.
1316 ! ---------------------------------------------------------------------
1317 !***ROUTINES CALLED DEWSET, DINTDY, DUMACH, DSTODE, DVNORM, XERRWD
1318 !***COMMON BLOCKS DLS001
1319 !***REVISION HISTORY (YYYYMMDD)
1320 ! 19791129 DATE WRITTEN
1321 ! 19791213 Minor changes to declarations; DELP init. in STODE.
1322 ! 19800118 Treat NEQ as array; integer declarations added throughout;
1323 ! minor changes to prologue.
1324 ! 19800306 Corrected TESCO(1,NQP1) setting in CFODE.
1325 ! 19800519 Corrected access of YH on forced order reduction;
1326 ! numerous corrections to prologues and other comments.
1327 ! 19800617 In main driver, added loading of SQRT(UROUND) in RWORK;
1328 ! minor corrections to main prologue.
1329 ! 19800923 Added zero initialization of HU and NQU.
1330 ! 19801218 Revised XERRWD routine; minor corrections to main prologue.
1331 ! 19810401 Minor changes to comments and an error message.
1332 ! 19810814 Numerous revisions: replaced EWT by 1/EWT; used flags
1333 ! JCUR, ICF, IERPJ, IERSL between STODE and subordinates;
1334 ! added tuning parameters CCMAX, MAXCOR, MSBP, MXNCF;
1335 ! reorganized returns from STODE; reorganized type decls.;
1336 ! fixed message length in XERRWD; changed default LUNIT to 6;
1337 ! changed Common lengths; changed comments throughout.
1338 ! 19870330 Major update by ACH: corrected comments throughout;
1339 ! removed TRET from Common; rewrote EWSET with 4 loops;
1340 ! fixed t test in INTDY; added Cray directives in STODE;
1341 ! in STODE, fixed DELP init. and logic around PJAC call;
1342 ! combined routines to save/restore Common;
1343 ! passed LEVEL = 0 in error message calls (except run abort).
1344 ! 19890426 Modified prologue to SLATEC/LDOC format. (FNF)
1345 ! 19890501 Many improvements to prologue. (FNF)
1346 ! 19890503 A few final corrections to prologue. (FNF)
1347 ! 19890504 Minor cosmetic changes. (FNF)
1348 ! 19890510 Corrected description of Y in Arguments section. (FNF)
1349 ! 19890517 Minor corrections to prologue. (FNF)
1350 ! 19920514 Updated with prologue edited 891025 by G. Shaw for manual.
1351 ! 19920515 Converted source lines to upper case. (FNF)
1352 ! 19920603 Revised XERRWD calls using mixed upper-lower case. (ACH)
1353 ! 19920616 Revised prologue comment regarding CFT. (ACH)
1354 ! 19921116 Revised prologue comments regarding Common. (ACH).
1355 ! 19930326 Added comment about non-reentrancy. (FNF)
1356 ! 19930723 Changed D1MACH to DUMACH. (FNF)
1357 ! 19930801 Removed ILLIN and NTREP from Common (affects driver logic);
1358 ! minor changes to prologue and internal comments;
1359 ! changed Hollerith strings to quoted strings;
1360 ! changed internal comments to mixed case;
1361 ! replaced XERRWD with new version using character type;
1362 ! changed dummy dimensions from 1 to *. (ACH)
1363 ! 19930809 Changed to generic intrinsic names; changed names of
1364 ! subprograms and Common blocks to DLSODE etc. (ACH)
1365 ! 19930929 Eliminated use of REAL intrinsic; other minor changes. (ACH)
1366 ! 20010412 Removed all 'own' variables from Common block /DLS001/
1367 ! (affects declarations in 6 routines). (ACH)
1368 ! 20010509 Minor corrections to prologue. (ACH)
1369 ! 20031105 Restored 'own' variables to Common block /DLS001/, to
1370 ! enable interrupt/restart feature. (ACH)
1371 ! 20031112 Added SAVE statements for data-loaded constants.
1373 !***END PROLOGUE DLSODE
1377 ! Other Routines in the DLSODE Package.
1379 ! In addition to Subroutine DLSODE, the DLSODE package includes the
1380 ! following subroutines and function routines:
1381 ! DINTDY computes an interpolated value of the y vector at t = TOUT.
1382 ! DSTODE is the core integrator, which does one step of the
1383 ! integration and the associated error control.
1384 ! DCFODE sets all method coefficients and test constants.
1385 ! DPREPJ computes and preprocesses the Jacobian matrix J = df/dy
1386 ! and the Newton iteration matrix P = I - h*l0*J.
1387 ! DSOLSY manages solution of linear system in chord iteration.
1388 ! DEWSET sets the error weight vector EWT before each step.
1389 ! DVNORM computes the weighted R.M.S. norm of a vector.
1390 ! DSRCOM is a user-callable routine to save and restore
1391 ! the contents of the internal Common block.
1392 ! DGEFA and DGESL are routines from LINPACK for solving full
1393 ! systems of linear algebraic equations.
1394 ! DGBFA and DGBSL are routines from LINPACK for solving banded
1396 ! DUMACH computes the unit roundoff in a machine-independent manner.
1397 ! XERRWD, XSETUN, XSETF, IXSAV, IUMACH handle the printing of all
1398 ! error messages and warnings. XERRWD is machine-dependent.
1399 ! Note: DVNORM, DUMACH, IXSAV, and IUMACH are function routines.
1400 ! All the others are subroutines.
1404 ! Declare externals.
1405 ! Note: they are now internal
1406 !EXTERNAL DPREPJ, DSOLSY
1407 !KPP_REAL DUMACH, DVNORM
1409 ! Declare all other variables.
1410 INTEGER INIT
, MXSTEP
, MXHNIL
, NHNIL
, NSLAST
, NYH
, IOWNS
, &
1411 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
1412 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
1413 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
1414 INTEGER I
, I1
, I2
, IFLAG
, IMXER
, KGO
, LF0
, &
1415 LENIW
, LENRW
, LENWM
, ML
, MORD(2), MU
, MXHNL0
, MXSTP0
1417 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
1418 KPP_REAL AbsTolI
, AYI
, BIG
, EWTI
, H0
, HMAX
, HMX
, RH
, RelTolI
, &
1419 TCRIT
, TDIST
, TNEXT
, TOL
, TOLSF
, TP
, SIZE
, SUM
, W0
1423 SAVE MORD
, MXSTP0
, MXHNL0
1424 !-----------------------------------------------------------------------
1425 ! The following internal Common block contains
1426 ! (a) variables which are local to any subroutine but whose values must
1427 ! be preserved between calls to the routine ("own" variables), and
1428 ! (b) variables which are communicated between subroutines.
1429 ! The block DLS001 is declared in subroutines DLSODE, DINTDY, DSTODE,
1430 ! DPREPJ, and DSOLSY.
1431 ! Groups of variables are replaced by dummy arrays in the Common
1432 ! declarations in routines where those variables are not used.
1433 !-----------------------------------------------------------------------
1434 COMMON /DLS001
/ ROWNS(209), &
1435 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
, &
1436 INIT
, MXSTEP
, MXHNIL
, NHNIL
, NSLAST
, NYH
, IOWNS(6), &
1437 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
1438 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
1439 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
1441 DATA MORD(1),MORD(2)/12,5/, MXSTP0
/500/, MXHNL0
/10/
1442 !-----------------------------------------------------------------------
1444 ! This code block is executed on every call.
1445 ! It tests ISTATE and ITASK for legality and branches appropriately.
1446 ! If ISTATE .GT. 1 but the flag INIT shows that initialization has
1447 ! not yet been done, an error return occurs.
1448 ! If ISTATE = 1 and TOUT = T, return immediately.
1449 !-----------------------------------------------------------------------
1451 !***FIRST EXECUTABLE STATEMENT DLSODE
1452 IF (ISTATE
.LT
. 1 .OR
. ISTATE
.GT
. 3) GO
TO 601
1453 IF (ITASK
.LT
. 1 .OR
. ITASK
.GT
. 5) GO
TO 602
1454 IF (ISTATE
.EQ
. 1) GO
TO 10
1455 IF (INIT
.EQ
. 0) GO
TO 603
1456 IF (ISTATE
.EQ
. 2) GO
TO 200
1459 IF (TOUT
.EQ
. T
) RETURN
1460 !-----------------------------------------------------------------------
1462 ! The next code block is executed for the initial call (ISTATE = 1),
1463 ! or for a continuation call with parameter changes (ISTATE = 3).
1464 ! It contains checking of all inputs and various initializations.
1466 ! First check legality of the non-optional inputs NEQ, ITOL, IOPT,
1468 !-----------------------------------------------------------------------
1469 20 IF (NEQ
.LE
. 0) GO
TO 604
1470 IF (ISTATE
.EQ
. 1) GO
TO 25
1471 IF (NEQ
.GT
. N
) GO
TO 605
1473 IF (ITOL
.LT
. 1 .OR
. ITOL
.GT
. 4) GO
TO 606
1474 IF (IOPT
.LT
. 0 .OR
. IOPT
.GT
. 1) GO
TO 607
1476 MITER
= MF
- 10*METH
1477 IF (METH
.LT
. 1 .OR
. METH
.GT
. 2) GO
TO 608
1478 IF (MITER
.LT
. 0 .OR
. MITER
.GT
. 5) GO
TO 608
1479 IF (MITER
.LE
. 3) GO
TO 30
1482 IF (ML
.LT
. 0 .OR
. ML
.GE
. N
) GO
TO 609
1483 IF (MU
.LT
. 0 .OR
. MU
.GE
. N
) GO
TO 610
1485 ! Next process and check the optional inputs. --------------------------
1486 IF (IOPT
.EQ
. 1) GO
TO 40
1490 IF (ISTATE
.EQ
. 1) H0
= 0.0D0
1494 40 MAXORD
= IWORK(5)
1495 IF (MAXORD
.LT
. 0) GO
TO 611
1496 IF (MAXORD
.EQ
. 0) MAXORD
= 100
1497 MAXORD
= MIN(MAXORD
,MORD(METH
))
1499 IF (MXSTEP
.LT
. 0) GO
TO 612
1500 IF (MXSTEP
.EQ
. 0) MXSTEP
= MXSTP0
1502 IF (MXHNIL
.LT
. 0) GO
TO 613
1503 IF (MXHNIL
.EQ
. 0) MXHNIL
= MXHNL0
1504 IF (ISTATE
.NE
. 1) GO
TO 50
1506 IF ((TOUT
- T
)*H0
.LT
. 0.0D0
) GO
TO 614
1508 IF (HMAX
.LT
. 0.0D0
) GO
TO 615
1510 IF (HMAX
.GT
. 0.0D0
) HMXI
= 1.0D0
/HMAX
1512 IF (HMIN
.LT
. 0.0D0
) GO
TO 616
1513 !-----------------------------------------------------------------------
1514 ! Set work array pointers and check lengths LRW and LIW.
1515 ! Pointers to segments of RWORK and IWORK are named by prefixing L to
1516 ! the name of the segment. E.g., the segment YH starts at RWORK(LYH).
1517 ! Segments of RWORK (in order) are denoted YH, WM, EWT, SAVF, ACOR.
1518 !-----------------------------------------------------------------------
1520 IF (ISTATE
.EQ
. 1) NYH
= N
1521 LWM
= LYH
+ (MAXORD
+ 1)*NYH
1522 IF (MITER
.EQ
. 0) LENWM
= 0
1523 IF (MITER
.EQ
. 1 .OR
. MITER
.EQ
. 2) LENWM
= N
*N
+ 2
1524 IF (MITER
.EQ
. 3) LENWM
= N
+ 2
1525 IF (MITER
.GE
. 4) LENWM
= (2*ML
+ MU
+ 1)*N
+ 2
1529 LENRW
= LACOR
+ N
- 1
1533 IF (MITER
.EQ
. 0 .OR
. MITER
.EQ
. 3) LENIW
= 20
1535 IF (LENRW
.GT
. LRW
) GO
TO 617
1536 IF (LENIW
.GT
. LIW
) GO
TO 618
1537 ! Check RelTol and AbsTol for legality. ------------------------------------
1541 IF (ITOL
.GE
. 3) RelTolI
= RelTol(I
)
1542 IF (ITOL
.EQ
. 2 .OR
. ITOL
.EQ
. 4) AbsTolI
= AbsTol(I
)
1543 IF (RelTolI
.LT
. 0.0D0
) GO
TO 619
1544 IF (AbsTolI
.LT
. 0.0D0
) GO
TO 620
1546 IF (ISTATE
.EQ
. 1) GO
TO 100
1547 ! If ISTATE = 3, set flag to signal parameter changes to DSTODE. -------
1549 IF (NQ
.LE
. MAXORD
) GO
TO 90
1550 ! MAXORD was reduced below NQ. Copy YH(*,MAXORD+2) into SAVF. ---------
1552 80 RWORK(I
+LSAVF
-1) = RWORK(I
+LWM
-1)
1553 ! Reload WM(1) = RWORK(LWM), since LWM may have changed. ---------------
1554 90 IF (MITER
.GT
. 0) RWORK(LWM
) = SQRT(UROUND
)
1555 IF (N
.EQ
. NYH
) GO
TO 200
1556 ! NEQ was reduced. Zero part of YH to avoid undefined references. -----
1558 I2
= LYH
+ (MAXORD
+ 1)*NYH
- 1
1559 IF (I1
.GT
. I2
) GO
TO 200
1563 !-----------------------------------------------------------------------
1565 ! The next block is for the initial call only (ISTATE = 1).
1566 ! It contains all remaining initializations, the initial call to F,
1567 ! and the calculation of the initial step size.
1568 ! The error weights in EWT are inverted after being loaded.
1569 !-----------------------------------------------------------------------
1570 100 UROUND
= DUMACH()
1572 IF (ITASK
.NE
. 4 .AND
. ITASK
.NE
. 5) GO
TO 110
1574 IF ((TCRIT
- TOUT
)*(TOUT
- T
) .LT
. 0.0D0
) GO
TO 625
1575 IF (H0
.NE
. 0.0D0
.AND
. (T
+ H0
- TCRIT
)*H0
.GT
. 0.0D0
) &
1578 IF (MITER
.GT
. 0) RWORK(LWM
) = SQRT(UROUND
)
1589 ! Initial call to F. (LF0 points to YH(*,2).) -------------------------
1591 CALL F (NEQ
, T
, Y
, RWORK(LF0
))
1593 ! Load the initial value vector in YH. ---------------------------------
1595 115 RWORK(I
+LYH
-1) = Y(I
)
1596 ! Load and invert the EWT array. (H is temporarily set to 1.0.) -------
1599 CALL DEWSET (N
, ITOL
, RelTol
, AbsTol
, RWORK(LYH
), RWORK(LEWT
))
1601 IF (RWORK(I
+LEWT
-1) .LE
. 0.0D0
) GO
TO 621
1602 120 RWORK(I
+LEWT
-1) = 1.0D0
/RWORK(I
+LEWT
-1)
1603 !-----------------------------------------------------------------------
1604 ! The coding below computes the step size, H0, to be attempted on the
1605 ! first step, unless the user has supplied a value for this.
1606 ! First check that TOUT - T differs significantly from zero.
1607 ! A scalar tolerance quantity TOL is computed, as MAX(RelTol(I))
1608 ! if this is positive, or MAX(AbsTol(I)/ABS(Y(I))) otherwise, adjusted
1609 ! so as to be between 100*UROUND and 1.0E-3.
1610 ! Then the computed value H0 is given by..
1612 ! H0**2 = TOL / ( w0**-2 + (1/NEQ) * SUM ( f(i)/ywt(i) )**2 )
1614 ! where w0 = MAX ( ABS(T), ABS(TOUT) ),
1615 ! f(i) = i-th component of initial value of f,
1616 ! ywt(i) = EWT(i)/TOL (a weight for y(i)).
1617 ! The sign of H0 is inferred from the initial values of TOUT and T.
1618 !-----------------------------------------------------------------------
1619 IF (H0
.NE
. 0.0D0
) GO
TO 180
1620 TDIST
= ABS(TOUT
- T
)
1621 W0
= MAX(ABS(T
),ABS(TOUT
))
1622 IF (TDIST
.LT
. 2.0D0
*UROUND
*W0
) GO
TO 622
1624 IF (ITOL
.LE
. 2) GO
TO 140
1626 130 TOL
= MAX(TOL
,RelTol(I
))
1627 140 IF (TOL
.GT
. 0.0D0
) GO
TO 160
1630 IF (ITOL
.EQ
. 2 .OR
. ITOL
.EQ
. 4) AbsTolI
= AbsTol(I
)
1632 IF (AYI
.NE
. 0.0D0
) TOL
= MAX(TOL
,AbsTolI
/AYI
)
1634 160 TOL
= MAX(TOL
,100.0D0
*UROUND
)
1635 TOL
= MIN(TOL
,0.001D0
)
1636 SUM
= DVNORM (N
, RWORK(LF0
), RWORK(LEWT
))
1637 SUM
= 1.0D0
/(TOL
*W0
*W0
) + TOL
*SUM
**2
1638 H0
= 1.0D0
/SQRT(SUM
)
1640 H0
= SIGN(H0
,TOUT
-T
)
1641 ! Adjust H0 if necessary to meet HMAX bound. ---------------------------
1642 180 RH
= ABS(H0
)*HMXI
1643 IF (RH
.GT
. 1.0D0
) H0
= H0
/RH
1644 ! Load H with H0 and scale YH(*,2) by H0. ------------------------------
1647 190 RWORK(I
+LF0
-1) = H0
*RWORK(I
+LF0
-1)
1649 !-----------------------------------------------------------------------
1651 ! The next code block is for continuation calls only (ISTATE = 2 or 3)
1652 ! and is to check stop conditions before taking a step.
1653 !-----------------------------------------------------------------------
1655 GO
TO (210, 250, 220, 230, 240), ITASK
1656 210 IF ((TN
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 250
1657 CALL DINTDY (TOUT
, 0, RWORK(LYH
), NYH
, Y
, IFLAG
)
1658 IF (IFLAG
.NE
. 0) GO
TO 627
1661 220 TP
= TN
- HU
*(1.0D0
+ 100.0D0
*UROUND
)
1662 IF ((TP
- TOUT
)*H
.GT
. 0.0D0
) GO
TO 623
1663 IF ((TN
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 250
1665 230 TCRIT
= RWORK(1)
1666 IF ((TN
- TCRIT
)*H
.GT
. 0.0D0
) GO
TO 624
1667 IF ((TCRIT
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 625
1668 IF ((TN
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 245
1669 CALL DINTDY (TOUT
, 0, RWORK(LYH
), NYH
, Y
, IFLAG
)
1670 IF (IFLAG
.NE
. 0) GO
TO 627
1673 240 TCRIT
= RWORK(1)
1674 IF ((TN
- TCRIT
)*H
.GT
. 0.0D0
) GO
TO 624
1675 245 HMX
= ABS(TN
) + ABS(H
)
1676 IHIT
= ABS(TN
- TCRIT
) .LE
. 100.0D0
*UROUND
*HMX
1678 TNEXT
= TN
+ H
*(1.0D0
+ 4.0D0
*UROUND
)
1679 IF ((TNEXT
- TCRIT
)*H
.LE
. 0.0D0
) GO
TO 250
1680 H
= (TCRIT
- TN
)*(1.0D0
- 4.0D0
*UROUND
)
1681 IF (ISTATE
.EQ
. 2) JSTART
= -2
1682 !-----------------------------------------------------------------------
1684 ! The next block is normally executed for all calls and contains
1685 ! the call to the one-step core integrator DSTODE.
1687 ! This is a looping point for the integration steps.
1689 ! First check for too many steps being taken, update EWT (if not at
1690 ! start of problem), check for too much accuracy being requested, and
1691 ! check for H below the roundoff level in T.
1692 !-----------------------------------------------------------------------
1694 IF ((NST
-NSLAST
) .GE
. MXSTEP
) GO
TO 500
1695 CALL DEWSET (N
, ITOL
, RelTol
, AbsTol
, RWORK(LYH
), RWORK(LEWT
))
1697 IF (RWORK(I
+LEWT
-1) .LE
. 0.0D0
) GO
TO 510
1698 260 RWORK(I
+LEWT
-1) = 1.0D0
/RWORK(I
+LEWT
-1)
1699 270 TOLSF
= UROUND
*DVNORM (N
, RWORK(LYH
), RWORK(LEWT
))
1700 IF (TOLSF
.LE
. 1.0D0
) GO
TO 280
1702 IF (NST
.EQ
. 0) GO
TO 626
1704 280 IF ((TN
+ H
) .NE
. TN
) GO
TO 290
1706 IF (NHNIL
.GT
. MXHNIL
) GO
TO 290
1707 MSG
= 'DLSODE- Warning..internal T (=R1) and H (=R2) are'
1708 CALL XERRWD (MSG
, 50, 101, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1709 MSG
=' such that in the machine, T + H = T on the next step '
1710 CALL XERRWD (MSG
, 60, 101, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1711 MSG
= ' (H = step size). Solver will continue anyway'
1712 CALL XERRWD (MSG
, 50, 101, 0, 0, 0, 0, 2, TN
, H
)
1713 IF (NHNIL
.LT
. MXHNIL
) GO
TO 290
1714 MSG
= 'DLSODE- Above warning has been issued I1 times. '
1715 CALL XERRWD (MSG
, 50, 102, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1716 MSG
= ' It will not be issued again for this problem'
1717 CALL XERRWD (MSG
, 50, 102, 0, 1, MXHNIL
, 0, 0, 0.0D0
, 0.0D0
)
1719 !-----------------------------------------------------------------------
1720 ! CALL DSTODE(NEQ,Y,YH,NYH,YH,EWT,SAVF,ACOR,WM,IWM,F,JAC,DPREPJ,DSOLSY)
1721 !-----------------------------------------------------------------------
1722 CALL DSTODE (NEQ
, Y
, RWORK(LYH
), NYH
, RWORK(LYH
), RWORK(LEWT
), &
1723 RWORK(LSAVF
), RWORK(LACOR
), RWORK(LWM
), IWORK(LIWM
), &
1725 !F, JAC, DPREPJ, DSOLSY)
1727 GO
TO (300, 530, 540), KGO
1728 !-----------------------------------------------------------------------
1730 ! The following block handles the case of a successful return from the
1731 ! core integrator (KFLAG = 0). Test for stop conditions.
1732 !-----------------------------------------------------------------------
1734 GO
TO (310, 400, 330, 340, 350), ITASK
1735 ! ITASK = 1. If TOUT has been reached, interpolate. -------------------
1736 310 IF ((TN
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 250
1737 CALL DINTDY (TOUT
, 0, RWORK(LYH
), NYH
, Y
, IFLAG
)
1740 ! ITASK = 3. Jump to exit if TOUT was reached. ------------------------
1741 330 IF ((TN
- TOUT
)*H
.GE
. 0.0D0
) GO
TO 400
1743 ! ITASK = 4. See if TOUT or TCRIT was reached. Adjust H if necessary.
1744 340 IF ((TN
- TOUT
)*H
.LT
. 0.0D0
) GO
TO 345
1745 CALL DINTDY (TOUT
, 0, RWORK(LYH
), NYH
, Y
, IFLAG
)
1748 345 HMX
= ABS(TN
) + ABS(H
)
1749 IHIT
= ABS(TN
- TCRIT
) .LE
. 100.0D0
*UROUND
*HMX
1751 TNEXT
= TN
+ H
*(1.0D0
+ 4.0D0
*UROUND
)
1752 IF ((TNEXT
- TCRIT
)*H
.LE
. 0.0D0
) GO
TO 250
1753 H
= (TCRIT
- TN
)*(1.0D0
- 4.0D0
*UROUND
)
1756 ! ITASK = 5. See if TCRIT was reached and jump to exit. ---------------
1757 350 HMX
= ABS(TN
) + ABS(H
)
1758 IHIT
= ABS(TN
- TCRIT
) .LE
. 100.0D0
*UROUND
*HMX
1759 !-----------------------------------------------------------------------
1761 ! The following block handles all successful returns from DLSODE.
1762 ! If ITASK .NE. 1, Y is loaded from YH and T is set accordingly.
1763 ! ISTATE is set to 2, and the optional outputs are loaded into the
1764 ! work arrays before returning.
1765 !-----------------------------------------------------------------------
1767 410 Y(I
) = RWORK(I
+LYH
-1)
1769 IF (ITASK
.NE
. 4 .AND
. ITASK
.NE
. 5) GO
TO 420
1781 !-----------------------------------------------------------------------
1783 ! The following block handles all unsuccessful returns other than
1784 ! those for illegal input. First the error message routine is called.
1785 ! If there was an error test or convergence test failure, IMXER is set.
1786 ! Then Y is loaded from YH and T is set to TN. The optional outputs
1787 ! are loaded into the work arrays before returning.
1788 !-----------------------------------------------------------------------
1789 ! The maximum number of steps was taken before reaching TOUT. ----------
1790 500 MSG
= 'DLSODE- At current T (=R1), MXSTEP (=I1) steps '
1791 CALL XERRWD (MSG
, 50, 201, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1792 MSG
= ' taken on this call before reaching TOUT '
1793 CALL XERRWD (MSG
, 50, 201, 0, 1, MXSTEP
, 0, 1, TN
, 0.0D0
)
1796 ! EWT(I) .LE. 0.0 for some I (not at start of problem). ----------------
1797 510 EWTI
= RWORK(LEWT
+I
-1)
1798 MSG
= 'DLSODE- At T (=R1), EWT(I1) has become R2 .LE. 0.'
1799 CALL XERRWD (MSG
, 50, 202, 0, 1, I
, 0, 2, TN
, EWTI
)
1802 ! Too much accuracy requested for machine precision. -------------------
1803 520 MSG
= 'DLSODE- At T (=R1), too much accuracy requested '
1804 CALL XERRWD (MSG
, 50, 203, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1805 MSG
= ' for precision of machine.. see TOLSF (=R2) '
1806 CALL XERRWD (MSG
, 50, 203, 0, 0, 0, 0, 2, TN
, TOLSF
)
1810 ! KFLAG = -1. Error test failed repeatedly or with ABS(H) = HMIN. -----
1811 530 MSG
= 'DLSODE- At T(=R1) and step size H(=R2), the error'
1812 CALL XERRWD (MSG
, 50, 204, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1813 MSG
= ' test failed repeatedly or with ABS(H) = HMIN'
1814 CALL XERRWD (MSG
, 50, 204, 0, 0, 0, 0, 2, TN
, H
)
1817 ! KFLAG = -2. Convergence failed repeatedly or with ABS(H) = HMIN. ----
1818 540 MSG
= 'DLSODE- At T (=R1) and step size H (=R2), the '
1819 CALL XERRWD (MSG
, 50, 205, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1820 MSG
= ' corrector convergence failed repeatedly '
1821 CALL XERRWD (MSG
, 50, 205, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1822 MSG
= ' or with ABS(H) = HMIN '
1823 CALL XERRWD (MSG
, 30, 205, 0, 0, 0, 0, 2, TN
, H
)
1825 ! Compute IMXER if relevant. -------------------------------------------
1829 SIZE
= ABS(RWORK(I
+LACOR
-1)*RWORK(I
+LEWT
-1))
1830 IF (BIG
.GE
. SIZE
) GO
TO 570
1835 ! Set Y vector, T, and optional outputs. -------------------------------
1837 590 Y(I
) = RWORK(I
+LYH
-1)
1848 !-----------------------------------------------------------------------
1850 ! The following block handles all error returns due to illegal input
1851 ! (ISTATE = -3), as detected before calling the core integrator.
1852 ! First the error message routine is called. If the illegal input
1853 ! is a negative ISTATE, the run is aborted (apparent infinite loop).
1854 !-----------------------------------------------------------------------
1855 601 MSG
= 'DLSODE- ISTATE (=I1) illegal '
1856 CALL XERRWD (MSG
, 30, 1, 0, 1, ISTATE
, 0, 0, 0.0D0
, 0.0D0
)
1857 IF (ISTATE
.LT
. 0) GO
TO 800
1859 602 MSG
= 'DLSODE- ITASK (=I1) illegal '
1860 CALL XERRWD (MSG
, 30, 2, 0, 1, ITASK
, 0, 0, 0.0D0
, 0.0D0
)
1862 603 MSG
= 'DLSODE- ISTATE .GT. 1 but DLSODE not initialized '
1863 CALL XERRWD (MSG
, 50, 3, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1865 604 MSG
= 'DLSODE- NEQ (=I1) .LT. 1 '
1866 CALL XERRWD (MSG
, 30, 4, 0, 1, NEQ
, 0, 0, 0.0D0
, 0.0D0
)
1868 605 MSG
= 'DLSODE- ISTATE = 3 and NEQ increased (I1 to I2) '
1869 CALL XERRWD (MSG
, 50, 5, 0, 2, N
, NEQ
, 0, 0.0D0
, 0.0D0
)
1871 606 MSG
= 'DLSODE- ITOL (=I1) illegal '
1872 CALL XERRWD (MSG
, 30, 6, 0, 1, ITOL
, 0, 0, 0.0D0
, 0.0D0
)
1874 607 MSG
= 'DLSODE- IOPT (=I1) illegal '
1875 CALL XERRWD (MSG
, 30, 7, 0, 1, IOPT
, 0, 0, 0.0D0
, 0.0D0
)
1877 608 MSG
= 'DLSODE- MF (=I1) illegal '
1878 CALL XERRWD (MSG
, 30, 8, 0, 1, MF
, 0, 0, 0.0D0
, 0.0D0
)
1880 609 MSG
= 'DLSODE- ML (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'
1881 CALL XERRWD (MSG
, 50, 9, 0, 2, ML
, NEQ
, 0, 0.0D0
, 0.0D0
)
1883 610 MSG
= 'DLSODE- MU (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)'
1884 CALL XERRWD (MSG
, 50, 10, 0, 2, MU
, NEQ
, 0, 0.0D0
, 0.0D0
)
1886 611 MSG
= 'DLSODE- MAXORD (=I1) .LT. 0 '
1887 CALL XERRWD (MSG
, 30, 11, 0, 1, MAXORD
, 0, 0, 0.0D0
, 0.0D0
)
1889 612 MSG
= 'DLSODE- MXSTEP (=I1) .LT. 0 '
1890 CALL XERRWD (MSG
, 30, 12, 0, 1, MXSTEP
, 0, 0, 0.0D0
, 0.0D0
)
1892 613 MSG
= 'DLSODE- MXHNIL (=I1) .LT. 0 '
1893 CALL XERRWD (MSG
, 30, 13, 0, 1, MXHNIL
, 0, 0, 0.0D0
, 0.0D0
)
1895 614 MSG
= 'DLSODE- TOUT (=R1) behind T (=R2) '
1896 CALL XERRWD (MSG
, 40, 14, 0, 0, 0, 0, 2, TOUT
, T
)
1897 MSG
= ' Integration direction is given by H0 (=R1) '
1898 CALL XERRWD (MSG
, 50, 14, 0, 0, 0, 0, 1, H0
, 0.0D0
)
1900 615 MSG
= 'DLSODE- HMAX (=R1) .LT. 0.0 '
1901 CALL XERRWD (MSG
, 30, 15, 0, 0, 0, 0, 1, HMAX
, 0.0D0
)
1903 616 MSG
= 'DLSODE- HMIN (=R1) .LT. 0.0 '
1904 CALL XERRWD (MSG
, 30, 16, 0, 0, 0, 0, 1, HMIN
, 0.0D0
)
1907 MSG
='DLSODE- RWORK length needed, LENRW (=I1), exceeds LRW (=I2)'
1908 CALL XERRWD (MSG
, 60, 17, 0, 2, LENRW
, LRW
, 0, 0.0D0
, 0.0D0
)
1911 MSG
='DLSODE- IWORK length needed, LENIW (=I1), exceeds LIW (=I2)'
1912 CALL XERRWD (MSG
, 60, 18, 0, 2, LENIW
, LIW
, 0, 0.0D0
, 0.0D0
)
1914 619 MSG
= 'DLSODE- RelTol(I1) is R1 .LT. 0.0 '
1915 CALL XERRWD (MSG
, 40, 19, 0, 1, I
, 0, 1, RelTolI
, 0.0D0
)
1917 620 MSG
= 'DLSODE- AbsTol(I1) is R1 .LT. 0.0 '
1918 CALL XERRWD (MSG
, 40, 20, 0, 1, I
, 0, 1, AbsTolI
, 0.0D0
)
1920 621 EWTI
= RWORK(LEWT
+I
-1)
1921 MSG
= 'DLSODE- EWT(I1) is R1 .LE. 0.0 '
1922 CALL XERRWD (MSG
, 40, 21, 0, 1, I
, 0, 1, EWTI
, 0.0D0
)
1925 MSG
='DLSODE- TOUT (=R1) too close to T(=R2) to start integration'
1926 CALL XERRWD (MSG
, 60, 22, 0, 0, 0, 0, 2, TOUT
, T
)
1929 MSG
='DLSODE- ITASK = I1 and TOUT (=R1) behind TCUR - HU (= R2) '
1930 CALL XERRWD (MSG
, 60, 23, 0, 1, ITASK
, 0, 2, TOUT
, TP
)
1933 MSG
='DLSODE- ITASK = 4 OR 5 and TCRIT (=R1) behind TCUR (=R2) '
1934 CALL XERRWD (MSG
, 60, 24, 0, 0, 0, 0, 2, TCRIT
, TN
)
1937 MSG
='DLSODE- ITASK = 4 or 5 and TCRIT (=R1) behind TOUT (=R2) '
1938 CALL XERRWD (MSG
, 60, 25, 0, 0, 0, 0, 2, TCRIT
, TOUT
)
1940 626 MSG
= 'DLSODE- At start of problem, too much accuracy '
1941 CALL XERRWD (MSG
, 50, 26, 0, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1942 MSG
=' requested for precision of machine.. See TOLSF (=R1) '
1943 CALL XERRWD (MSG
, 60, 26, 0, 0, 0, 0, 1, TOLSF
, 0.0D0
)
1946 627 MSG
= 'DLSODE- Trouble in DINTDY. ITASK = I1, TOUT = R1'
1947 CALL XERRWD (MSG
, 50, 27, 0, 1, ITASK
, 0, 1, TOUT
, 0.0D0
)
1952 800 MSG
= 'DLSODE- Run aborted.. apparent infinite loop '
1953 CALL XERRWD (MSG
, 50, 303, 2, 0, 0, 0, 0, 0.0D0
, 0.0D0
)
1955 !----------------------- END OF SUBROUTINE DLSODE ----------------------
1956 !END SUBROUTINE DLSODE
1961 KPP_REAL
FUNCTION DUMACH ()
1962 !***BEGIN PROLOGUE DUMACH
1963 !***PURPOSE Compute the unit roundoff of the machine.
1965 !***TYPE KPP_REAL (RUMACH-S, DUMACH-D)
1966 !***KEYWORDS MACHINE CONSTANTS
1967 !***AUTHOR Hindmarsh, Alan C., (LLNL)
1970 ! KPP_REAL A, DUMACH
1973 ! *Function Return Values:
1974 ! A : the unit roundoff of the machine.
1977 ! The unit roundoff is defined as the smallest positive machine
1978 ! number u such that 1.0 + u .ne. 1.0. This is computed by DUMACH
1979 ! in a machine-independent manner.
1981 !***REFERENCES (NONE)
1982 !***ROUTINES CALLED DUMSUM
1983 !***REVISION HISTORY (YYYYMMDD)
1984 ! 19930216 DATE WRITTEN
1985 ! 19930818 Added SLATEC-format prologue. (FNF)
1986 ! 20030707 Added DUMSUM to force normal storage of COMP. (ACH)
1987 !***END PROLOGUE DUMACH
1990 !***FIRST EXECUTABLE STATEMENT DUMACH
1993 CALL DUMSUM(1.0D0
, U
, COMP
)
1994 IF (COMP
.NE
. 1.0D0
) GO
TO 10
1997 !----------------------- End of Function DUMACH ------------------------
2000 SUBROUTINE DUMSUM(A
,B
,C
)
2001 ! Routine to force normal storing of A + B, for DUMACH.
2005 END SUBROUTINE DUMSUM
2007 SUBROUTINE DCFODE (METH
, ELCO
, TESCO
)
2008 !***BEGIN PROLOGUE DCFODE
2010 !***PURPOSE Set ODE integrator coefficients.
2011 !***TYPE KPP_REAL (SCFODE-S, DCFODE-D)
2012 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2015 ! DCFODE is called by the integrator routine to set coefficients
2016 ! needed there. The coefficients for the current method, as
2017 ! given by the value of METH, are set for all orders and saved.
2018 ! The maximum order assumed here is 12 if METH = 1 and 5 if METH = 2.
2019 ! (A smaller value of the maximum order is also allowed.)
2020 ! DCFODE is called once at the beginning of the problem,
2021 ! and is not called again unless and until METH is changed.
2023 ! The ELCO array contains the basic method coefficients.
2024 ! The coefficients el(i), 1 .le. i .le. nq+1, for the method of
2025 ! order nq are stored in ELCO(i,nq). They are given by a genetrating
2027 ! l(x) = el(1) + el(2)*x + ... + el(nq+1)*x**nq.
2028 ! For the implicit Adams methods, l(x) is given by
2029 ! dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1), l(-1) = 0.
2030 ! For the BDF methods, l(x) is given by
2031 ! l(x) = (x+1)*(x+2)* ... *(x+nq)/K,
2032 ! where K = factorial(nq)*(1 + 1/2 + ... + 1/nq).
2034 ! The TESCO array contains test constants used for the
2035 ! local error test and the selection of step size and/or order.
2036 ! At order nq, TESCO(k,nq) is used for the selection of step
2037 ! size at order nq - 1 if k = 1, at order nq if k = 2, and at order
2041 !***ROUTINES CALLED (NONE)
2042 !***REVISION HISTORY (YYMMDD)
2043 ! 791129 DATE WRITTEN
2044 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2045 ! 890503 Minor cosmetic changes. (FNF)
2046 ! 930809 Renamed to allow single/double precision versions. (ACH)
2047 !***END PROLOGUE DCFODE
2050 INTEGER I
, IB
, NQ
, NQM1
, NQP1
2051 KPP_REAL
ELCO(13,12), TESCO(3,12), PC(12)
2052 KPP_REAL AGAMQ
, FNQ
, FNQM1
, PINT
, RAGQ
, RQFAC
, RQ1FAC
, TSIGN
, XPIN
2054 !***FIRST EXECUTABLE STATEMENT DCFODE
2055 GO
TO (100, 200), METH
2057 100 ELCO(1,1) = 1.0D0
2066 !-----------------------------------------------------------------------
2067 ! The PC array will contain the coefficients of the polynomial
2068 ! p(x) = (x+1)*(x+2)*...*(x+nq-1).
2069 ! Initially, p(x) = 1.
2070 !-----------------------------------------------------------------------
2076 ! Form coefficients of p(x)*(x+nq-1). ----------------------------------
2080 110 PC(I
) = PC(I
-1) + FNQM1
*PC(I
)
2082 ! Compute integral, -1 to 0, of p(x) and x*p(x). -----------------------
2088 PINT
= PINT
+ TSIGN
*PC(I
)/I
2089 120 XPIN
= XPIN
+ TSIGN
*PC(I
)/(I
+1)
2090 ! Store coefficients in ELCO and TESCO. --------------------------------
2091 ELCO(1,NQ
) = PINT
*RQ1FAC
2094 130 ELCO(I
+1,NQ
) = RQ1FAC
*PC(I
)/I
2098 IF (NQ
.LT
. 12) TESCO(1,NQP1
) = RAGQ
*RQFAC
/NQP1
2099 TESCO(3,NQM1
) = RAGQ
2106 !-----------------------------------------------------------------------
2107 ! The PC array will contain the coefficients of the polynomial
2108 ! p(x) = (x+1)*(x+2)*...*(x+nq).
2109 ! Initially, p(x) = 1.
2110 !-----------------------------------------------------------------------
2113 ! Form coefficients of p(x)*(x+nq). ------------------------------------
2117 210 PC(I
) = PC(I
-1) + FNQ
*PC(I
)
2119 ! Store coefficients in ELCO and TESCO. --------------------------------
2121 220 ELCO(I
,NQ
) = PC(I
)/PC(2)
2123 TESCO(1,NQ
) = RQ1FAC
2124 TESCO(2,NQ
) = NQP1
/ELCO(1,NQ
)
2125 TESCO(3,NQ
) = (NQ
+2)/ELCO(1,NQ
)
2129 !----------------------- END OF SUBROUTINE DCFODE ----------------------
2130 END SUBROUTINE DCFODE
2132 SUBROUTINE DINTDY (T
, K
, YH
, NYH
, DKY
, IFLAG
)
2133 !***BEGIN PROLOGUE DINTDY
2135 !***PURPOSE Interpolate solution derivatives.
2136 !***TYPE KPP_REAL (SINTDY-S, DINTDY-D)
2137 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2140 ! DINTDY computes interpolated values of the K-th derivative of the
2141 ! dependent variable vector y, and stores it in DKY. This routine
2142 ! is called within the package with K = 0 and T = TOUT, but may
2143 ! also be called by the user for any K up to the current order.
2144 ! (See detailed instructions in the usage documentation.)
2146 ! The computed values in DKY are gotten by interpolation using the
2147 ! Nordsieck history array YH. This array corresponds uniquely to a
2148 ! vector-valued polynomial of degree NQCUR or less, and DKY is set
2149 ! to the K-th derivative of this polynomial at T.
2150 ! The formula for DKY is:
2152 ! DKY(i) = sum c(j,K) * (T - tn)**(j-K) * h**(-j) * YH(i,j+1)
2154 ! where c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, tn = TCUR, h = HCUR.
2155 ! The quantities nq = NQCUR, l = nq+1, N = NEQ, tn, and h are
2156 ! communicated by COMMON. The above sum is done in reverse order.
2157 ! IFLAG is returned negative if either K or T is out of bounds.
2160 !***ROUTINES CALLED XERRWD
2161 !***COMMON BLOCKS DLS001
2162 !***REVISION HISTORY (YYMMDD)
2163 ! 791129 DATE WRITTEN
2164 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2165 ! 890503 Minor cosmetic changes. (FNF)
2166 ! 930809 Renamed to allow single/double precision versions. (ACH)
2167 ! 010418 Reduced size of Common block /DLS001/. (ACH)
2168 ! 031105 Restored 'own' variables to Common block /DLS001/, to
2169 ! enable interrupt/restart feature. (ACH)
2170 ! 050427 Corrected roundoff decrement in TP. (ACH)
2171 !***END PROLOGUE DINTDY
2173 INTEGER K
, NYH
, IFLAG
2174 KPP_REAL T
, YH(NYH
,*), DKY(*)
2175 INTEGER IOWND
, IOWNS
, &
2176 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2177 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2178 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2180 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
2181 COMMON /DLS001
/ ROWNS(209), &
2182 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
, &
2183 IOWND(6), IOWNS(6), &
2184 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2185 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2186 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2187 INTEGER I
, IC
, J
, JB
, JB2
, JJ
, JJ1
, JP1
2188 KPP_REAL C
, R
, S
, TP
2191 !***FIRST EXECUTABLE STATEMENT DINTDY
2193 IF (K
.LT
. 0 .OR
. K
.GT
. NQ
) GO
TO 80
2194 TP
= TN
- HU
- 100.0D0
*UROUND
*SIGN(ABS(TN
) + ABS(HU
), HU
)
2195 IF ((T
-TP
)*(T
-TN
) .GT
. 0.0D0
) GO
TO 90
2199 IF (K
.EQ
. 0) GO
TO 15
2205 20 DKY(I
) = C
*YH(I
,L
)
2206 IF (K
.EQ
. NQ
) GO
TO 55
2212 IF (K
.EQ
. 0) GO
TO 35
2218 40 DKY(I
) = C
*YH(I
,JP1
) + S
*DKY(I
)
2220 IF (K
.EQ
. 0) RETURN
2223 60 DKY(I
) = R
*DKY(I
)
2226 80 MSG
= 'DINTDY- K (=I1) illegal '
2227 CALL XERRWD (MSG
, 30, 51, 0, 1, K
, 0, 0, 0.0D0
, 0.0D0
)
2230 90 MSG
= 'DINTDY- T (=R1) illegal '
2231 CALL XERRWD (MSG
, 30, 52, 0, 0, 0, 0, 1, T
, 0.0D0
)
2232 MSG
=' T not in interval TCUR - HU (= R1) to TCUR (=R2) '
2233 CALL XERRWD (MSG
, 60, 52, 0, 0, 0, 0, 2, TP
, TN
)
2236 !----------------------- END OF SUBROUTINE DINTDY ----------------------
2237 END SUBROUTINE DINTDY
2239 SUBROUTINE DPREPJ (NEQ
, Y
, YH
, NYH
, EWT
, FTEM
, SAVF
, WM
, IWM
, F
, JAC
)
2240 !***BEGIN PROLOGUE DPREPJ
2242 !***PURPOSE Compute and process Newton iteration matrix.
2243 !***TYPE KPP_REAL (SPREPJ-S, DPREPJ-D)
2244 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2247 ! DPREPJ is called by DSTODE to compute and process the matrix
2248 ! P = I - h*el(1)*J , where J is an approximation to the Jacobian.
2249 ! Here J is computed by the user-supplied routine JAC if
2250 ! MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5.
2251 ! If MITER = 3, a diagonal approximation to J is used.
2252 ! J is stored in WM and replaced by P. If MITER .ne. 3, P is then
2253 ! subjected to LU decomposition in preparation for later solution
2254 ! of linear systems with P as coefficient matrix. This is done
2255 ! by DGEFA if MITER = 1 or 2, and by DGBFA if MITER = 4 or 5.
2257 ! In addition to variables described in DSTODE and DLSODE prologues,
2258 ! communication with DPREPJ uses the following:
2259 ! Y = array containing predicted values on entry.
2260 ! FTEM = work array of length N (ACOR in DSTODE).
2261 ! SAVF = array containing f evaluated at predicted y.
2262 ! WM = real work space for matrices. On output it contains the
2263 ! inverse diagonal matrix if MITER = 3 and the LU decomposition
2264 ! of P if MITER is 1, 2 , 4, or 5.
2265 ! Storage of matrix elements starts at WM(3).
2266 ! WM also contains the following matrix-related data:
2267 ! WM(1) = SQRT(UROUND), used in numerical Jacobian increments.
2268 ! WM(2) = H*EL0, saved for later use if MITER = 3.
2269 ! IWM = integer work space containing pivot information, starting at
2270 ! IWM(21), if MITER is 1, 2, 4, or 5. IWM also contains band
2271 ! parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.
2272 ! EL0 = EL(1) (input).
2273 ! IERPJ = output error flag, = 0 if no trouble, .gt. 0 if
2274 ! P matrix found to be singular.
2275 ! JCUR = output flag = 1 to indicate that the Jacobian matrix
2276 ! (or approximation) is now current.
2277 ! This routine also uses the COMMON variables EL0, H, TN, UROUND,
2278 ! MITER, N, NFE, and NJE.
2281 !***ROUTINES CALLED DGBFA, DGEFA, DVNORM
2282 !***COMMON BLOCKS DLS001
2283 !***REVISION HISTORY (YYMMDD)
2284 ! 791129 DATE WRITTEN
2285 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2286 ! 890504 Minor cosmetic changes. (FNF)
2287 ! 930809 Renamed to allow single/double precision versions. (ACH)
2288 ! 010418 Reduced size of Common block /DLS001/. (ACH)
2289 ! 031105 Restored 'own' variables to Common block /DLS001/, to
2290 ! enable interrupt/restart feature. (ACH)
2291 !***END PROLOGUE DPREPJ
2294 INTEGER NEQ
, NYH
, IWM(*)
2295 KPP_REAL
Y(*), YH(NYH
,*), EWT(*), FTEM(*), SAVF(*), WM(*)
2296 INTEGER IOWND
, IOWNS
, &
2297 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2298 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2299 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2301 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
2302 COMMON /DLS001
/ ROWNS(209), &
2303 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
, &
2304 IOWND(6), IOWNS(6), &
2305 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2306 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2307 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2308 INTEGER I
, I1
, I2
, IER
, II
, J
, J1
, JJ
, LENP
, &
2309 MBA
, MBAND
, MEB1
, MEBAND
, ML
, ML3
, MU
, NP1
2310 KPP_REAL CON
, DI
, FAC
, HL0
, R
, R0
, SRUR
, YI
, YJ
, YJJ
2313 !***FIRST EXECUTABLE STATEMENT DPREPJ
2325 CALL JAC_CHEM (NEQ
, TN
, Y
, WM(3))
2327 WM(I
+2) = WM(I
+2)*CON
2329 ! Add identity matrix
2333 WM(J
) = WM(J
) + 1.0D0
2336 ! Do LU decomposition on P
2337 CALL DGETRF(N
,N
,WM(3),N
,IWM(21),IER
)
2339 CALL JAC_CHEM (NEQ
, TN
, Y
, WM(3))
2341 WM(i
+2) = WM(i
+2)*CON
2343 ! Add identity matrix
2346 WM(j
) = WM(j
) + 1.0D0
2348 ! Do LU decomposition on P
2349 CALL KppDecomp(WM(3),IER
)
2351 IF (IER
.NE
. 0) IERPJ
= 1
2353 !----------------------- END OF SUBROUTINE DPREPJ ----------------------
2354 END SUBROUTINE DPREPJ
2356 SUBROUTINE DSOLSY (WM
, IWM
, X
, TEM
)
2357 !***BEGIN PROLOGUE DSOLSY
2359 !***PURPOSE ODEPACK linear system solver.
2360 !***TYPE KPP_REAL (SSOLSY-S, DSOLSY-D)
2361 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2364 ! This routine manages the solution of the linear system arising from
2365 ! a chord iteration. It is called if MITER .ne. 0.
2366 ! If MITER is 1 or 2, it calls DGESL to accomplish this.
2367 ! If MITER = 3 it updates the coefficient h*EL0 in the diagonal
2368 ! matrix, and then computes the solution.
2369 ! If MITER is 4 or 5, it calls DGBSL.
2370 ! Communication with DSOLSY uses the following variables:
2371 ! WM = real work space containing the inverse diagonal matrix if
2372 ! MITER = 3 and the LU decomposition of the matrix otherwise.
2373 ! Storage of matrix elements starts at WM(3).
2374 ! WM also contains the following matrix-related data:
2375 ! WM(1) = SQRT(UROUND) (not used here),
2376 ! WM(2) = HL0, the previous value of h*EL0, used if MITER = 3.
2377 ! IWM = integer work space containing pivot information, starting at
2378 ! IWM(21), if MITER is 1, 2, 4, or 5. IWM also contains band
2379 ! parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.
2380 ! X = the right-hand side vector on input, and the solution vector
2381 ! on output, of length N.
2382 ! TEM = vector of work space of length N, not used in this version.
2383 ! IERSL = output flag (in COMMON). IERSL = 0 if no trouble occurred.
2384 ! IERSL = 1 if a singular matrix arose with MITER = 3.
2385 ! This routine also uses the COMMON variables EL0, H, MITER, and N.
2388 !***ROUTINES CALLED DGBSL, DGESL
2389 !***COMMON BLOCKS DLS001
2390 !***REVISION HISTORY (YYMMDD)
2391 ! 791129 DATE WRITTEN
2392 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2393 ! 890503 Minor cosmetic changes. (FNF)
2394 ! 930809 Renamed to allow single/double precision versions. (ACH)
2395 ! 010418 Reduced size of Common block /DLS001/. (ACH)
2396 ! 031105 Restored 'own' variables to Common block /DLS001/, to
2397 ! enable interrupt/restart feature. (ACH)
2398 !***END PROLOGUE DSOLSY
2401 KPP_REAL
WM(*), X(*), TEM(*)
2402 INTEGER IOWND
, IOWNS
, &
2403 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2404 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2405 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2407 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
2408 COMMON /DLS001
/ ROWNS(209), &
2409 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
, &
2410 IOWND(6), IOWNS(6), &
2411 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2412 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2413 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2414 INTEGER I
, MEBAND
, ML
, MU
2415 KPP_REAL DI
, HL0
, PHL0
, R
2417 !***FIRST EXECUTABLE STATEMENT DSOLSY
2420 CALL DGETRS ('N',N
,1,WM(3),N
,IWM(21),X
,N
,0)
2422 CALL KppSolve(WM(3),X
)
2425 !----------------------- END OF SUBROUTINE DSOLSY ----------------------
2426 END SUBROUTINE DSOLSY
2428 SUBROUTINE DSRCOM (RSAV
, ISAV
, JOB
)
2429 !***BEGIN PROLOGUE DSRCOM
2431 !***PURPOSE Save/restore ODEPACK COMMON blocks.
2432 !***TYPE KPP_REAL (SSRCOM-S, DSRCOM-D)
2433 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2436 ! This routine saves or restores (depending on JOB) the contents of
2437 ! the COMMON block DLS001, which is used internally
2438 ! by one or more ODEPACK solvers.
2440 ! RSAV = real array of length 218 or more.
2441 ! ISAV = integer array of length 37 or more.
2442 ! JOB = flag indicating to save or restore the COMMON blocks:
2443 ! JOB = 1 if COMMON is to be saved (written to RSAV/ISAV)
2444 ! JOB = 2 if COMMON is to be restored (read from RSAV/ISAV)
2445 ! A call with JOB = 2 presumes a prior call with JOB = 1.
2448 !***ROUTINES CALLED (NONE)
2449 !***COMMON BLOCKS DLS001
2450 !***REVISION HISTORY (YYMMDD)
2451 ! 791129 DATE WRITTEN
2452 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2453 ! 890503 Minor cosmetic changes. (FNF)
2454 ! 921116 Deleted treatment of block /EH0001/. (ACH)
2455 ! 930801 Reduced Common block length by 2. (ACH)
2456 ! 930809 Renamed to allow single/double precision versions. (ACH)
2457 ! 010418 Reduced Common block length by 209+12. (ACH)
2458 ! 031105 Restored 'own' variables to Common block /DLS001/, to
2459 ! enable interrupt/restart feature. (ACH)
2460 ! 031112 Added SAVE statement for data-loaded constants.
2461 !***END PROLOGUE DSRCOM
2463 INTEGER ISAV(*), JOB
2465 INTEGER I
, LENILS
, LENRLS
2466 KPP_REAL
RSAV(*), RLS
2468 COMMON /DLS001
/ RLS(218), ILS(37)
2469 DATA LENRLS
/218/, LENILS
/37/
2471 !***FIRST EXECUTABLE STATEMENT DSRCOM
2472 IF (JOB
.EQ
. 2) GO
TO 100
2482 110 RLS(I
) = RSAV(I
)
2484 120 ILS(I
) = ISAV(I
)
2486 !----------------------- END OF SUBROUTINE DSRCOM ----------------------
2487 END SUBROUTINE DSRCOM
2489 SUBROUTINE DSTODE (NEQ
, Y
, YH
, NYH
, YH1
, EWT
, SAVF
, ACOR
, &
2491 !WM, IWM, F, JAC, PJAC, SLVS)
2492 !***BEGIN PROLOGUE DSTODE
2494 !***PURPOSE Performs one step of an ODEPACK integration.
2495 !***TYPE KPP_REAL (SSTODE-S, DSTODE-D)
2496 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2499 ! DSTODE performs one step of the integration of an initial value
2500 ! problem for a system of ordinary differential equations.
2501 ! Note: DSTODE is independent of the value of the iteration method
2502 ! indicator MITER, when this is .ne. 0, and hence is independent
2503 ! of the type of chord method used, or the Jacobian structure.
2504 ! Communication with DSTODE is done with the following variables:
2506 ! NEQ = integer array containing problem size in NEQ, and
2507 ! passed as the NEQ argument in all calls to F and JAC.
2508 ! Y = an array of length .ge. N used as the Y argument in
2509 ! all calls to F and JAC.
2510 ! YH = an NYH by LMAX array containing the dependent variables
2511 ! and their approximate scaled derivatives, where
2512 ! LMAX = MAXORD + 1. YH(i,j+1) contains the approximate
2513 ! j-th derivative of y(i), scaled by h**j/factorial(j)
2514 ! (j = 0,1,...,NQ). on entry for the first step, the first
2515 ! two columns of YH must be set from the initial values.
2516 ! NYH = a constant integer .ge. N, the first dimension of YH.
2517 ! YH1 = a one-dimensional array occupying the same space as YH.
2518 ! EWT = an array of length N containing multiplicative weights
2519 ! for local error measurements. Local errors in Y(i) are
2520 ! compared to 1.0/EWT(i) in various error tests.
2521 ! SAVF = an array of working storage, of length N.
2522 ! Also used for input of YH(*,MAXORD+2) when JSTART = -1
2523 ! and MAXORD .lt. the current order NQ.
2524 ! ACOR = a work array of length N, used for the accumulated
2525 ! corrections. On a successful return, ACOR(i) contains
2526 ! the estimated one-step local error in Y(i).
2527 ! WM,IWM = real and integer work arrays associated with matrix
2528 ! operations in chord iteration (MITER .ne. 0).
2529 ! PJAC = name of routine to evaluate and preprocess Jacobian matrix
2530 ! and P = I - h*el0*JAC, if a chord method is being used.
2531 ! SLVS = name of routine to solve linear system in chord iteration.
2532 ! CCMAX = maximum relative change in h*el0 before PJAC is called.
2533 ! H = the step size to be attempted on the next step.
2534 ! H is altered by the error control algorithm during the
2535 ! problem. H can be either positive or negative, but its
2536 ! sign must remain constant throughout the problem.
2537 ! HMIN = the minimum absolute value of the step size h to be used.
2538 ! HMXI = inverse of the maximum absolute value of h to be used.
2539 ! HMXI = 0.0 is allowed and corresponds to an infinite hmax.
2540 ! HMIN and HMXI may be changed at any time, but will not
2541 ! take effect until the next change of h is considered.
2542 ! TN = the independent variable. TN is updated on each step taken.
2543 ! JSTART = an integer used for input only, with the following
2544 ! values and meanings:
2545 ! 0 perform the first step.
2546 ! .gt.0 take a new step continuing from the last.
2547 ! -1 take the next step with a new value of H, MAXORD,
2548 ! N, METH, MITER, and/or matrix parameters.
2549 ! -2 take the next step with a new value of H,
2550 ! but with other inputs unchanged.
2551 ! On return, JSTART is set to 1 to facilitate continuation.
2552 ! KFLAG = a completion code with the following meanings:
2553 ! 0 the step was succesful.
2554 ! -1 the requested error could not be achieved.
2555 ! -2 corrector convergence could not be achieved.
2556 ! -3 fatal error in PJAC or SLVS.
2557 ! A return with KFLAG = -1 or -2 means either
2558 ! abs(H) = HMIN or 10 consecutive failures occurred.
2559 ! On a return with KFLAG negative, the values of TN and
2560 ! the YH array are as of the beginning of the last
2561 ! step, and H is the last step size attempted.
2562 ! MAXORD = the maximum order of integration method to be allowed.
2563 ! MAXCOR = the maximum number of corrector iterations allowed.
2564 ! MSBP = maximum number of steps between PJAC calls (MITER .gt. 0).
2565 ! MXNCF = maximum number of convergence failures allowed.
2566 ! METH/MITER = the method flags. See description in driver.
2567 ! N = the number of first-order differential equations.
2568 ! The values of CCMAX, H, HMIN, HMXI, TN, JSTART, KFLAG, MAXORD,
2569 ! MAXCOR, MSBP, MXNCF, METH, MITER, and N are communicated via COMMON.
2572 !***ROUTINES CALLED DCFODE, DVNORM
2573 !***COMMON BLOCKS DLS001
2574 !***REVISION HISTORY (YYMMDD)
2575 ! 791129 DATE WRITTEN
2576 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
2577 ! 890503 Minor cosmetic changes. (FNF)
2578 ! 930809 Renamed to allow single/double precision versions. (ACH)
2579 ! 010418 Reduced size of Common block /DLS001/. (ACH)
2580 ! 031105 Restored 'own' variables to Common block /DLS001/, to
2581 ! enable interrupt/restart feature. (ACH)
2582 !***END PROLOGUE DSTODE
2584 EXTERNAL F
, JAC
!, PJAC, SLVS
2585 INTEGER NEQ
, NYH
, IWM(*)
2586 KPP_REAL
Y(*), YH(NYH
,*), YH1(*), EWT(*), SAVF(*), &
2588 INTEGER IOWND
, IALTH
, IPUP
, LMAX
, MEO
, NQNYH
, NSLP
, &
2589 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2590 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2591 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2592 INTEGER I
, I1
, IREDO
, IRET
, J
, JB
, M
, NCF
, NEWQ
2593 KPP_REAL CONIT
, CRATE
, EL
, ELCO
, HOLD
, RMAX
, TESCO
, &
2594 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
2595 KPP_REAL DCON
, DDN
, DEL
, DELP
, DSM
, DUP
, EXDN
, EXSM
, &
2596 EXUP
,R
, RH
, RHDN
, RHSM
, RHUP
, TOLD
2598 COMMON /DLS001
/ CONIT
, CRATE
, EL(13), ELCO(13,12), &
2599 HOLD
, RMAX
, TESCO(3,12), &
2600 CCMAX
, EL0
, H
, HMIN
, HMXI
, HU
, RC
, TN
, UROUND
, &
2601 IOWND(6), IALTH
, IPUP
, LMAX
, MEO
, NQNYH
, NSLP
, &
2602 ICF
, IERPJ
, IERSL
, JCUR
, JSTART
, KFLAG
, L
, &
2603 LYH
, LEWT
, LACOR
, LSAVF
, LWM
, LIWM
, METH
, MITER
, &
2604 MAXORD
, MAXCOR
, MSBP
, MXNCF
, N
, NQ
, NST
, NFE
, NJE
, NQU
2606 !***FIRST EXECUTABLE STATEMENT DSTODE
2615 IF (JSTART
.GT
. 0) GO
TO 200
2616 IF (JSTART
.EQ
. -1) GO
TO 100
2617 IF (JSTART
.EQ
. -2) GO
TO 160
2618 !-----------------------------------------------------------------------
2619 ! On the first call, the order is set to 1, and other variables are
2620 ! initialized. RMAX is the maximum ratio by which H can be increased
2621 ! in a single step. It is initially 1.E4 to compensate for the small
2622 ! initial H, but then is normally equal to 10. If a failure
2623 ! occurs (in corrector convergence or error test), RMAX is set to 2
2624 ! for the next increase.
2625 !-----------------------------------------------------------------------
2640 !-----------------------------------------------------------------------
2641 ! The following block handles preliminaries needed when JSTART = -1.
2642 ! IPUP is set to MITER to force a matrix update.
2643 ! If an order increase is about to be considered (IALTH = 1),
2644 ! IALTH is reset to 2 to postpone consideration one more step.
2645 ! If the caller has changed METH, DCFODE is called to reset
2646 ! the coefficients of the method.
2647 ! If the caller has changed MAXORD to a value less than the current
2648 ! order NQ, NQ is reduced to MAXORD, and a new H chosen accordingly.
2649 ! If H is to be changed, YH must be rescaled.
2650 ! If H or METH is being changed, IALTH is reset to L = NQ + 1
2651 ! to prevent further changes in H for that many steps.
2652 !-----------------------------------------------------------------------
2655 IF (IALTH
.EQ
. 1) IALTH
= 2
2656 IF (METH
.EQ
. MEO
) GO
TO 110
2657 CALL DCFODE (METH
, ELCO
, TESCO
)
2659 IF (NQ
.GT
. MAXORD
) GO
TO 120
2663 110 IF (NQ
.LE
. MAXORD
) GO
TO 160
2667 125 EL(I
) = ELCO(I
,NQ
)
2671 CONIT
= 0.5D0
/(NQ
+2)
2672 DDN
= DVNORM (N
, SAVF
, EWT
)/TESCO(1,L
)
2674 RHDN
= 1.0D0
/(1.3D0
*DDN
**EXDN
+ 0.0000013D0
)
2675 RH
= MIN(RHDN
,1.0D0
)
2677 IF (H
.EQ
. HOLD
) GO
TO 170
2678 RH
= MIN(RH
,ABS(H
/HOLD
))
2681 !-----------------------------------------------------------------------
2682 ! DCFODE is called to get all the integration coefficients for the
2683 ! current METH. Then the EL vector and related constants are reset
2684 ! whenever the order NQ is changed, or at the start of the problem.
2685 !-----------------------------------------------------------------------
2686 140 CALL DCFODE (METH
, ELCO
, TESCO
)
2688 155 EL(I
) = ELCO(I
,NQ
)
2692 CONIT
= 0.5D0
/(NQ
+2)
2693 GO
TO (160, 170, 200), IRET
2694 !-----------------------------------------------------------------------
2695 ! If H is being changed, the H ratio RH is checked against
2696 ! RMAX, HMIN, and HMXI, and the YH array rescaled. IALTH is set to
2697 ! L = NQ + 1 to prevent a change of H for that many steps, unless
2698 ! forced by a convergence or error test failure.
2699 !-----------------------------------------------------------------------
2700 160 IF (H
.EQ
. HOLD
) GO
TO 200
2705 170 RH
= MAX(RH
,HMIN
/ABS(H
))
2706 175 RH
= MIN(RH
,RMAX
)
2707 RH
= RH
/MAX(1.0D0
,ABS(H
)*HMXI
*RH
)
2712 180 YH(I
,J
) = YH(I
,J
)*R
2716 IF (IREDO
.EQ
. 0) GO
TO 690
2717 !-----------------------------------------------------------------------
2718 ! This section computes the predicted values by effectively
2719 ! multiplying the YH array by the Pascal Triangle matrix.
2720 ! RC is the ratio of new to old values of the coefficient H*EL(1).
2721 ! When RC differs from 1 by more than CCMAX, IPUP is set to MITER
2722 ! to force PJAC to be called, if a Jacobian is involved.
2723 ! In any case, PJAC is called at least every MSBP steps.
2724 !-----------------------------------------------------------------------
2725 200 IF (ABS(RC
-1.0D0
) .GT
. CCMAX
) IPUP
= MITER
2726 IF (NST
.GE
. NSLP
+MSBP
) IPUP
= MITER
2733 210 YH1(I
) = YH1(I
) + YH1(I
+NYH
)
2735 !-----------------------------------------------------------------------
2736 ! Up to MAXCOR corrector iterations are taken. A convergence test is
2737 ! made on the R.M.S. norm of each correction, weighted by the error
2738 ! weight vector EWT. The sum of the corrections is accumulated in the
2739 ! vector ACOR(i). The YH array is not altered in the corrector loop.
2740 !-----------------------------------------------------------------------
2744 CALL F (NEQ
, TN
, Y
, SAVF
)
2746 IF (IPUP
.LE
. 0) GO
TO 250
2747 !-----------------------------------------------------------------------
2748 ! If indicated, the matrix P = I - h*el(1)*J is reevaluated and
2749 ! preprocessed before starting the corrector iteration. IPUP is set
2750 ! to 0 as an indicator that this has been done.
2751 !-----------------------------------------------------------------------
2752 !CALL PJAC (NEQ, Y, YH, NYH, EWT, ACOR, SAVF, WM, IWM, F, JAC)
2753 CALL DPREPJ(NEQ
, Y
, YH
, NYH
, EWT
, ACOR
, SAVF
, WM
, IWM
, F
, JAC
)
2758 IF (IERPJ
.NE
. 0) GO
TO 430
2761 270 IF (MITER
.NE
. 0) GO
TO 350
2762 !-----------------------------------------------------------------------
2763 ! In the case of functional iteration, update Y directly from
2764 ! the result of the last function evaluation.
2765 !-----------------------------------------------------------------------
2767 SAVF(I
) = H
*SAVF(I
) - YH(I
,2)
2768 290 Y(I
) = SAVF(I
) - ACOR(I
)
2769 DEL
= DVNORM (N
, Y
, EWT
)
2771 Y(I
) = YH(I
,1) + EL(1)*SAVF(I
)
2772 300 ACOR(I
) = SAVF(I
)
2774 !-----------------------------------------------------------------------
2775 ! In the case of the chord method, compute the corrector error,
2776 ! and solve the linear system with that as right-hand side and
2777 ! P as coefficient matrix.
2778 !-----------------------------------------------------------------------
2780 360 Y(I
) = H
*SAVF(I
) - (YH(I
,2) + ACOR(I
))
2781 !CALL SLVS (WM, IWM, Y, SAVF)
2782 CALL DSOLSY(WM
, IWM
, Y
, SAVF
)
2783 IF (IERSL
.LT
. 0) GO
TO 430
2784 IF (IERSL
.GT
. 0) GO
TO 410
2785 DEL
= DVNORM (N
, Y
, EWT
)
2787 ACOR(I
) = ACOR(I
) + Y(I
)
2788 380 Y(I
) = YH(I
,1) + EL(1)*ACOR(I
)
2789 !-----------------------------------------------------------------------
2790 ! Test for convergence. If M.gt.0, an estimate of the convergence
2791 ! rate constant is stored in CRATE, and this is used in the test.
2792 !-----------------------------------------------------------------------
2793 400 IF (M
.NE
. 0) CRATE
= MAX(0.2D0
*CRATE
,DEL
/DELP
)
2794 DCON
= DEL
*MIN(1.0D0
,1.5D0
*CRATE
)/(TESCO(2,NQ
)*CONIT
)
2795 IF (DCON
.LE
. 1.0D0
) GO
TO 450
2797 IF (M
.EQ
. MAXCOR
) GO
TO 410
2798 IF (M
.GE
. 2 .AND
. DEL
.GT
. 2.0D0
*DELP
) GO
TO 410
2800 CALL F (NEQ
, TN
, Y
, SAVF
)
2803 !-----------------------------------------------------------------------
2804 ! The corrector iteration failed to converge.
2805 ! If MITER .ne. 0 and the Jacobian is out of date, PJAC is called for
2806 ! the next try. Otherwise the YH array is retracted to its values
2807 ! before prediction, and H is reduced, if possible. If H cannot be
2808 ! reduced or MXNCF failures have occurred, exit with KFLAG = -2.
2809 !-----------------------------------------------------------------------
2810 410 IF (MITER
.EQ
. 0 .OR
. JCUR
.EQ
. 1) GO
TO 430
2823 440 YH1(I
) = YH1(I
) - YH1(I
+NYH
)
2825 IF (IERPJ
.LT
. 0 .OR
. IERSL
.LT
. 0) GO
TO 680
2826 IF (ABS(H
) .LE
. HMIN
*1.00001D0
) GO
TO 670
2827 IF (NCF
.EQ
. MXNCF
) GO
TO 670
2832 !-----------------------------------------------------------------------
2833 ! The corrector has converged. JCUR is set to 0
2834 ! to signal that the Jacobian involved may need updating later.
2835 ! The local error test is made and control passes to statement 500
2837 !-----------------------------------------------------------------------
2839 IF (M
.EQ
. 0) DSM
= DEL
/TESCO(2,NQ
)
2840 IF (M
.GT
. 0) DSM
= DVNORM (N
, ACOR
, EWT
)/TESCO(2,NQ
)
2841 IF (DSM
.GT
. 1.0D0
) GO
TO 500
2842 !-----------------------------------------------------------------------
2843 ! After a successful step, update the YH array.
2844 ! Consider changing H if IALTH = 1. Otherwise decrease IALTH by 1.
2845 ! If IALTH is then 1 and NQ .lt. MAXORD, then ACOR is saved for
2846 ! use in a possible order increase on the next step.
2847 ! If a change in H is considered, an increase or decrease in order
2848 ! by one is considered also. A change in H is made only if it is by a
2849 ! factor of at least 1.1. If not, IALTH is set to 3 to prevent
2850 ! testing for that many steps.
2851 !-----------------------------------------------------------------------
2859 470 YH(I
,J
) = YH(I
,J
) + EL(J
)*ACOR(I
)
2861 IF (IALTH
.EQ
. 0) GO
TO 520
2862 IF (IALTH
.GT
. 1) GO
TO 700
2863 IF (L
.EQ
. LMAX
) GO
TO 700
2865 490 YH(I
,LMAX
) = ACOR(I
)
2867 !-----------------------------------------------------------------------
2868 ! The error test failed. KFLAG keeps track of multiple failures.
2869 ! Restore TN and the YH array to their previous values, and prepare
2870 ! to try the step again. Compute the optimum step size for this or
2871 ! one lower order. After 2 or more failures, H is forced to decrease
2872 ! by a factor of 0.2 or less.
2873 !-----------------------------------------------------------------------
2874 500 KFLAG
= KFLAG
- 1
2881 510 YH1(I
) = YH1(I
) - YH1(I
+NYH
)
2884 IF (ABS(H
) .LE
. HMIN
*1.00001D0
) GO
TO 660
2885 IF (KFLAG
.LE
. -3) GO
TO 640
2889 !-----------------------------------------------------------------------
2890 ! Regardless of the success or failure of the step, factors
2891 ! RHDN, RHSM, and RHUP are computed, by which H could be multiplied
2892 ! at order NQ - 1, order NQ, or order NQ + 1, respectively.
2893 ! In the case of failure, RHUP = 0.0 to avoid an order increase.
2894 ! The largest of these is determined and the new order chosen
2895 ! accordingly. If the order is to be increased, we compute one
2896 ! additional scaled derivative.
2897 !-----------------------------------------------------------------------
2899 IF (L
.EQ
. LMAX
) GO
TO 540
2901 530 SAVF(I
) = ACOR(I
) - YH(I
,LMAX
)
2902 DUP
= DVNORM (N
, SAVF
, EWT
)/TESCO(3,NQ
)
2904 RHUP
= 1.0D0
/(1.4D0
*DUP
**EXUP
+ 0.0000014D0
)
2906 RHSM
= 1.0D0
/(1.2D0
*DSM
**EXSM
+ 0.0000012D0
)
2908 IF (NQ
.EQ
. 1) GO
TO 560
2909 DDN
= DVNORM (N
, YH(1,L
), EWT
)/TESCO(1,NQ
)
2911 RHDN
= 1.0D0
/(1.3D0
*DDN
**EXDN
+ 0.0000013D0
)
2912 560 IF (RHSM
.GE
. RHUP
) GO
TO 570
2913 IF (RHUP
.GT
. RHDN
) GO
TO 590
2915 570 IF (RHSM
.LT
. RHDN
) GO
TO 580
2921 IF (KFLAG
.LT
. 0 .AND
. RH
.GT
. 1.0D0
) RH
= 1.0D0
2925 IF (RH
.LT
. 1.1D0
) GO
TO 610
2928 600 YH(I
,NEWQ
+1) = ACOR(I
)*R
2932 620 IF ((KFLAG
.EQ
. 0) .AND
. (RH
.LT
. 1.1D0
)) GO
TO 610
2933 IF (KFLAG
.LE
. -2) RH
= MIN(RH
,0.2D0
)
2934 !-----------------------------------------------------------------------
2935 ! If there is a change of order, reset NQ, l, and the coefficients.
2936 ! In any case H is reset according to RH and the YH array is rescaled.
2937 ! Then exit from 690 if the step was OK, or redo the step otherwise.
2938 !-----------------------------------------------------------------------
2939 IF (NEWQ
.EQ
. NQ
) GO
TO 170
2944 !-----------------------------------------------------------------------
2945 ! Control reaches this section if 3 or more failures have occured.
2946 ! If 10 failures have occurred, exit with KFLAG = -1.
2947 ! It is assumed that the derivatives that have accumulated in the
2948 ! YH array have errors of the wrong order. Hence the first
2949 ! derivative is recomputed, and the order is set to 1. Then
2950 ! H is reduced by a factor of 10, and the step is retried,
2951 ! until it succeeds or H reaches HMIN.
2952 !-----------------------------------------------------------------------
2953 640 IF (KFLAG
.EQ
. -10) GO
TO 660
2955 RH
= MAX(HMIN
/ABS(H
),RH
)
2959 CALL F (NEQ
, TN
, Y
, SAVF
)
2962 650 YH(I
,2) = H
*SAVF(I
)
2965 IF (NQ
.EQ
. 1) GO
TO 200
2970 !-----------------------------------------------------------------------
2971 ! All returns are made through this section. H is saved in HOLD
2972 ! to allow the caller to change H on the next step.
2973 !-----------------------------------------------------------------------
2981 700 R
= 1.0D0
/TESCO(2,NQU
)
2983 710 ACOR(I
) = ACOR(I
)*R
2987 !----------------------- END OF SUBROUTINE DSTODE ----------------------
2988 END SUBROUTINE DSTODE
2990 SUBROUTINE DEWSET (N
, ITOL
, RelTol
, AbsTol
, YCUR
, EWT
)
2991 !***BEGIN PROLOGUE DEWSET
2993 !***PURPOSE Set error weight vector.
2994 !***TYPE KPP_REAL (SEWSET-S, DEWSET-D)
2995 !***AUTHOR Hindmarsh, Alan C., (LLNL)
2998 ! This subroutine sets the error weight vector EWT according to
2999 ! EWT(i) = RelTol(i)*ABS(YCUR(i)) + AbsTol(i), i = 1,...,N,
3000 ! with the subscript on RelTol and/or AbsTol possibly replaced by 1 above,
3001 ! depending on the value of ITOL.
3004 !***ROUTINES CALLED (NONE)
3005 !***REVISION HISTORY (YYMMDD)
3006 ! 791129 DATE WRITTEN
3007 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
3008 ! 890503 Minor cosmetic changes. (FNF)
3009 ! 930809 Renamed to allow single/double precision versions. (ACH)
3010 !***END PROLOGUE DEWSET
3014 KPP_REAL
RelTol(*), AbsTol(*), YCUR(N
), EWT(N
)
3016 !***FIRST EXECUTABLE STATEMENT DEWSET
3017 GO
TO (10, 20, 30, 40), ITOL
3020 15 EWT(I
) = RelTol(1)*ABS(YCUR(I
)) + AbsTol(1)
3024 25 EWT(I
) = RelTol(1)*ABS(YCUR(I
)) + AbsTol(I
)
3028 35 EWT(I
) = RelTol(I
)*ABS(YCUR(I
)) + AbsTol(1)
3032 45 EWT(I
) = RelTol(I
)*ABS(YCUR(I
)) + AbsTol(I
)
3034 !----------------------- END OF SUBROUTINE DEWSET ----------------------
3035 END SUBROUTINE DEWSET
3037 KPP_REAL
FUNCTION DVNORM (N
, V
, W
)
3038 !***BEGIN PROLOGUE DVNORM
3040 !***PURPOSE Weighted root-mean-square vector norm.
3041 !***TYPE KPP_REAL (SVNORM-S, DVNORM-D)
3042 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3045 ! This function routine computes the weighted root-mean-square norm
3046 ! of the vector of length N contained in the array V, with weights
3047 ! contained in the array W of length N:
3048 ! DVNORM = SQRT( (1/N) * SUM( V(i)*W(i) )**2 )
3051 !***ROUTINES CALLED (NONE)
3052 !***REVISION HISTORY (YYMMDD)
3053 ! 791129 DATE WRITTEN
3054 ! 890501 Modified prologue to SLATEC/LDOC format. (FNF)
3055 ! 890503 Minor cosmetic changes. (FNF)
3056 ! 930809 Renamed to allow single/double precision versions. (ACH)
3057 !***END PROLOGUE DVNORM
3060 KPP_REAL
V(N
), W(N
), SUM
3062 !***FIRST EXECUTABLE STATEMENT DVNORM
3065 10 SUM
= SUM
+ (V(I
)*W(I
))**2
3066 DVNORM
= SQRT(SUM
/N
)
3068 !----------------------- END OF FUNCTION DVNORM ------------------------
3071 SUBROUTINE XERRWD (MSG
, NMES
, NERR
, LEVEL
, NI
, I1
, I2
, NR
, R1
, R2
)
3072 !***BEGIN PROLOGUE XERRWD
3074 !***PURPOSE Write error message with values.
3076 !***TYPE KPP_REAL (XERRWV-S, XERRWD-D)
3077 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3080 ! Subroutines XERRWD, XSETF, XSETUN, and the function routine IXSAV,
3081 ! as given here, constitute a simplified version of the SLATEC error
3084 ! All arguments are input arguments.
3086 ! MSG = The message (character array).
3087 ! NMES = The length of MSG (number of characters).
3088 ! NERR = The error number (not used).
3089 ! LEVEL = The error level..
3090 ! 0 or 1 means recoverable (control returns to caller).
3091 ! 2 means fatal (run is aborted--see note below).
3092 ! NI = Number of integers (0, 1, or 2) to be printed with message.
3093 ! I1,I2 = Integers to be printed, depending on NI.
3094 ! NR = Number of reals (0, 1, or 2) to be printed with message.
3095 ! R1,R2 = Reals to be printed, depending on NR.
3097 ! Note.. this routine is machine-dependent and specialized for use
3098 ! in limited context, in the following ways..
3099 ! 1. The argument MSG is assumed to be of type CHARACTER, and
3100 ! the message is printed with a format of (1X,A).
3101 ! 2. The message is assumed to take only one line.
3102 ! Multi-line messages are generated by repeated calls.
3103 ! 3. If LEVEL = 2, control passes to the statement STOP
3104 ! to abort the run. This statement may be machine-dependent.
3105 ! 4. R1 and R2 are assumed to be in double precision and are printed
3108 !***ROUTINES CALLED IXSAV
3109 !***REVISION HISTORY (YYMMDD)
3110 ! 920831 DATE WRITTEN
3111 ! 921118 Replaced MFLGSV/LUNSAV by IXSAV. (ACH)
3112 ! 930329 Modified prologue to SLATEC format. (FNF)
3113 ! 930407 Changed MSG from CHARACTER*1 array to variable. (FNF)
3114 ! 930922 Minor cosmetic change. (FNF)
3115 !***END PROLOGUE XERRWD
3119 ! For a different default logical unit number, IXSAV (or a subsidiary
3120 ! routine that it calls) will need to be modified.
3121 ! For a different run-abort command, change the statement following
3122 ! statement 100 at the end.
3123 !-----------------------------------------------------------------------
3124 ! Subroutines called by XERRWD.. None
3125 ! Function routine called by XERRWD.. IXSAV
3126 !-----------------------------------------------------------------------
3129 ! Declare arguments.
3132 INTEGER NMES
, NERR
, LEVEL
, NI
, I1
, I2
, NR
3135 ! Declare local variables.
3137 INTEGER LUNIT
, MESFLG
!, IXSAV
3139 ! Get logical unit number and message print flag.
3141 !***FIRST EXECUTABLE STATEMENT XERRWD
3142 LUNIT
= IXSAV (1, 0, .FALSE
.)
3143 MESFLG
= IXSAV (2, 0, .FALSE
.)
3144 IF (MESFLG
.EQ
. 0) GO
TO 100
3146 ! Write the message.
3148 WRITE (LUNIT
,10) MSG
3150 IF (NI
.EQ
. 1) WRITE (LUNIT
, 20) I1
3151 20 FORMAT(6X
,'In above message, I1 =',I10
)
3152 IF (NI
.EQ
. 2) WRITE (LUNIT
, 30) I1
,I2
3153 30 FORMAT(6X
,'In above message, I1 =',I10
,3X
,'I2 =',I10
)
3154 IF (NR
.EQ
. 1) WRITE (LUNIT
, 40) R1
3155 40 FORMAT(6X
,'In above message, R1 =',D21
.13
)
3156 IF (NR
.EQ
. 2) WRITE (LUNIT
, 50) R1
,R2
3157 50 FORMAT(6X
,'In above, R1 =',D21
.13
,3X
,'R2 =',D21
.13
)
3159 ! Abort the run if LEVEL = 2.
3161 100 IF (LEVEL
.NE
. 2) RETURN
3163 !----------------------- End of Subroutine XERRWD ----------------------
3164 END SUBROUTINE XERRWD
3166 SUBROUTINE XSETF (MFLAG
)
3167 !***BEGIN PROLOGUE XSETF
3168 !***PURPOSE Reset the error print control flag.
3170 !***TYPE ALL (XSETF-A)
3171 !***KEYWORDS ERROR CONTROL
3172 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3175 ! XSETF sets the error print control flag to MFLAG:
3176 ! MFLAG=1 means print all messages (the default).
3177 ! MFLAG=0 means no printing.
3179 !***SEE ALSO XERRWD, XERRWV
3180 !***REFERENCES (NONE)
3181 !***ROUTINES CALLED IXSAV
3182 !***REVISION HISTORY (YYMMDD)
3183 ! 921118 DATE WRITTEN
3184 ! 930329 Added SLATEC format prologue. (FNF)
3185 ! 930407 Corrected SEE ALSO section. (FNF)
3186 ! 930922 Made user-callable, and other cosmetic changes. (FNF)
3187 !***END PROLOGUE XSETF
3189 ! Subroutines called by XSETF.. None
3190 ! Function routine called by XSETF.. IXSAV
3191 !-----------------------------------------------------------------------
3193 INTEGER MFLAG
, JUNK
!, IXSAV
3195 !***FIRST EXECUTABLE STATEMENT XSETF
3196 IF (MFLAG
.EQ
. 0 .OR
. MFLAG
.EQ
. 1) JUNK
= IXSAV (2,MFLAG
,.TRUE
.)
3198 !----------------------- End of Subroutine XSETF -----------------------
3199 END SUBROUTINE XSETF
3201 SUBROUTINE XSETUN (LUN
)
3202 !***BEGIN PROLOGUE XSETUN
3203 !***PURPOSE Reset the logical unit number for error messages.
3205 !***TYPE ALL (XSETUN-A)
3206 !***KEYWORDS ERROR CONTROL
3209 ! XSETUN sets the logical unit number for error messages to LUN.
3211 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3212 !***SEE ALSO XERRWD, XERRWV
3213 !***REFERENCES (NONE)
3214 !***ROUTINES CALLED IXSAV
3215 !***REVISION HISTORY (YYMMDD)
3216 ! 921118 DATE WRITTEN
3217 ! 930329 Added SLATEC format prologue. (FNF)
3218 ! 930407 Corrected SEE ALSO section. (FNF)
3219 ! 930922 Made user-callable, and other cosmetic changes. (FNF)
3220 !***END PROLOGUE XSETUN
3222 ! Subroutines called by XSETUN.. None
3223 ! Function routine called by XSETUN.. IXSAV
3224 !-----------------------------------------------------------------------
3226 INTEGER LUN
, JUNK
!, IXSAV
3228 !***FIRST EXECUTABLE STATEMENT XSETUN
3229 IF (LUN
.GT
. 0) JUNK
= IXSAV (1,LUN
,.TRUE
.)
3231 !----------------------- End of Subroutine XSETUN ----------------------
3232 END SUBROUTINE XSETUN
3234 INTEGER FUNCTION IXSAV (IPAR
, IVALUE
, ISET
)
3235 !***BEGIN PROLOGUE IXSAV
3237 !***PURPOSE Save and recall error message control parameters.
3239 !***TYPE ALL (IXSAV-A)
3240 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3243 ! IXSAV saves and recalls one of two error message parameters:
3244 ! LUNIT, the logical unit number to which messages are printed, and
3245 ! MESFLG, the message print flag.
3246 ! This is a modification of the SLATEC library routine J4SAVE.
3248 ! Saved local variables..
3249 ! LUNIT = Logical unit number for messages. The default is obtained
3250 ! by a call to IUMACH (may be machine-dependent).
3251 ! MESFLG = Print control flag..
3252 ! 1 means print all messages (the default).
3253 ! 0 means no printing.
3256 ! IPAR = Parameter indicator (1 for LUNIT, 2 for MESFLG).
3257 ! IVALUE = The value to be set for the parameter, if ISET = .TRUE.
3258 ! ISET = Logical flag to indicate whether to read or write.
3259 ! If ISET = .TRUE., the parameter will be given
3260 ! the value IVALUE. If ISET = .FALSE., the parameter
3261 ! will be unchanged, and IVALUE is a dummy argument.
3264 ! IXSAV = The (old) value of the parameter.
3266 !***SEE ALSO XERRWD, XERRWV
3267 !***ROUTINES CALLED IUMACH
3268 !***REVISION HISTORY (YYMMDD)
3269 ! 921118 DATE WRITTEN
3270 ! 930329 Modified prologue to SLATEC format. (FNF)
3271 ! 930915 Added IUMACH call to get default output unit. (ACH)
3272 ! 930922 Minor cosmetic changes. (FNF)
3273 ! 010425 Type declaration for IUMACH added. (ACH)
3274 !***END PROLOGUE IXSAV
3276 ! Subroutines called by IXSAV.. None
3277 ! Function routine called by IXSAV.. IUMACH
3278 !-----------------------------------------------------------------------
3281 INTEGER IPAR
, IVALUE
3282 !-----------------------------------------------------------------------
3283 INTEGER LUNIT
, MESFLG
!, IUMACH
3284 !-----------------------------------------------------------------------
3285 ! The following Fortran-77 declaration is to cause the values of the
3286 ! listed (local) variables to be saved between calls to this routine.
3287 !-----------------------------------------------------------------------
3289 DATA LUNIT
/-1/, MESFLG
/1/
3291 !***FIRST EXECUTABLE STATEMENT IXSAV
3292 IF (IPAR
.EQ
. 1) THEN
3293 IF (LUNIT
.EQ
. -1) LUNIT
= IUMACH()
3295 IF (ISET
) LUNIT
= IVALUE
3298 IF (IPAR
.EQ
. 2) THEN
3300 IF (ISET
) MESFLG
= IVALUE
3304 !----------------------- End of Function IXSAV -------------------------
3307 INTEGER FUNCTION IUMACH()
3308 !***BEGIN PROLOGUE IUMACH
3309 !***PURPOSE Provide standard output unit number.
3311 !***TYPE INTEGER (IUMACH-I)
3312 !***KEYWORDS MACHINE CONSTANTS
3313 !***AUTHOR Hindmarsh, Alan C., (LLNL)
3316 ! INTEGER LOUT, IUMACH
3319 ! *Function Return Values:
3320 ! LOUT : the standard logical unit for Fortran output.
3322 !***REFERENCES (NONE)
3323 !***ROUTINES CALLED (NONE)
3324 !***REVISION HISTORY (YYMMDD)
3325 ! 930915 DATE WRITTEN
3326 ! 930922 Made user-callable, and other cosmetic changes. (FNF)
3327 !***END PROLOGUE IUMACH
3330 ! The built-in value of 6 is standard on a wide range of Fortran
3331 ! systems. This may be machine-dependent.
3333 !***FIRST EXECUTABLE STATEMENT IUMACH
3337 !----------------------- End of Function IUMACH ------------------------
3340 !---- END OF SUBROUTINE DLSODE AND ITS INTERNAL PROCEDURES
3341 END SUBROUTINE DLSODE
3342 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3343 SUBROUTINE FUN_CHEM(N
, T
, V
, FCT
)
3344 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3346 USE KPP_ROOT_Parameters
3348 USE KPP_ROOT_Function
, ONLY
: Fun
3354 KPP_REAL
:: V(NVAR
), FCT(NVAR
), T
, TOLD
3359 ! CALL Update_RCONST()
3360 ! CALL Update_PHOTO()
3363 CALL Fun(V
, FIX
, RCONST
, FCT
)
3367 END SUBROUTINE FUN_CHEM
3370 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3371 SUBROUTINE JAC_CHEM (N
, T
, V
, JF
)
3372 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3374 USE KPP_ROOT_Parameters
3376 USE KPP_ROOT_JacobianSP
3377 USE KPP_ROOT_Jacobian
, ONLY
: Jac_SP
3382 KPP_REAL
:: V(NVAR
), T
, TOLD
3383 INTEGER :: I
, J
, N
, ML
, MU
, NROWPD
3385 KPP_REAL
:: JV(LU_NONZERO
), JF(NVAR
,NVAR
)
3387 KPP_REAL
:: JF(LU_NONZERO
)
3393 ! CALL Update_RCONST()
3394 ! CALL Update_PHOTO()
3398 CALL Jac_SP(V
, FIX
, RCONST
, JV
)
3405 JF(LU_IROW(i
),LU_ICOL(i
)) = JV(i
)
3408 CALL Jac_SP(V
, FIX
, RCONST
, JF
)
3412 END SUBROUTINE JAC_CHEM
3415 END MODULE KPP_ROOT_Integrator