source: palm/trunk/UTIL/chemistry/gasphase_preproc/kpp/int/kpp_dvode.f90.save @ 4601

Last change on this file since 4601 was 2696, checked in by kanani, 7 years ago

Merge of branch palm4u into trunk

File size: 719.4 KB
Line 
1MODULE KPP_ROOT_Integrator
2
3  USE KPP_ROOT_Precision
4  USE KPP_ROOT_Global, ONLY: FIX, RCONST, TIME, ATOL, RTOL
5  USE KPP_ROOT_Parameters, ONLY: NVAR, NSPEC, NFIX, LU_NONZERO
6  USE KPP_ROOT_JacobianSP, ONLY: LU_DIAG
7  USE KPP_ROOT_LinearAlgebra, ONLY: KppDecomp, KppSolve, &
8               Set2zero, WLAMCH
9 
10  IMPLICIT NONE
11  PUBLIC
12  SAVE
13 
14  !~~~>  Statistics on the work performed by the VODE method
15  INTEGER :: Nfun,Njac,Nstp,Nacc,Nrej,Ndec,Nsol,Nsng
16  INTEGER, PARAMETER :: ifun=1, ijac=2, istp=3, iacc=4,  &
17    irej=5, idec=6, isol=7, isng=8, itexit=1, ihexit=2
18 
19  CHARACTER(LEN=50), PARAMETER, DIMENSION(-8:1) :: IERR_NAMES = (/ &
20    'Matrix is repeatedly singular                     ', & ! -8
21    'Step size too small                               ', & ! -7
22    'No of steps exceeds maximum bound                 ', & ! -6
23    'Improper tolerance values                         ', & ! -5
24    'FacMin/FacMax/FacRej must be positive             ', & ! -4
25    'Hmin/Hmax/Hstart must be positive                 ', & ! -3
26    'Improper value for maximal no of Newton iterations', & ! -2
27    'Improper value for maximal no of steps            ', & ! -1
28    '                                                  ', & !  0 (not used)
29    'Success                                           ' /) !  1
30
31CONTAINS
32
33SUBROUTINE INTEGRATE( TIN, TOUT, &
34  ICNTRL_U, RCNTRL_U, ISTATUS_U, RSTATUS_U, IERR_U )
35
36   USE KPP_ROOT_Parameters
37   USE KPP_ROOT_Global
38   IMPLICIT NONE
39
40   KPP_REAL, INTENT(IN) :: TIN  ! Start Time
41   KPP_REAL, INTENT(IN) :: TOUT ! End Time
42   ! Optional input parameters and statistics
43   INTEGER,  INTENT(IN),  OPTIONAL :: ICNTRL_U(20)
44   KPP_REAL, INTENT(IN),  OPTIONAL :: RCNTRL_U(20)
45   INTEGER,  INTENT(OUT), OPTIONAL :: ISTATUS_U(20)
46   KPP_REAL, INTENT(OUT), OPTIONAL :: RSTATUS_U(20)
47   INTEGER,  INTENT(OUT), OPTIONAL :: IERR_U
48
49   KPP_REAL :: RCNTRL(20), RSTATUS(20)
50   INTEGER       :: ICNTRL(20), ISTATUS(20), IERR
51!!$   INTEGER, SAVE :: Ntotal = 0
52   TYPE(VODE_OPTS) :: OPTIONS
53
54   ICNTRL(:)  = 0
55   RCNTRL(:)  = 0.0_dp
56   ISTATUS(:) = 0
57   RSTATUS(:) = 0.0_dp
58
59   ICNTRL(5) = 2 ! maximal order
60
61   ! If optional parameters are given, and if they are >0,
62   ! then they overwrite default settings.
63   IF (PRESENT(ICNTRL_U)) THEN
64     WHERE(ICNTRL_U(:) > 0) ICNTRL(:) = ICNTRL_U(:)
65   END IF
66   IF (PRESENT(RCNTRL_U)) THEN
67     WHERE(RCNTRL_U(:) > 0) RCNTRL(:) = RCNTRL_U(:)
68   END IF
69
70    OPTIONS = SET_OPTS(SPARSE_J=SPARSE,            &
71              ABSERR_VECTOR=ATOL, RELERR=RTOL, MXSTEP=100000,                      &
72              NZSWAG=LU_NONZERO, HMAX=MAXH, LOWER_BANDWIDTH=ML, UPPER_BANDWIDTH=MU,&
73              MA28_ELBOW_ROOM=10, MC19_SCALING=.TRUE., MA28_MESSAGES=.FALSE.,      &
74              MA28_EPS=1.0D-4, MA28_RPS=.TRUE.,                                    &
75              USER_SUPPLIED_SPARSITY=SUPPLY_STRUCTURE)
76
77   ISTATE = 1
78   NG = 0
79   ITASK = 1
80   CALL DVODE_F90(FUN_CHEM,NVAR,VAR,TIN,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JAC_CHEM)
81
82   STEPMIN = RSTATUS(ihexit) ! Save last step
83   
84   ! if optional parameters are given for output they to return information
85   IF (PRESENT(ISTATUS_U)) ISTATUS_U(:) = ISTATUS(1:20)
86   IF (PRESENT(RSTATUS_U)) RSTATUS_U(:) = RSTATUS(1:20)
87   IF (PRESENT(IERR_U)) THEN
88     IF (IERR==2) THEN ! DLSODE returns "2" after successful completion
89       IERR_U = 1 ! IERR_U will return "1" for successful completion
90     ELSE
91       IERR_U = IERR
92     ENDIF
93   ENDIF
94
95   END SUBROUTINE INTEGRATE
96
97
98!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99      SUBROUTINE FUN_CHEM(N, T, V, FCT)
100!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101
102      USE KPP_ROOT_Parameters
103      USE KPP_ROOT_Global
104      USE KPP_ROOT_Function, ONLY: Fun
105      USE KPP_ROOT_Rates
106
107      IMPLICIT NONE
108
109      INTEGER :: N
110      KPP_REAL :: V(NVAR), FCT(NVAR), T
111     
112!      TOLD = TIME
113!      TIME = T
114!      CALL Update_SUN()
115!      CALL Update_RCONST()
116!      CALL Update_PHOTO()
117!      TIME = TOLD
118
119      CALL Fun(V, FIX, RCONST, FCT)
120     
121      !Nfun=Nfun+1
122
123      END SUBROUTINE FUN_CHEM
124
125!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126      SUBROUTINE JAC_CHEM (N,T,V,IA,JA,NNZ,JF)
127!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128
129      USE KPP_ROOT_Parameters
130      USE KPP_ROOT_Global
131      USE KPP_ROOT_JacobianSP
132      USE KPP_ROOT_Jacobian, ONLY: Jac_SP
133      USE KPP_ROOT_Rates
134
135      IMPLICIT NONE
136
137      KPP_REAL :: V(NVAR), T
138      INTEGER, INTENT(IN)  :: N
139      INTEGER, INTENT(OUT) :: NNZ
140#ifdef FULL_ALGEBRA   
141      INTEGER :: I, J
142      KPP_REAL :: JV(LU_NONZERO), JF(NVAR,NVAR)
143#else
144      KPP_REAL :: JF(LU_NONZERO)
145      INTEGER  :: IA(LU_NONZERO), JA(LU_NONZERO)
146#endif   
147 
148!      TOLD = TIME
149!      TIME = T
150!      CALL Update_SUN()
151!      CALL Update_RCONST()
152!      CALL Update_PHOTO()
153!      TIME = TOLD
154   
155#ifdef FULL_ALGEBRA   
156      CALL Jac_SP(V, FIX, RCONST, JV)
157      DO j=1,NVAR
158      DO i=1,NVAR
159         JF(i,j) = 0.0d0
160      END DO
161      END DO
162      DO i=1,LU_NONZERO
163         JF(LU_IROW(i),LU_ICOL(i)) = JV(i)
164      END DO
165#else
166      CALL Jac_SP(V, FIX, RCONST, JF)
167      NNZ = LU_NONZERO
168      IA = LU_IROW
169      JA = LU_ICOL
170#endif   
171      !Njac=Njac+1
172   
173   END SUBROUTINE JAC_CHEM (N,T,V,IA,JA,NNZ,JF)
174
175   MODULE DVODE
176
177! This version is the December 2005 release.
178! Last change: 01/01/08
179! _____________________________________________________________________
180! Working Precision
181!  IMPLICIT NONE
182! Define the working precision for DVODE_F90. Change D0 to E0 in the
183! next statement to convert to single precision.
184!  INTEGER, PARAMETER, PRIVATE :: WP = KIND(1.0D0)
185! ______________________________________________________________________
186! Overview
187
188! The f77 ordinary differential equation solver VODE.f is applicable to
189! nonstiff systems of odes and to stiff systems having dense or banded
190! Jacobians. DVODE_F90 is a Fortran 90 extension of VODE.f. While
191! retaining all of the features available in VODE.f, we have
192! incorporated several new options in DVODE_F90 including:
193!   1. the ability to solve stiff systems with sparse Jacobians
194!   2. internal management of storage and work arrays
195!   3. specification of options via optional keywords
196!   4. the ability to perform root finding or "event detection"
197!   5. various new diagnostic and warning messages
198!   6. the ability to impose solution bounds
199!   7. several specialized options for dealing with sparsity
200! ______________________________________________________________________
201! Version Information
202
203! This is DVODE_F90, the double precision FORTRAN 90 extension of the
204! f77 DVODE.f ordinary differential equation solver. This version uses
205! MA28 for sparse Jacobians. This file and related information can be
206! obtained at the following support page:
207!
208!     http://www.radford.edu/~thompson/vodef90web/
209!
210! We are indebted to Richard Cox (ORNL) for providing us with his
211! implementation of MA28 in LSOD28.f (a variant of Alan Hindmarsh's
212! lsodes.f). We are indebted to Alan Hindmarsh for numerous contributions.
213! In particular, we borrowed liberally from the f77 solvers VODE.f,
214! LSODAR.f, and LSODES.f while developing DVODE_F90. We are indebted
215! to Doug Salane for providing us with his JACSP Jacobian routines.
216!
217! If you find a bug or encounter a problem with DVODE_F90, please
218! contact one of us:
219!    G.D. Byrne (gbyrne@wi.rr.com)
220!    S. Thompson (thompson@radford.edu)
221! A set of quick start instructions is provided below.
222! ______________________________________________________________________
223! Note on F90/F95 Compilers
224
225! To date we have used DVODE_F90 successfully with all F90/F95 compilers
226! to which we have access. In particular, we have used it with the Lahey
227! F90 and Lahey-Fujitsu F95 compilers, the Compaq Visual F90 compiler,
228! the g90 compiler, and the INTEL, Portland, Salford, and SUN compilers.
229! It should be noted that compilers such as Salford's FTN95 complain
230! about uninitialized arrays passed as subroutine arguments and the use of
231! slices of two dimensional arrays as one dimensional vectors, and will
232! not run using the strictest compiler options. It is perfectly safe to
233! use the /-CHECK compiler option to avoid these FTN95 runtime checks.
234! DVODE_F90 does not use any variable for numerical purposes until it
235! has been assigned an appropriate value.
236! ______________________________________________________________________
237! Quick Start Instructions
238
239! (1) Compile this file. Then compile, link, and execute the program
240!     example1.f90. The output is written to the file example1.dat.
241!     Verify that the last line of the output is the string
242!     'No errors occurred.'
243! (2) Repeat this process for the program example2.f90.
244!
245! Other test programs you may wish to run to verify your installation
246! of DVODE_F90 are:
247!
248! (3) Run the test programs nonstiffoptions.f90 and stiffoptions.f90
249!     and verify that the last line in the output files produced is
250!     'No errors occurred.' They solve the problems in the Toronto
251!     test suites using several different error tolerances and various
252!     solution options. Note that stiffoptions.f90 takes several
253!     minutes to run because it performs several thousand separate
254!     integrations.
255! (4) Locate the file robertson.f90 in the demo programs and look at
256!     how options are set using SET_OPTS, how DVODE_F90 is called to
257!     obtain the solution at desired output times, and how the
258!     derivative and Jacobian routines are supplied. Note too the
259!     manner in which the solution is constrained to be nonnegative.
260! (5) Locate demoharmonic.f90 and look at how root finding options
261!     are set and how the event residual routine is supplied to
262!     DVODE_F90.
263! (6) The other demo programs available from the DVODE_F90 support
264!     page illustrate various other solution options available in
265!     DVODE_F90. The demo programs may be obtained from
266!
267!        http://www.radford.edu/~thompson/vodef90web/index.html
268! ______________________________________________________________________
269! DVODE_F90 Full Documentation Prologue
270
271! Section 1.  Setting Options in DVODE_F90
272! Section 2.  Calling DVODE_F90
273! Section 3.  Choosing Error Tolerances
274! Section 4.  Choosing the Method of Integration
275! Section 5.  Interpolation of the Solution and Derivatives
276! Section 6.  Handling Events (Root Finding)
277! Section 7.  Gathering Integration Statistics
278! Section 8.  Determining Jacobian Sparsity Structure Arrays
279! Section 9.  Original DVODE Documentation Prologue
280! Section 10. Example Usage
281
282! Note: Search on the string 'Section' to locate these sections. You
283! may wish to refer to the support page which has the sections broken
284! into smaller pieces.
285! ______________________________________________________________________
286! Section 1.  Setting Options in DVODE_F90
287!
288! You can use any of three options routines:
289!
290! SET_NORMAL_OPTS
291! SET_INTERMEDIATE_OPTS
292! SET_OPTS
293
294! OPTIONS = SET_NORMAL_OPTS(DENSE_J, BANDED_J, SPARSE_J,               &
295!   USER_SUPPLIED_JACOBIAN, LOWER_BANDWIDTH, UPPER_BANDWIDTH,          &
296!   RELERR, ABSERR, ABSERR_VECTOR, NEVENTS)
297
298! OPTIONS = SET_INTERMEDIATE_OPTS(DENSE_J, BANDED_J, SPARSE_J,         &
299!   USER_SUPPLIED_JACOBIAN,LOWER_BANDWIDTH, UPPER_BANDWIDTH,           &
300!   RELERR, ABSERR, ABSERR_VECTOR,TCRIT, H0, HMAX, HMIN, MAXORD,       &
301!   MXSTEP, MXHNIL, NZSWAG, USER_SUPPLIED_SPARSITY, MA28_RPS,          &
302!   NEVENTS, CONSTRAINED, CLOWER, CUPPER, CHANGE_ONLY_f77_OPTIONS)     &
303
304! OPTIONS = SET_OPTS(METHOD_FLAG, DENSE_J, BANDED_J, SPARSE_J,         &
305!   USER_SUPPLIED_JACOBIAN, SAVE_JACOBIAN, CONSTANT_JACOBIAN,          &
306!   LOWER_BANDWIDTH, UPPER_BANDWIDTH, SUB_DIAGONALS, SUP_DIAGONALS,    &
307!   RELERR, RELERR_VECTOR, ABSERR, ABSERR_VECTOR, TCRIT, H0, HMAX,     &
308!   HMIN, MAXORD, MXSTEP, MXHNIL, YMAGWARN, SETH, UPIVOT, NZSWAG,      &
309!   USER_SUPPLIED_SPARSITY, NEVENTS, CONSTRAINED, CLOWER, CUPPER,      &
310!   MA28_ELBOW_ROOM, MC19_SCALING, MA28_MESSAGES, MA28_EPS,            &
311!   MA28_RPS, CHANGE_ONLY_f77_OPTIONS, JACOBIAN_BY_JACSP)
312
313! Please refer to the documentation prologue for each of these functions
314! to see what options may be used with each. Note that input to each is
315! via keyword and all variables except error tolerances are optional.
316! Defaults are used for unspecified options. If an option is available
317! in SET_NORMAL OPTS, it is available and has the same meaning in
318! SET_INTERMEDIATE_OPTS and SET_OPTS. Similarly, if an option is available
319! in SET_INTERMEDIATE_OPTS, it is available and has the same meaning in
320! SET_OPTS.
321
322! The first two functions are provided merely for convenience.
323! SET_NORMAL_OPTS is available simply to relieve you of reading the
324! documentation for SET_OPTS and to use default values for all but
325! the most common options. SET_INTERMEDIATE_OPTS is available to allow
326! you more control of the integration while still using default values
327! for less commonly used options. SET_OPTS allows you to specify any
328! of the options available in DVODE_F90.
329
330! Roughly, SET_NORMAL_OPTS is intended to provide for dense, banded,
331! and numerical sparse Jacobians without the need to specify other
332! specialized options. SET_INTERMEDIATE_OPTIONS is intended to allow
333! more general sparse Jacobian options. SET_OPTS is intended to provide
334
335! access to all options in DVODE_F90.
336
337! Please note that SET_INTERMEDIATE_OPTS can be invoked using the same
338! arguments as SET_NORMAL_OPTS; and SET_OPTS can be invoked using the
339! same arguments as either SET_NORMAL_OPTS or SET_INTERMEDIATE_OPTS.
340! If you wish you can simply delete SET_NORMAL_OPTS as well as
341! SET_INTERMEDIATE_OPTS and use only SET_OPTS for all problems. If you
342! do so, you need only include the options that you wish to use when
343! you invoke SET_OPTIONS.
344
345! In the following description any reference to SET_OPTS applies equally
346! to SET_NORMAL_OPTS and SET_INTERMEDIATE OPTS.
347
348! Before calling DVODE_F90 for the first time, SET_OPTS must be invoked.
349! Typically, SET_OPTS is called once to set the desired integration
350! options and parameters. DVODE_F90 is then called in an output loop to
351! obtain the solution for the desired times. A detailed description of
352! the DVODE_F90 arguments is given in a section below. Detailed descriptions
353! of the options available via SET_OPTS are given in the documentation prologue.
354! Although each option available in the f77 version of DVODE as well as
355! several additional ones are available in DVODE_F90 via SET_OPTS,
356! several of the available options are not relevant for most problems
357! and need not be specified. Refer to the accompanying demonstration
358! programs for specific examples of each usage. Note that after any call
359! to DVODE_F90, you may call GET_STATS to gather relevant integration
360! statistics. After your problem has completed, you may call
361! RELEASE_ARRAYS to deallocate any internal arrays allocated by
362! DVODE_F90 and to determine how much storage was used by DVODE_F90.
363!
364! To communicate with DVODE_F90 you will need to include the following
365! statement in your calling program:
366!    USE DVODE_F90_M
367! and include the following statement in your type declarations section:
368!    TYPE(VODE_OPTS) :: OPTIONS
369! Below are brief summaries of typical uses of SET_OPTS.
370! Nonstiff Problems:
371! OPTIONS = SET_OPTS(RELERR=RTOL,ABSERR=ATOL)
372!    The above use of SET_OPTS will integrate your system of odes
373!    using the nonstiff Adams methods while using a relative error
374!    tolerance of RTOL and an absolute error tolerance of ATOL.
375!    Your subsequent call to DVODE_F90 might look like:
376!    CALL DVODE_F90(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS)
377! OPTIONS = SET_OPTS(RELERR=RTOL,ABSERR=ATOL,NEVENTS=NG)
378!    If you wish to do root finding, SET_OPTS can be used as above.
379!    Here, NEVENTS is the desired number of root finding functions.
380!    Your subsequent call to DVODE_F90 might look like:
381!    CALL DVODE_F90(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,G_FCN=G)
382!    Here F is the name of your derivative subroutine and G is the
383!    name of your subroutine to evaluate residuals of the root
384!    finding functions.
385! OPTIONS = SET_OPTS(RELERR=RTOL,ABSERR_VECTOR=ATOL)
386!    This use of SET_OPTS indicates that a scalar relative error
387!    tolerance and a vector of absolute error tolerances will be
388!    used.
389! Stiff Problems, internally generated dense Jacobian:
390! OPTIONS = SET_OPTS(DENSE_J=.TRUE.,RELERR=RTOL,ABSERR=ATOL)
391!    This use of DENSE_J=.TRUE. indicates that DVODE_F90 will
392!    use the stiffly stable BDF methods and will approximate
393!    the Jacobian, considered to be a dense matrix, using
394!    finite differences. Your subsequent call to DVODE_F90
395!    might look like:
396!    CALL DVODE_F90(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS)
397! OPTIONS = SET_OPTS(DENSE_J=.TRUE.,ABSERR=ATOL,RELERR=RTOL, &
398!                    USER_SUPPLIED_JACOBIAN=.TRUE.)
399!    If you know the Jacobian and wish to supply subroutine JAC
400!    as described in the documentation for DVODE_F90, the options
401!    call could look like the above.
402!    Your subsequent call to DVODE_F90 might look like:
403!    CALL DVODE_F90(F1,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JAC)
404!    Here, JAC is the name of the subroutine that you provide to
405!    evaluate the known Jacobian.
406! Stiff Problems, internally generated banded Jacobian:
407! OPTIONS = SET_OPTS(BANDED_J=.TRUE.,RELERR=RTOL,ABSERR=ATOL, &
408!                       LOWER_BANDWIDTH=ML,UPPER_BANDWIDTH=MU)
409!    This use of BANDED_J=.TRUE. indicates that DVODE_F90 will
410!    use the stiffly stable BDF methods and will approximate the
411!    Jacobian, considered to be a banded matrix, using finite
412!    differences. Here ML is the lower bandwidth of the Jacobian
413!    and ML is the upper bandwidth of the Jacobian.
414! Stiff Problems, internally generated sparse Jacobian:
415! OPTIONS = SET_OPTS(SPARSE_J=.TRUE.,ABSERR=ATOL,RELERR=RTOL)
416!    This use of SET_OPTS indicates that the Jacobian is a sparse
417!    matrix. Its structure will be approximated internally by
418!    making calls to your derivative routine. If you know the
419!    structure before hand, you may provide it directly in a
420!    variety of ways as described in the documentation prologue
421!    for SET_OPTS. In addition, several other options related
422!    to sparsity are available.
423! More complicated common usage:
424!    Suppose you need to solve a stiff problem with a sparse Jacobian.
425!    After some time, the structure of the Jacobian changes and you
426!    wish to have DVODE_F90 recalculate the structure before continuing
427!    the integration. Suppose that initially you want to use an absolute
428!    error tolerance of 1.0D-5 and that when the Jacobian structure is
429!    changed you wish to reduce the error tolerance 1.0D-7. Your calls
430!    might look like this.
431!    RTOL = ...
432!    ATOL = 1.0D-5
433!    OPTIONS = SET_OPTS(SPARSE_J=.TRUE.,ABSERR=ATOL,RELERR=RTOL)
434!    Output loop:
435!       CALL DVODE_F90(FCN,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS)
436!       At desired time:
437!       ISTATE = 3
438!       ATOL = 1.0D-7
439!       OPTIONS = SET_OPTS(SPARSE_J=.TRUE.,ABSERR=ATOL,RELERR=RTOL)
440!    End of output loop
441
442! In the following we have summarized and described how some of the demonstration
443! programs set options and call DVODE_F90. In each case the necessary parameters
444! are defined before invoking SET_OPTS. The call to DVODE_F90 is in a loop in
445! which the output time is successively updated. The actual programs are available
446! from the web support page
447!
448!    http://www.radford. edu/~thompson/vodef90web/index.html/
449!
450!                              Problem Summary
451!
452! Problem                  NEQ      Jacobian            Features Illustrated
453!
454! Prologue Example 1        3        Dense               Basic
455!
456! Prologue Example 2        3        Dense               Root finding
457!
458! Robertson                 3        Dense               Solution bounds
459!
460! Harmonic Oscillator       4        Nonstiff            Root finding
461!
462! Flow Equations         5-1800      Sparse              Automatic determination
463!                                                        of sparsity arrays
464!
465! Diurnal Kinetics      50-5000      Sparse or banded    Sparsity options
466!
467!                       Options Used and DVODE_F90 Call
468!
469! Prologue Example 1
470!
471!    OPTIONS = SET_NORMAL_OPTS(DENSE_J=.TRUE., ABSERR_VECTOR=ATOL, RELERR=RTOL,     &
472!              USER_SUPPLIED_JACOBIAN=.TRUE.)
473!    CALL DVODE_F90(FEX,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JEX)
474!
475!    The problem consists of a stiff system of NEQ=3 equations. The dense
476!    Jacobian option (DENSE_J) is used. A vector ATOL(*) of error tolerances
477!    is used. A scalar relative error tolerance RTOL is used. Subroutine JEX
478!    is provided to evaluate the analytical Jacobian. If the last argument
479!    J_FCN=JEX is omitted (as in Example 2), a numerical Jacobian will
480!    be used.
481!
482! Prologue Example 2
483!
484!    OPTIONS = SET_NORMAL_OPTS(DENSE_J=.TRUE., RELERR=RTOL, ABSERR_VECTOR=ATOL,     &
485!              NEVENTS=NG)
486!    CALL DVODE_F90(FEX,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,G_FCN=GEX)
487!
488!    The system in Example 1 is used to illustrate root finding. It is
489!    desired to locate the times at which two of the solution components
490!    attain prescribed values. NEVENTS=2 informs the solver that two such
491!    functions are used. Subroutine GEX is used to calculate the residuals
492!    for these two functions. A dense numerical Jacobian is used.
493!
494! Robertson Problem
495!
496!    OPTIONS = SET_INTERMEDIATE_OPTS(DENSE_J=.TRUE., RELERR_VECTOR=RTOL,            &
497!              ABSERR_VECTOR=ABSERR_TOLERANCES, CONSTRAINED=BOUNDED_COMPONENTS,     &
498!              CLOWER=LOWER_BOUNDS, CUPPER=UPPER_BOUNDS)
499!
500!    CALL DVODE_F90(DERIVS,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JACD)
501!    The system used in Examples 1 and 2 is solved over a much larger
502!    time interval. The solution is constrained to be nonegative. This
503!    is done by prescribing the components to be constrained (BOUNDED_COMPONENTS).
504!    Artificially large values are used to impose upper bounds (UPPER_BOUNDS)
505!    and lower bounds of zero are used to force a nonnegative solution.
506!
507! Harmonic Oscillator Problem
508!
509!    OPTIONS = SET_NORMAL_OPTS(RELERR=RTOL, ABSERR=ATOL, NEVENTS=NG)
510!    CALL DVODE_F90(DERIVS,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,G_FCN=GEVENTS)
511!
512!    A nonstiff system of NEQ=4 equations is solved. The nonstiff option is
513!    used because neither DENSE_ nor BANDED_J nor SPARSE_J is present. It is
514!    desired to find the times at which Y(2) or Y(3) is equal to 0. Residuals
515!    for the two corresponding event functions are calculated in subroutine
516!    GEVENTS.
517!
518! Flow Equations Problem
519!
520!    OPTIONS = SET_OPTS(SPARSE_J=SPARSE, ABSERR=ATOL(1), RELERR=RTOL(1),            &
521!              MXSTEP=100000, NZSWAG=20000)
522!    CALL DVODE_F90(FCN,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS)
523!
524!    This is a stiff system of equations resulting a method of lines
525!    discretization. The Jacobian is sparse. Scalar absolute and relative
526!    error tolerances are used. The Jacobian structure and a numerical
527!    Jacobian are used. The solver is limited to a maximum of MXSTEP steps.
528!    NZSWAG is the amount by which allocated array sizes will be increased.
529!    The accompanying test program may be used to illutrate several other
530!    solution options.
531!
532! Diurnal Kinetics Problem
533!
534!    OPTIONS = SET_OPTS(SPARSE_J=SPARSE, BANDED_J=BANDED, DENSE_J=DENSE,            &
535!              ABSERR_VECTOR=ATOL(1:NEQ), RELERR=RTOL(1), MXSTEP=100000,            &
536!              NZSWAG=50000, HMAX=MAXH, LOWER_BANDWIDTH=ML, UPPER_BANDWIDTH=MU,     &
537!              MA28_ELBOW_ROOM=10, MC19_SCALING=.TRUE., MA28_MESSAGES=.FALSE.,      &
538!              MA28_EPS=1.0D-4, MA28_RPS=.TRUE.,                                    &
539!              USER_SUPPLIED_SPARSITY=SUPPLY_STRUCTURE)
540!   CALL USERSETS_IAJA(IA, IADIM, JA, JADIM)
541!   CALL DVODE_F90(FCN, NEQ, Y, T, TOUT, ITASK, ISTATE, OPTIONS)
542!
543!   This problem can be used to illustrate most solution options. Here, dense,
544!   banded, or sparse Jacobians are used depending on the values of the first
545!   three parameters. A vector error tolerance is used and a scalar relative
546!   error tolerance is used. If a banded solution is desired, it is necessary
547!   to supply the bandwidths ML and MU. If a sparse solution is desired,
548!   several special options are used. The most important one is MA28_RPS to
549!   force the solver to update the partial pivoting sequence when singular
550!   iteration matrices are encountered. The sparsity pattern is determined
551!   numerically if SUPPLY_STRUCTURE is FALSE. Otherwise the user will supply
552!   the pattern by calling subroutine USERSETS_IAJA.
553! ______________________________________________________________________
554! Section 2.  Calling DVODE_F90
555!
556! DVODE_F90 solves the initial value problem for stiff or nonstiff
557! systems of first order ODEs,
558!     dy/dt = f(t,y), or, in component form,
559!     dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ)) (i = 1,...,NEQ).
560! DVODE_F90 is a package based on the EPISODE and EPISODEB packages,
561! and on the ODEPACK user interface standard. It was developed from
562! the f77 solver DVODE developed by Brown, Byrne, and Hindmarsh.
563! DVODE_F90 also provides for the solution of sparse systems in a
564! fashion similar to LSODES and LSOD28. Currently, MA28 is used
565! to perform the necessary sparse linear algebra. DVODE_F90 also
566! contains the provision to do root finding in a fashion similar
567! to the LSODAR solver from ODEPACK.
568
569! Communication between the user and the DVODE_F90 package, for normal
570! situations, is summarized here. This summary describes only a subset
571! of the full set of options available. See the full description for
572! details, including optional communication, nonstandard options, and
573! instructions for special situations.
574!    CALL DVODE_F90(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JAC,G_FCN=GEX)
575!    The arguments in the call list to DVODE_F90 have the following
576!    meanings.
577! F       = The name of the user-supplied subroutine defining the
578!           ODE system. The system must be put in the first-order
579!           form dy/dt = f(t,y), where f is a vector-valued function
580!           of the scalar t and the vector y. Subroutine F is to
581!           compute the function f. It is to have the form
582!                SUBROUTINE F(NEQ,T,Y,YDOT)
583!                DOUBLE PRECISION T,Y(NEQ),YDOT(NEQ)
584!           where NEQ, T, and Y are input, and the array YDOT = f(t,y)
585!           is output. Y and YDOT are arrays of length NEQ.
586!           Subroutine F should not alter Y(1),...,Y(NEQ).
587!           If F (and JAC) are not contained in a module available to
588!           your calling program, you must declare F to be EXTERNAL
589!           in the calling program.
590! NEQ     = The size of the ODE system (number of first order
591!           ordinary differential equations).
592! Y       = A double precision array for the vector of dependent variables,
593!           of length NEQ or more. Used for both input and output on the
594!           first call (ISTATE = 1), and only for output on other calls.
595!           On the first call, Y must contain the vector of initial
596!           values. In the output, Y contains the computed solution
597!           evaluated at T.
598! T       = The independent variable. In the input, T is used only on
599!           the first call, as the initial point of the integration.
600!           In the output, after each call, T is the value at which a
601!           computed solution Y is evaluated (usually the same as TOUT).
602!           On an error return, T is the farthest point reached.
603! TOUT    = The next value of t at which a computed solution is desired.
604!           TOUT is Used only for input. When starting the problem
605!           (ISTATE = 1), TOUT may be equal to T for one call, then
606!           should not equal T for the next call. For the initial T,
607!           an input value of TOUT unequal to T is used in order to
608!           determine the direction of the integration (i.e. the
609!           algebraic sign of the step sizes) and the rough scale
610!           of the problem. Integration in either direction (forward
611!           or backward in t) is permitted. If ITASK = 2 or 5 (one-step
612!           modes), TOUT is ignored after the first call (i.e. the
613!           first call with TOUT \= T). Otherwise, TOUT is required
614!           on every call. If ITASK = 1, 3, or 4, the values of TOUT
615!           need not be monotone, but a value of TOUT which backs up
616!           is limited to the current internal t interval, whose
617!           endpoints are TCUR - HU and TCUR. (Refer to the description
618!           of GET_STATS for a description of TCUR and HU.)
619! ITASK   = An index specifying the task to be performed.
620!           Input only. ITASK has the following values and meanings.
621!           1  means normal computation of output values of y(t) at
622!              t = TOUT (by overshooting and interpolating).
623!           2  means take one step only and return.
624!           3  means stop at the first internal mesh point at or
625!              beyond t = TOUT and return.
626!           4  means normal computation of output values of y(t) at
627!              t = TOUT but without overshooting t = TCRIT.
628!              TCRIT must be specified in your SET_OPTS call. TCRIT
629!              may be equal to or beyond TOUT, but not behind it in
630!              the direction of integration. This option is useful
631!              if the problem has a singularity at or beyond t = TCRIT.
632!           5  means take one step, without passing TCRIT, and return.
633!              TCRIT must be specified in your SET_OPTS call.
634!           If ITASK = 4 or 5 and the solver reaches TCRIT (within
635!           roundoff), it will return T = TCRIT(exactly) to indicate
636!           this (unless ITASK = 4 and TOUT comes before TCRIT, in
637!           which case answers at T = TOUT are returned first).
638! ISTATE  = an index used for input and output to specify the
639!           the state of the calculation.
640!           In the input, the values of ISTATE are as follows.
641!           1  means this is the first call for the problem
642!              (initializations will be done). See note below.
643!           2  means this is not the first call, and the calculation
644!              is to continue normally, with no change in any input
645!              parameters except possibly TOUT and ITASK.
646!           3  means this is not the first call, and the
647!              calculation is to continue normally, but with
648!              a change in input parameters other than
649!              TOUT and ITASK. Desired changes require SET_OPTS
650!              be called prior to calling DVODE_F90 again.
651!           A preliminary call with TOUT = T is not counted as a
652!           first call here, as no initialization or checking of
653!           input is done. (Such a call is sometimes useful to
654!           include the initial conditions in the output.)
655!           Thus the first call for which TOUT is unequal to T
656!           requires ISTATE = 1 in the input.
657!           In the output, ISTATE has the following values and meanings.
658!            1  means nothing was done, as TOUT was equal to T with
659!               ISTATE = 1 in the input.
660!            2  means the integration was performed successfully.
661!            3  means a root of one of your root finding functions
662!               has been located.
663!           A negative value of ISTATE indicates that DVODE_F90
664!           encountered an error as described in the printed error
665!           message. Since the normal output value of ISTATE is 2,
666!           it does not need to be reset for normal continuation.
667!           Also, since a negative input value of ISTATE will be
668!           regarded as illegal, a negative output value requires
669!           the user to change it, and possibly other input, before
670!           calling the solver again.
671! OPTIONS = The options structure produced by your call to SET_OPTS.
672! JAC     = The name of the user-supplied routine (MITER = 1 or 4 or 6)
673!           If you do not specify that a stiff method is to be used
674!           in your call to SET_OPTS, you need not include JAC in
675!           your call to DVODE_F90. If you specify a stiff method and
676!           that a user supplied Jacobian will be supplied, JAC must
677!           compute the Jacobian matrix, df/dy, as a function of the
678!           scalar t and the vector y. It is to have the form:
679!              SUBROUTINE JAC(NEQ, T, Y, ML, MU, PD, NROWPD)
680!              DOUBLE PRECISION T, Y(NEQ), PD(NROWPD,NEQ)
681!           where NEQ, T, Y, ML, MU, and NROWPD are input and the array
682!           PD is to be loaded with partial derivatives (elements of the
683!           Jacobian matrix) in the output. PD must be given a first
684!           dimension of NROWPD. T and Y have the same meaning as in
685!           Subroutine F.
686!           In the full matrix case (MITER = 1), ML and MU are
687!           ignored, and the Jacobian is to be loaded into PD in
688!           columnwise manner, with df(i)/dy(j) loaded into PD(i,j).
689!           In the band matrix case (MITER = 4), the elements
690!           within the band are to be loaded into PD in columnwise
691!           manner, with diagonal lines of df/dy loaded into the rows
692!           of PD. Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j).
693!           ML and MU are the half-bandwidth parameters. (See IUSER).
694!           The locations in PD in the two triangular areas which
695!           correspond to nonexistent matrix elements can be ignored
696!           or loaded arbitrarily, as they are overwritten by DVODE_F90.
697!           In the sparse matrix case the elements of the matrix
698!           are determined by the sparsity structure given by the
699!           IA and JA pointer arrays. Refer to the documentation
700!           prologue for SET_OPTS for a description of the arguments
701!           for JAC since they differ from the dense and banded cases.
702!           JAC need not provide df/dy exactly. A crude
703!           approximation (possibly with a smaller bandwidth) will do.
704!           In either case, PD is preset to zero by the solver,
705!           so that only the nonzero elements need be loaded by JAC.
706!           In the sparse matrix case, JAC has a different form:
707!                SUBROUTINE JAC (N, T, Y, IA, JA, NZ, PD)
708!           Given the number of odes N, the current time T, and the
709!           current solution vector Y, JAC must do the following:
710!              If NZ = 0 on input:
711!              Replace NZ by the number of nonzero elements in the
712!              Jacobian. The diagonal of the Jacobian must be included.
713!              Do NOT define the arrays IA, JA, PD at this time.
714!              Once JAC has been called with NZ = 0 and you have
715!              defined the value of NZ, future calls to JAC will use
716!              this value of NZ.
717!              When a call is made with NZ unequal to 0, you must
718!              define the sparsity structure arrays IA and JA, and
719!              the sparse Jacobian PD.
720!                 IA defines the number of nonzeros including the
721!                 diagonal in each column of the Jacobian. Define
722!                 IA(1) = 1 and for J = 1,..., N,
723!                 IA(J+1) = IA(J) + number of nonzeros in column J.
724!                 Diagonal elements must be included even if they are
725!                 zero. You should check to ensure that IA(N+1)-1 = NZ.
726!                 JA defines the rows in which the nonzeros occur.
727!                 For I = 1,...,NZ, JA(I) is the row in which the Ith
728!                 element of the Jacobian occurs. JA must also include
729!                 the diagonal elements of the Jacobian.
730!                 PD defines the numerical value of the Jacobian
731!                 elements. For I = 1,...,NZ, PD(I) is the numerical
732!                 value of the Ith element in the Jacobian. PD must
733!                 also include the diagonal elements of the Jacobian.
734! GFUN    = the name of the subroutine to evaluate the residuals for
735!           event functions. If you do not specify that events are
736!           present (by specifying NEVENTS > 0 in SET_OPTS), you
737!           need not include GFUN in your call list for DVODE_F90.
738!           If GFUN is not contained in a module available to your
739!           calling program, you must declare GFUN to be EXTERNAL
740!           in your calling program.
741! To continue the integration after a successful return, simply
742! reset TOUT and call DVODE_F90 again. No other parameters need
743! be reset unless ISTATE=3 in which case, reset it to 2 before
744! calling DVODE_F90 again.
745! ______________________________________________________________________
746! Section 3.  Choosing Error Tolerances
747!
748! This is the most important aspect of solving odes numerically.
749! You may supply any of four keywords and values. If you wish to
750! use scalar error tolerances, you should supply ABSERR and RELERR.
751! For a good many problems, it is advisable to supply a vector of
752! absolute error tolerances ABSERR_VECTOR = desired vector. This
753! allows you to use different tolerances for each component of
754! the solution. If ABSERR_VECTOR is supplied, it must be a vector
755! of length NEQ where NEQ is the number of odes in your system.
756! Similarly, you may supply a vector of relative error tolerances,
757! RELERR_VECTOR. If no tolerances are specified, DVODE_F90 will use
758! default error tolerances ABSERR=1D-6 and RELERR=1D-4; but it is
759! strongly recommended that you supply values that are appropriate
760! for your problem. In the event you do not supply error tolerances,
761! DVODE_F90 will print a reminder that the default error tolerances
762! are not appropriate for all problems.
763!
764! RELERR can be set to a scalar value as follows.
765! Determine the number of significant digits of accuracy desired,
766! which will be a positive integer, say, N.
767! Then set RELERR = 10**-(N+1).
768! The authors recommend that RELERR be no larger than 10**-4.
769! The authors recommend a vector valued absolute error tolerance,
770! which can be set as follows.
771! For the I-th component of the solution vector, Y(I), determine
772! the positive number FLOOR(I) at which ABS(Y(I)) becomes
773! negligible for the problem at hand. FLOOR(I) is sometimes called
774! the problem zero or the floor value for the I-th component and is
775! problem dependent. For a given problem that is not scaled, these
776! floor values may well vary by up to 9 orders of magnitude.
777! Set ABSERR(I) = FLOOR(I) or to be conservative
778! ABSERR_VECTOR(I) = 0.1*FLOOR(I). There is no variable FLOOR in
779! DVODE_F90. If it is difficult to divine the components of ABSERR,
780! (or FLOOR) make a reasonable guess, run the problem, then set that
781! ABSERR_VECTOR so for I = 1, 2,...NEQ,
782! ABSERR_VECTOR(I) = 1D-6*RELERR*MAX{ABS(Y(I,TOUT): for all TOUT}.
783! The correct choices for RELERR and ABSERR can and do have
784! significant impact on both the quality of the solution and run
785! time. Counter intuitively, error tolerances that are too loose
786! can and do increase run time significantly and the quality of
787! the solution may be seriously compromised.
788! Examples:
789! 1. OPTIONS = SET_OPTS(DENSE_J=.TRUE., ABSERR=1D-8,RELERR=1D-8)
790!    This will yield MF = 22. Both the relative error tolerance
791!    and the absolute error tolerance will equal 1D-8.
792! 2. OPTIONS = SET_OPTS(DENSE_J=.TRUE.,RELERR=1D-5, &
793!                       ABSERR_VECTOR=(/1D-6,1D-8/))
794!    For a system with NEQ=2 odes, this will yield MF = 22. A scalar
795!    relative error tolerance equal to 1D-5 will be used. Component 1
796!    of the solution will use an absolute error tolerance of 1D-6
797!    while component 2 will use an absolute error tolerance of 1D-8.
798! ______________________________________________________________________
799! Section 4.  Choosing the Method of Integration
800!
801! If you wish to specify a numerical value for METHOD_FLAG, it can equal
802! any of the legal values of MF for DVODE or LSODES. (See below.) If
803! you do not wish to specify a numerical value for METHOD_FLAG, you
804! may specify any combination of the five logical keywords DENSE_J,
805! BANDED_J, SPARSE_J, USER_SUPPLIED_JACOBIAN, SAVE_JACOBIAN that you
806! wish. Appropriate values will be used in DVODE_F90 for any variables
807! that are not present. The first three flags indicate the type of
808! Jacobian, dense, banded, or sparse. If USER_SUPPLIED_JACOBIAN=.TRUE.,
809! the Jacobian will be determined using the subroutine JAC you supply
810! in your call to DVODE_F90. Otherwise, an internal Jacobian will be
811! generated using finite differences.
812! Examples:
813! 1. OPTIONS = SET_OPTS(METHOD_FLAG=22,...)
814!    DVODE will use the value MF=22 as described in the documentation
815!    prologue. In this case, the stiff BDF methods will be used with
816!    a dense, internally generated Jacobian.
817! 2. OPTIONS = SET_OPTS(METHOD_FLAG=21,...)
818!    This is the same an Example 1 except that a user supplied dense
819!    Jacobian will be used and DVODE will use MF=21.
820! 3. OPTIONS = SET_OPTS(DENSE_J=.TRUE.,...)
821!    This will yield MF = 22 as in Example 1, provided
822!    USER_SUPPLIED_JACOBIAN and SAVE_JACOBIAN are not present, or if
823!    present are set to their default
824!     values of .FALSE. and .TRUE., respectively.
825! 4. OPTIONS = SET_OPTS(DENSE_J=.TRUE.,&
826!                       USER_SUPPLIED_JACOBIAN=.TRUE.,...)
827!    This will yield MF = 21 as in Example 2, provided SAVE_JACOBIAN
828!    is not present, or if present is set to its default value .FALSE.
829! Notes:
830! 1. If you specify more than one of DENSE_J, BANDED_J, and SPARSE_J,
831!    DENSE_J takes precedence over BANDED_J which in turn takes
832!    precedence over SPARSE_J.
833! 2. By default, DVODE_F90 saves a copy of the Jacobian and reuses the
834!    copy when necessary. For problems in which storage requirements
835!    are acute, you may wish to override this default and have
836!    DVODE_F90 recalculate the Jacobian rather than use a saved copy.
837!    You can do this by specifying SAVE_JACOBIAN=.FALSE. It is
838!    recommended that you not do this unless necessary since it can
839!    have a significant impact on the efficiency of DVODE_F90. (For
840!    example, when solving a linear problem only one evaluation of
841!    the Jacobian is required with the default option.)
842! 3. If you choose BANDED_J = .TRUE. or if you supply a value of MF
843!    that corresponds to a banded Jacobian, you must also supply the
844!    lower  bandwidth ML and the upper bandwidth of the Jacobian MU
845!    by including the keywords
846!    LOWER_BANDWIDTH = value of ML and UPPER_BANDWIDTH = value of M
847!                   More on Method Selection
848! The keyword options available in SET_OPTS are intended to replace
849! the original method indicator flag MF. However, if you wish to
850! retain the flexibility of the original solver, you may specify MF
851! directly in your call to SET_OPTS. This is done by using the
852! keyword METHOD_FLAG=MF in your SET_OPTS where MF has any of the
853! values in the following description. Refer to the demonstration
854! program demosp.f90 for an example in which this is done.
855! MF     = The method flag. Used only for input. The legal values of
856!          MF are:
857!          10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26,
858!          27, -11, -12, -14, -15, -21, -22, -24, -25, -26, -27.
859!          MF is a signed two-digit integer, MF = JSV*(10*METH+MITER).
860!          JSV = SIGN(MF) indicates the Jacobian-saving strategy:
861!            JSV =  1 means a copy of the Jacobian is saved for reuse
862!                     in the corrector iteration algorithm.
863!            JSV = -1 means a copy of the Jacobian is not saved
864!                     (valid only for MITER = 1, 2, 4, or 5).
865!          METH indicates the basic linear multistep method:
866!            METH = 1 means the implicit Adams method.
867!            METH = 2 means the method based on backward
868!                     differentiation formulas (BDF-s).
869!          MITER indicates the corrector iteration method:
870!            MITER = 0 means functional iteration (no Jacobian matrix
871!                      is involved).
872!            MITER = 1 means chord iteration with a user-supplied
873!                      full (NEQ by NEQ) Jacobian.
874!            MITER = 2 means chord iteration with an internally
875!                      generated (difference quotient) full Jacobian
876!                      (using NEQ extra calls to F per df/dy value).
877!            MITER = 4 means chord iteration with a user-supplied
878!                      banded Jacobian.
879!            MITER = 5 means chord iteration with an internally
880!                      generated banded Jacobian (using ML+MU+1 extra
881!                      calls to F per df/dy evaluation).
882!            MITER = 6 means chord iteration with a user-supplied
883!                      sparse Jacobian.
884!            MITER = 7 means chord iteration with an internally
885!                      generated sparse Jacobian
886!          If MITER = 1, 4, or 6 the user must supply a subroutine
887!          JAC(the name is arbitrary) as described above under JAC.
888!          For other values of MITER, JAC need not be provided.
889! ______________________________________________________________________
890! Section 5.  Interpolation of the Solution and Derivative
891!
892! Following a successful return from DVODE_F90, you may call
893! subroutine DVINDY to interpolate the solution or derivative.
894! SUBROUTINE DVINDY(T, K, DKY, IFLAG)
895! DVINDY computes interpolated values of the K-th derivative of the
896! dependent variable vector y, and stores it in DKY. This routine
897! is called with K = 0 or K = 1 and T = TOUT. In either case, the
898! results are returned in the array DKY of length at least NEQ which
899! must be declared and dimensioned in your calling program. The
900! computed values in DKY are obtained by interpolation using the
901! Nordsieck history array.
902! ______________________________________________________________________
903! Section 6.  Handling Events (Root Finding)
904!
905!    DVODE_F90 contains root finding provisions. It attempts to
906!    locates the roots of a set of functions
907!         g(i) = g(i,t,y(1),...,y(NEQ))  (i = 1,...,ng).
908!    To use root finding include NEVENTS=NG in your call to SET_OPTS
909!    where NG is the number of root finding functions. You must then
910!    supply subroutine GFUN in your call to DVODE_F90 using
911!    G_FCN=GFUN as the last argument. GFUN must has the form
912!               SUBROUTINE GFUN(NEQ, T, Y, NG, GOUT)
913!    where NEQ, T, Y, and NG are input, and the array GOUT is output.
914!    NEQ, T, and Y have the same meaning as in the F routine, and
915!    GOUT is an array of length NG. For i = 1,...,NG, this routine is
916!    to load into GOUT(i) the value at (T,Y) of the i-th constraint
917!    function g(i). DVODE_F90 will find roots of the g(i) of odd
918!    multiplicity (i.e. sign changes) as they occur during the
919!    integration. GFUN must be declared EXTERNAL in the calling
920!    program. Note that because of numerical errors in the functions
921!    g(i) due to roundoff and integration error, DVODE_F90 may return
922!    false roots, or return the same root at two or more nearly equal
923!    values of t. This is particularly true for problems in which the
924!    integration is restarted (ISTATE = 1) at a root. If such false
925!    roots are suspected, you should consider smaller error tolerances
926!    and/or higher precision in the evaluation of the g(i). Note
927!    further that if a root of some g(i) defines the end of the
928!    problem, the input to DVODE_F90 should nevertheless allow
929!    integration to a point slightly past that root, so that DVODE_F90
930!    can locate the root by interpolation. Each time DVODE_F90 locates
931!    a root of one of your event functions it makes a return to the
932!    calling program with ISTATE = 3. When such a return is made and
933!    you have processed the results, simply change ISTATE = 2 and call
934!    DVODE_F90 again without making other changes.
935! ______________________________________________________________________
936! Section 7.  Gathering Integration Statistics
937!
938! SUBROUTINE GET_STATS(RSTATS, ISTATS, NUMEVENTS, JROOTS)
939! Caution:
940! RSTATS and ISTATS must be declared and dimensioned in your
941! main program. The minimum dimensions are:
942! DIMENSION RSTATS(22), ISTATS(31)
943! This subroutine returns the user portions of the original DVODE
944! RUSER and IUSER arrays, and if root finding is being done, it
945! returns the original LSODAR JROOT vector. NUMEVENTS and JROOTS
946! are optional parameters. NUMEVENTS is the number of root functions
947! and JROOTS is an integer array of length NUMEVENTS.
948! Available Integration Statistics:
949! HU      RUSER(11) The step size in t last used (successfully).
950! HCUR    RUSER(12) The step size to be attempted on the next step.
951! TCUR    RUSER(13) The current value of the independent variable
952!                   which the solver has actually reached, i.e. the
953!                   current internal mesh point in t. In the output,
954!                   TCUR will always be at least as far from the
955!                   initial value of t as the current argument T,
956!                   but may be farther (if interpolation was done).
957! TOLSF   RUSER(14) A tolerance scale factor, greater than 1.0,
958!                   computed when a request for too much accuracy was
959!                   detected (ISTATE = -3 if detected at the start of
960!                   the problem, ISTATE = -2 otherwise). If ITOL is
961!                   left unaltered but RTOL and ATOL are uniformly
962!                   scaled up by a factor of TOLSF for the next call,
963!                   then the solver is deemed likely to succeed.
964!                   (The user may also ignore TOLSF and alter the
965!                   tolerance parameters in any other way appropriate.)
966! NST     IUSER(11) The number of steps taken for the problem so far.
967! NFE     IUSER(12) The number of f evaluations for the problem so far.
968! NJE     IUSER(13) The number of Jacobian evaluations so far.
969! NQU     IUSER(14) The method order last used (successfully).
970! NQCUR   IUSER(15) The order to be attempted on the next step.
971! IMXER   IUSER(16) The index of the component of largest magnitude in
972!                   the weighted local error vector (E(i)/EWT(i)),
973!                   on an error return with ISTATE = -4 or -5.
974! LENRW   IUSER(17) The length of RUSER actually required.
975!                   This is defined on normal returns and on an illegal
976!                   input return for insufficient storage.
977! LENIW   IUSER(18) The length of IUSER actually required.
978!                   This is defined on normal returns and on an illegal
979!                   input return for insufficient storage.
980! NLU     IUSER(19) The number of matrix LU decompositions so far.
981! NNI     IUSER(20) The number of nonlinear (Newton) iterations so far.
982! NCFN    IUSER(21) The number of convergence failures of the nonlinear
983!                   solver so far.
984! NETF    IUSER(22) The number of error test failures of the integrator
985!                   so far.
986! MA28AD_CALLS      IUSER(23) The number of calls made to MA28AD
987! MA28BD_CALLS      IUSER(24) The number of calls made to MA28BD
988! MA28CD_CALLS      IUSER(25) The number of calls made to MA28CD
989! MC19AD_CALLS      IUSER(26) The number of calls made to MC19AD
990! IRNCP             IUSER(27) The number of compressions done on array JAN
991! ICNCP             IUSER(28) The number of compressions done on array ICN
992! MINIRN            IUSER(29) Minimum size for JAN array
993! MINICN            IUSER(30) Minimum size for ICN array
994! MINNZ             IUSER(31) Number of nonzeros in sparse Jacobian
995! JROOTS  JROOTS    Optional array of component indices for components
996!                   having a zero at the current time
997! ______________________________________________________________________
998! Section 8.  Determining Jacobian Sparsity Structure Arrays
999!
1000! If you are solving a problem with a sparse Jacobian, the arrays
1001! that define the sparsity structure are needed. The arrays may
1002! be determined in any of several ways.
1003! 1. If you choose the default mode by indicating SPARSE=.TRUE.,
1004!    the sparsity arrays will be determined internally by DVODE_F90
1005!    by making calls to your derivative subroutine. This mode is
1006!    equivalent to using the integration method flag MF = 227.
1007! 2. The DVODE_F90 method flag MF is defined to be
1008!    MF = 100*MOSS + 10*METH + MITER. If you supply MF = 227 (or 217),
1009!    the sparse Jacobian will be determined using finite differences;
1010!    and the sparsity arrays will be determined by calling your
1011!    derivative subroutine.
1012! 3. If you supply MF = 126 (or 116), you must supply the Jacobian
1013!    subroutine JAC to define the exact Jacobian. JAC must have the
1014!    following form:
1015!           SUBROUTINE JAC (N, T, Y, IA, JA, NZ, PD)
1016!    Given the number of odes N, the current time T, and the current
1017!    solution vector Y, JAC must do the following:
1018!    -  If NZ = 0 on input:
1019!       Replace NZ by the number of nonzero elements in the Jacobian.
1020!       The diagonal of the Jacobian must be included.
1021!       Do NOT define the arrays IA, JA, PD at this time.
1022!       Once JAC has been called with NZ = 0 and you have defined the
1023!       value of NZ, future calls to JAC will use this value of NZ.
1024!    -  When a call is made with NZ unequal to 0, you must define the
1025!       sparsity structure arrays IA and JA, and the sparse Jacobian
1026!       PD.
1027!         - IA defines the number of nonzeros including the diagonal
1028!           in each column of the Jacobian. Define IA(1) = 1 and for
1029!           J = 1,..., N,
1030!           IA(J+1) = IA(J) + number of nonzeros in column J.
1031!           Diagonal elements must be include even if they are zero.
1032!           You should check to ensure that IA(N+1)-1 = NZ.
1033!         - JA defines the rows in which the nonzeros occur. For
1034!           I = 1,...,NZ, JA(I) is the row in which the Ith element
1035!           of the Jacobian occurs. JA must also include the diagonal
1036!           elements of the Jacobian.
1037!         - PD defines the numerical value of the Jacobian elements.
1038!           For I = 1,...,NZ, PD(I) is the numerical value of the
1039!           Ith element in the Jacobian. PD must also include the
1040!           diagonal elements of the Jacobian.
1041! 4. If you wish to supply the IA and JA arrays directly, use
1042!    MF = 27. In this case, after calling SET_OPTS, you must call
1043!    SET_IAJA supplying the arrays IAUSER and JAUSER described in
1044!    the documentation prologue for SET_IAJA. These arrays will be
1045!    used when approximate Jacobians are determined using finite
1046!    differences.
1047! There are two user callable sparsity structure subroutines:
1048! USERSETS_IAJA may be used if you wish to supply the sparsity
1049! structure directly.
1050! SUBROUTINE USERSETS_IAJA(IAUSER,NIAUSER,JAUSER,NJAUSER)
1051!     Caution:
1052!     If it is called, USERSETS_IAJA must be called after the
1053!     call to SET_OPTS.
1054!     Usage:
1055!     CALL SET_IAJA(IAUSER,NIAUSER,JAUSER,NJAUSER)
1056!       In this case, IAUSER of length NIAUSER will be used for
1057!       IA; and JAUSER of length NJAUSER will be used for JA.
1058!     Arguments:
1059!     IAUSER  = user supplied IA array
1060!     NIAUSER = length of IAUSER array
1061!     JAUSER  = user supplied JA vector
1062!     NJAUSER = length of JAUSER array
1063! The second subroutine allows you to approximate the sparsity
1064! structure using derivative differences. It allows more flexibility
1065! in the determination of perturbation increments used.
1066! SUBROUTINE SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB,IAUSER, &
1067!   NIAUSER, JAUSER, NJAUSER)
1068!     Caution:
1069!     If it is called, SET_IAJA must be called after the call to
1070!     SET_OPTS.
1071!     Usage:
1072!     SET_IAJA may be called in one of two ways:
1073
1074!     CALL SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB)
1075!       In this case IA and JA will be determined using calls
1076!       to your derivative routine DFN.
1077!     CALL SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB,IAUSER,NIAUSER, &
1078!       JAUSER, NJAUSER)
1079!       In this case, IAUSER of length NIAUSER will be used for
1080!       IA; and JAUSER of length NJAUSER will be used for JA.
1081!       T, Y, FMIN, NTURB, and DTURB will be ignored (though
1082!       they must be present in the argument list).
1083!     Arguments:
1084!     DFN     = DVODE derivative subroutine
1085!     NEQ     = Number of odes
1086!     T       = independent variable t
1087!     Y       = solution y(t)
1088!     FMIN    = Jacobian threshold value. Elements of the Jacobian
1089!               with magnitude smaller than FMIN will be ignored.
1090!               FMIN will be ignored if it is less than or equal
1091!               to ZERO.
1092!     NTURB   = Perturbation flag. If NTURB=1, component I of Y
1093!               will be perturbed by 1.01D0.
1094!               If NTURB=NEQ, component I of Y will be perturbed
1095!               by ONE + DTURB(I).
1096!     DTURB   = perturbation vector of length 1 or NEQ.
1097!     If these four optional parameters are present, IAUSER and JAUSER
1098!     will be copied to IA and JA rather than making derivative calls
1099!     to approximate IA and JA:
1100!        IAUSER  = user supplied IA array
1101!        NIAUSER = length of IAUSER array
1102!        JAUSER  = user supplied JA vector
1103!        NJAUSER = length of JAUSER array
1104! ______________________________________________________________________
1105! Section 9.  Original DVODE.F Documentation Prologue
1106!
1107! SUBROUTINE DVODE(F, NEQ, Y, T, TOUT, ITASK, ISTATE, OPTS, JAC, GFUN)
1108! DVODE: Variable-coefficient Ordinary Differential Equation solver,
1109! with fixed-leading-coefficient implementation.
1110! Note:
1111! Numerous changes have been made in the documentation and the code
1112! from the original Fortran 77 DVODE solver. With regard to the new
1113! F90 version, if you choose options that correspond to options
1114! available in the original f77 solver, you should obtain the same
1115! results. In all testing, identical results have been obtained
1116! between this version and a simple F90 translation of the original
1117! solver.
1118! DVODE solves the initial value problem for stiff or nonstiff
1119! systems of first order ODEs,
1120!     dy/dt = f(t,y), or, in component form,
1121!     dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ)) (i = 1,...,NEQ).
1122! DVODE is a package based on the EPISODE and EPISODEB packages, and
1123! on the ODEPACK user interface standard, with minor modifications.
1124! This version is based also on elements of LSODES and LSODAR.
1125! Authors:
1126!               Peter N. Brown and Alan C. Hindmarsh
1127!               Center for Applied Scientific Computing, L-561
1128!               Lawrence Livermore National Laboratory
1129!               Livermore, CA 94551
1130!               George D. Byrne
1131!               Illinois Institute of Technology
1132!               Chicago, IL 60616
1133! References:
1134! 1. P. N. Brown, G. D. Byrne, and A. C. Hindmarsh, "VODE: A Variable
1135!    Coefficient ODE Solver," SIAM J. Sci. Stat. Comput., 10 (1989),
1136!    pp. 1038-1051. Also, LLNL Report UCRL-98412, June 1988.
1137! 2. G. D. Byrne and A. C. Hindmarsh, "A Polyalgorithm for the
1138!    Numerical Solution of Ordinary Differential Equations,"
1139!    ACM Trans. Math. Software, 1 (1975), pp. 71-96.
1140! 3. A. C. Hindmarsh and G. D. Byrne, "EPISODE: An Effective Package
1141!    for the Integration of Systems of Ordinary Differential
1142!    Equations," LLNL Report UCID/30112, Rev. 1, April 1977.
1143! 4. G. D. Byrne and A. C. Hindmarsh, "EPISODEB: An Experimental
1144!    Package for the Integration of Systems of Ordinary Differential
1145!    Equations with Banded Jacobians," LLNL Report UCID/30132, April
1146!    1976.
1147! 5. A. C. Hindmarsh, "ODEPACK, a Systematized Collection of ODE
1148!    Solvers," in Scientific Computing, R. S. Stepleman et al., eds.,
1149!    North-Holland, Amsterdam, 1983, pp. 55-64.
1150! 6. K. R. Jackson and R. Sacks-Davis, "An Alternative Implementation
1151!    of Variable Step-Size Multistep Formulas for Stiff ODEs," ACM
1152!    Trans. Math. Software, 6 (1980), pp. 295-318.
1153!                     Summary of Usage
1154! Communication between the user and the DVODE package, for normal
1155! situations, is summarized here. This summary describes only a subset
1156! of the full set of options available. See the full description for
1157! details, including optional communication, nonstandard options,
1158! and instructions for special situations. See also the example
1159! problem (with program and output) following this summary.
1160! A. First provide a subroutine of the form:
1161!           SUBROUTINE F(NEQ, T, Y, YDOT)
1162!           REAL(KIND=WP) T, Y(NEQ), YDOT(NEQ)
1163! which supplies the vector function f by loading YDOT(i) with f(i).
1164! B. Next determine (or guess) whether or not the problem is stiff.
1165! Stiffness occurs when the Jacobian matrix df/dy has an eigenvalue
1166! whose real part is negative and large in magnitude, compared to the
1167! reciprocal of the t span of interest. If the problem is nonstiff,
1168! use a method flag MF = 10. If it is stiff, there are four standard
1169! choices for MF(21, 22, 24, 25), and DVODE requires the Jacobian
1170! matrix in some form. In these cases (MF > 0), DVODE will use a
1171! saved copy of the Jacobian matrix. If this is undesirable because of
1172! storage limitations, set MF to the corresponding negative value
1173! (-21, -22, -24, -25). (See full description of MF below.)
1174! The Jacobian matrix is regarded either as full (MF = 21 or 22),
1175! or banded (MF = 24 or 25). In the banded case, DVODE requires two
1176! half-bandwidth parameters ML and MU. These are, respectively, the
1177! widths of the lower and upper parts of the band, excluding the main
1178! diagonal. Thus the band consists of the locations (i,j) with
1179! i-ML <= j <= i+MU, and the full bandwidth is ML+MU+1.
1180! C. If the problem is stiff, you are encouraged to supply the Jacobian
1181! directly (MF = 21 or 24), but if this is not feasible, DVODE will
1182! compute it internally by difference quotients (MF = 22 or 25).
1183! If you are supplying the Jacobian, provide a subroutine of the form:
1184!           SUBROUTINE JAC(NEQ, T, Y, ML, MU, PD, NROWPD)
1185!           REAL(KIND=WP) T, Y(NEQ), PD(NROWPD,NEQ)
1186! which supplies df/dy by loading PD as follows:
1187!     For a full Jacobian (MF = 21), load PD(i,j) with df(i)/dy(j),
1188! the partial derivative of f(i) with respect to y(j). (Ignore the
1189! ML and MU arguments in this case.)
1190!     For a banded Jacobian (MF = 24), load PD(i-j+MU+1,j) with
1191! df(i)/dy(j), i.e. load the diagonal lines of df/dy into the rows of
1192! PD from the top down.
1193!     In either case, only nonzero elements need be loaded.
1194! D. Write a main program which calls subroutine DVODE once for
1195! each point at which answers are desired. This should also provide
1196! for possible use of logical unit 6 for output of error messages
1197! by DVODE. On the first call to DVODE, supply arguments as follows:
1198! F      = Name of subroutine for right-hand side vector f.
1199!          This name must be declared external in calling program.
1200! NEQ    = Number of first order ODEs.
1201! Y      = Array of initial values, of length NEQ.
1202! T      = The initial value of the independent variable.
1203! TOUT   = First point where output is desired (/= T).
1204! ITOL   = 1 or 2 according as ATOL(below) is a scalar or array.
1205! RTOL   = Relative tolerance parameter (scalar).
1206! ATOL   = Absolute tolerance parameter (scalar or array).
1207!          The estimated local error in Y(i) will be controlled so as
1208!          to be roughly less (in magnitude) than
1209!             EWT(i) = RTOL*ABS(Y(i)) + ATOL     if ITOL = 1, or
1210!             EWT(i) = RTOL*ABS(Y(i)) + ATOL(i)  if ITOL = 2.
1211!          Thus the local error test passes if, in each component,
1212!          either the absolute error is less than ATOL(or ATOL(i)),
1213!          or the relative error is less than RTOL.
1214!          Use RTOL = 0.0 for pure absolute error control, and
1215!          use ATOL = 0.0 (or ATOL(i) = 0.0) for pure relative error
1216!          control. Caution: Actual (global) errors may exceed these
1217!          local tolerances, so choose them conservatively.
1218! ITASK  = 1 for normal computation of output values of Y at t = TOUT.
1219! ISTATE = Integer flag (input and output). Set ISTATE = 1.
1220! IOPT   = 0 to indicate no optional input used.
1221! JAC    = Name of subroutine for Jacobian matrix (MF = 21 or 24).
1222!          If used, this name must be declared external in calling
1223!          program. If not used, pass a dummy name.
1224! MF     = Method flag. Standard values are:
1225!          10 for nonstiff (Adams) method, no Jacobian used.
1226!          21 for stiff (BDF) method, user-supplied full Jacobian.
1227!          22 for stiff method, internally generated full Jacobian.
1228!          24 for stiff method, user-supplied banded Jacobian.
1229!          25 for stiff method, internally generated banded Jacobian.
1230! E. The output from the first call (or any call) is:
1231!      Y = Array of computed values of y(t) vector.
1232!      T = Corresponding value of independent variable (normally TOUT).
1233! ISTATE = 2  if DVODE was successful, negative otherwise.
1234!          -1 means excess work done on this call. (Perhaps wrong MF.)
1235!          -2 means excess accuracy requested. (Tolerances too small.)
1236!          -3 means illegal input detected. (See printed message.)
1237!          -4 means repeated error test failures. (Check all input.)
1238!          -5 means repeated convergence failures. (Perhaps bad
1239!             Jacobian supplied or wrong choice of MF or tolerances.)
1240!          -6 means error weight became zero during problem. (Solution
1241!             component I vanished, and ATOL or ATOL(I) = 0.)
1242! F. To continue the integration after a successful return, simply
1243! reset TOUT and call DVODE again. No other parameters need be reset.
1244!         Full Description of User Interface to DVODE
1245! The user interface to DVODE consists of the following parts.
1246! i.  The call sequence to subroutine DVODE, which is a driver
1247!      routine for the solver. This includes descriptions of both
1248!      the call sequence arguments and of user-supplied routines.
1249!      Following these descriptions is
1250!        * a description of optional input available through the
1251!          call sequence,
1252!        * a description of optional output (in the work arrays), and
1253!        * instructions for interrupting and restarting a solution.
1254! ii. Descriptions of other routines in the DVODE package that may be
1255!      (optionally) called by the user. These provide the ability to
1256!      alter error message handling, save and restore the internal
1257!      PRIVATE variables, and obtain specified derivatives of the
1258!      solution y(t).
1259! iii. Descriptions of PRIVATE variables to be declared in overlay
1260!      or similar environments.
1261! iv. Description of two routines in the DVODE package, either of
1262!      which the user may replace with his own version, if desired.
1263!      these relate to the measurement of errors.
1264! Part i. Call Sequence.
1265! The call sequence parameters used for input only are
1266!     F, NEQ, TOUT, ITOL, RTOL, ATOL, ITASK, IOPT, JAC, MF,
1267! and those used for both input and output are
1268!     Y, T, ISTATE.
1269! The work arrays RUSER and IUSER are used for conditional and
1270! optional input and optional output. (The term output here refers
1271! to the return from subroutine DVODE to the user's calling program.)
1272! The legality of input parameters will be thoroughly checked on the
1273! initial call for the problem, but not checked thereafter unless a
1274! change in input parameters is flagged by ISTATE = 3 in the input.
1275! The descriptions of the call arguments are as follows.
1276! F      = The name of the user-supplied subroutine defining the
1277!          ODE system. The system must be put in the first-order
1278!          form dy/dt = f(t,y), where f is a vector-valued function
1279!          of the scalar t and the vector y. Subroutine F is to
1280!          compute the function f. It is to have the form
1281!               SUBROUTINE F(NEQ, T, Y, YDOT)
1282!               REAL(KIND=WP) T, Y(NEQ), YDOT(NEQ)
1283!          where NEQ, T, and Y are input, and the array YDOT = f(t,y)
1284!          is output. Y and YDOT are arrays of length NEQ.
1285!          Subroutine F should not alter Y(1),...,Y(NEQ).
1286!          F must be declared EXTERNAL in the calling program.
1287
1288!          If quantities computed in the F routine are needed
1289!          externally to DVODE, an extra call to F should be made
1290!          for this purpose, for consistent and accurate results.
1291!          If only the derivative dy/dt is needed, use DVINDY instead.
1292! NEQ    = The size of the ODE system (number of first order
1293!          ordinary differential equations). Used only for input.
1294!          NEQ may not be increased during the problem, but
1295!          can be decreased (with ISTATE = 3 in the input).
1296! Y      = A real array for the vector of dependent variables, of
1297!          length NEQ or more. Used for both input and output on the
1298!          first call (ISTATE = 1), and only for output on other calls.
1299!          On the first call, Y must contain the vector of initial
1300!          values. In the output, Y contains the computed solution
1301!          evaluated at T. If desired, the Y array may be used
1302!          for other purposes between calls to the solver.
1303!          This array is passed as the Y argument in all calls to
1304!          F and JAC.
1305! T      = The independent variable. In the input, T is used only on
1306!          the first call, as the initial point of the integration.
1307!          In the output, after each call, T is the value at which a
1308!          computed solution Y is evaluated (usually the same as TOUT).
1309!          On an error return, T is the farthest point reached.
1310! TOUT   = The next value of t at which a computed solution is desired.
1311!          Used only for input.
1312!          When starting the problem (ISTATE = 1), TOUT may be equal
1313!          to T for one call, then should /= T for the next call.
1314!          For the initial T, an input value of TOUT /= T is used
1315!          in order to determine the direction of the integration
1316!          (i.e. the algebraic sign of the step sizes) and the rough
1317!          scale of the problem. Integration in either direction
1318!          (forward or backward in t) is permitted.
1319!          If ITASK = 2 or 5 (one-step modes), TOUT is ignored after
1320!          the first call (i.e. the first call with TOUT /= T).
1321!          Otherwise, TOUT is required on every call.
1322!          If ITASK = 1, 3, or 4, the values of TOUT need not be
1323!          monotone, but a value of TOUT which backs up is limited
1324!          to the current internal t interval, whose endpoints are
1325!          TCUR - HU and TCUR. (See optional output, below, for
1326!          TCUR and HU.)
1327! ITOL   = An indicator for the type of error control. See
1328!          description below under ATOL. Used only for input.
1329! RTOL   = A relative error tolerance parameter, either a scalar or
1330!          an array of length NEQ. See description below under ATOL.
1331!          Input only.
1332! ATOL   = An absolute error tolerance parameter, either a scalar or
1333!          an array of length NEQ. Input only.
1334!          The input parameters ITOL, RTOL, and ATOL determine
1335!          the error control performed by the solver. The solver will
1336!          control the vector e = (e(i)) of estimated local errors
1337!          in Y, according to an inequality of the form
1338!                      rms-norm of (E(i)/EWT(i)) <= 1,
1339!          where       EWT(i) = RTOL(i)*ABS(Y(i)) + ATOL(i),
1340!          and the rms-norm (root-mean-square norm) here is
1341!          rms-norm(v) = sqrt(sum v(i)**2 / NEQ). Here EWT
1342!          is a vector of weights which must always be positive, and
1343!          the values of RTOL and ATOL should all be nonnegative.
1344!          The following table gives the types (scalar/array) of
1345!          RTOL and ATOL, and the corresponding form of EWT(i).
1346!           ITOL    RTOL       ATOL          EWT(i)
1347!            1     scalar     scalar     RTOL*ABS(Y(i)) + ATOL
1348!            2     scalar     array      RTOL*ABS(Y(i)) + ATOL(i)
1349!            3     array      scalar     RTOL(i)*ABS(Y(i)) + ATOL
1350!            4     array      array      RTOL(i)*ABS(Y(i)) + ATOL(i)
1351!          When either of these parameters is a scalar, it need not
1352!          be dimensioned in the user's calling program.
1353!          If none of the above choices (with ITOL, RTOL, and ATOL
1354!          fixed throughout the problem) is suitable, more general
1355!          error controls can be obtained by substituting
1356!          user-supplied routines for the setting of EWT and/or for
1357!          the norm calculation. See Part iv below.
1358!          If global errors are to be estimated by making a repeated
1359!          run on the same problem with smaller tolerances, then all
1360!          components of RTOL and ATOL(i.e. of EWT) should be scaled
1361!          down uniformly.
1362! ITASK  = An index specifying the task to be performed.
1363!          Input only. ITASK has the following values and meanings.
1364!          1  means normal computation of output values of y(t) at
1365!             t = TOUT(by overshooting and interpolating).
1366!          2  means take one step only and return.
1367!          3  means stop at the first internal mesh point at or
1368!             beyond t = TOUT and return.
1369!          4  means normal computation of output values of y(t) at
1370!             t = TOUT but without overshooting t = TCRIT.
1371!             TCRIT must be input as RUSER(1). TCRIT may be equal to
1372!             or beyond TOUT, but not behind it in the direction of
1373!             integration. This option is useful if the problem
1374!             has a singularity at or beyond t = TCRIT.
1375!          5  means take one step, without passing TCRIT, and return.
1376!             TCRIT must be input as RUSER(1).
1377!          Note:  If ITASK = 4 or 5 and the solver reaches TCRIT
1378!          (within roundoff), it will return T = TCRIT(exactly) to
1379!          indicate this (unless ITASK = 4 and TOUT comes before TCRIT,
1380!          in which case answers at T = TOUT are returned first).
1381! ISTATE = an index used for input and output to specify the
1382!          the state of the calculation.
1383!          In the input, the values of ISTATE are as follows.
1384!          1  means this is the first call for the problem
1385!             (initializations will be done). See note below.
1386!          2  means this is not the first call, and the calculation
1387!             is to continue normally, with no change in any input
1388!             parameters except possibly TOUT and ITASK.
1389!             (If ITOL, RTOL, and/or ATOL are changed between calls
1390!             with ISTATE = 2, the new values will be used but not
1391!             tested for legality.)
1392!          3  means this is not the first call, and the
1393
1394!             calculation is to continue normally, but with
1395!             a change in input parameters other than
1396!             TOUT and ITASK. Changes are allowed in
1397!             NEQ, ITOL, RTOL, ATOL, IOPT, MF, ML, MU,
1398!             and any of the optional input except H0.
1399!             (See IUSER description for ML and MU.)
1400!          Caution:
1401!          If you make a call to DVODE_F90 with ISTATE=3, you will
1402!          first need to call SET_OPTS again, supplying the new
1403!          necessary option values.
1404!          Note:  A preliminary call with TOUT = T is not counted
1405!          as a first call here, as no initialization or checking of
1406!          input is done. (Such a call is sometimes useful to include
1407!          the initial conditions in the output.)
1408!          Thus the first call for which TOUT /= T requires
1409!          ISTATE = 1 in the input.
1410!          In the output, ISTATE has the following values and meanings.
1411!           1  means nothing was done, as TOUT was equal to T with
1412!              ISTATE = 1 in the input.
1413!           2  means the integration was performed successfully.
1414!          -1  means an excessive amount of work (more than MXSTEP
1415!              steps) was done on this call, before completing the
1416!              requested task, but the integration was otherwise
1417!              successful as far as T. (MXSTEP is an optional input
1418!              and is normally 5000.)  To continue, the user may
1419!              simply reset ISTATE to a value > 1 and call again.
1420!              (The excess work step counter will be reset to 0.)
1421!              In addition, the user may increase MXSTEP to avoid
1422!              this error return. (See optional input below.)
1423!          -2  means too much accuracy was requested for the precision
1424!              of the machine being used. This was detected before
1425!              completing the requested task, but the integration
1426!              was successful as far as T. To continue, the tolerance
1427!              parameters must be reset, and ISTATE must be set
1428!              to 3. The optional output TOLSF may be used for this
1429!              purpose. (Note: If this condition is detected before
1430!              taking any steps, then an illegal input return
1431!              (ISTATE = -3) occurs instead.)
1432!          -3  means illegal input was detected, before taking any
1433!              integration steps. See written message for details.
1434!              Note:  If the solver detects an infinite loop of calls
1435!              to the solver with illegal input, it will cause
1436!              the run to stop.
1437!          -4  means there were repeated error test failures on
1438!              one attempted step, before completing the requested
1439!              task, but the integration was successful as far as T.
1440!              The problem may have a singularity, or the input
1441!              may be inappropriate.
1442!          -5  means there were repeated convergence test failures on
1443!              one attempted step, before completing the requested
1444!              task, but the integration was successful as far as T.
1445!              This may be caused by an inaccurate Jacobian matrix,
1446!              if one is being used.
1447!          -6  means EWT(i) became zero for some i during the
1448!              integration. Pure relative error control (ATOL(i)=0.0)
1449!              was requested on a variable which has now vanished.
1450!              The integration was successful as far as T.
1451!          Note:  Since the normal output value of ISTATE is 2,
1452!          it does not need to be reset for normal continuation.
1453!          Also, since a negative input value of ISTATE will be
1454!          regarded as illegal, a negative output value requires the
1455!          user to change it, and possibly other input, before
1456!          calling the solver again.
1457! IOPT   = An integer flag to specify whether or not any optional
1458!          input is being used on this call. Input only.
1459!          The optional input is listed separately below.
1460!          IOPT = 0 means no optional input is being used.
1461!                   Default values will be used in all cases.
1462!          IOPT = 1 means optional input is being used.
1463! RUSER  = A real working array (real(wp)).
1464!          The length of RUSER must be at least 22
1465!             20 + NYH * (MAXORD + 1) where
1466!          NYH    = the initial value of NEQ,
1467!          MAXORD = 12 (if METH = 1) or 5 (if METH = 2) (unless a
1468!                   smaller value is given as an optional input),
1469!          The first 22 words of RUSER are reserved for conditional
1470!          and optional input and optional output.
1471
1472!          The following word in RUSER is a conditional input:
1473!            RUSER(1) = TCRIT = critical value of t which the solver
1474!                       is not to overshoot. Required if ITASK is
1475!                       4 or 5, and ignored otherwise. (See ITASK.)
1476! IUSER  = An integer work array. The length of IUSER must be at least 30.
1477!             30        if MITER = 0 or 3 (MF = 10, 13, 20, 23), or
1478!             30 + NEQ  otherwise (ABS(MF) = 11,12,14,15,16,17,21,22,
1479!             24,25,26,27).
1480!          The first 30 words of IUSER are reserved for conditional and
1481!          optional input and optional output.
1482
1483!          The following 2 words in IUSER are conditional input:
1484!            IUSER(1) = ML  These are the lower and upper
1485!            IUSER(2) = MU  half-bandwidths, respectively, of the
1486!                       banded Jacobian, excluding the main diagonal.
1487!                       The band is defined by the matrix locations
1488!                       (i,j) with i-ML <= j <= i+MU. ML and MU
1489!                       must satisfy  0 <= ML,MU  <= NEQ-1.
1490!                       These are required if MITER is 4 or 5, and
1491!                       ignored otherwise. ML and MU may in fact be
1492!                       the band parameters for a matrix to which
1493!                       df/dy is only approximately equal.
1494! Note:  The work arrays must not be altered between calls to DVODE
1495! for the same problem, except possibly for the conditional and
1496! optional input, and except for the last 3*NEQ words of RUSER.
1497! The latter space is used for internal scratch space, and so is
1498! available for use by the user outside DVODE between calls, if
1499! desired (but not for use by F or JAC).
1500! JAC    = The name of the user-supplied routine (MITER = 1 or 4 or 6)
1501!          to compute the Jacobian matrix, df/dy, as a function of
1502!          the scalar t and the vector y. It is to have the form
1503!               SUBROUTINE JAC(NEQ, T, Y, ML, MU, PD, NROWPD)
1504!               REAL(KIND=WP) T, Y(NEQ), PD(NROWPD,NEQ)
1505!          where NEQ, T, Y, ML, MU, and NROWPD are input and the array
1506!          PD is to be loaded with partial derivatives (elements of the
1507!          Jacobian matrix) in the output. PD must be given a first
1508!          dimension of NROWPD. T and Y have the same meaning as in
1509!          Subroutine F.
1510!               In the full matrix case (MITER = 1), ML and MU are
1511!          ignored, and the Jacobian is to be loaded into PD in
1512!          columnwise manner, with df(i)/dy(j) loaded into PD(i,j).
1513!               In the band matrix case (MITER = 4), the elements
1514!          within the band are to be loaded into PD in columnwise
1515!          manner, with diagonal lines of df/dy loaded into the rows
1516!          of PD. Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j).
1517!          ML and MU are the half-bandwidth parameters. (See IUSER).
1518!          The locations in PD in the two triangular areas which
1519!          correspond to nonexistent matrix elements can be ignored
1520!          or loaded arbitrarily, as they are overwritten by DVODE.
1521!               In the sparse matrix case the elements of the matrix
1522!          are determined by the sparsity structure given by the
1523!          IA and JA pointer arrays. Refer to the documentation
1524!          prologue for SET_OPTS for a description of the arguments
1525!          for JAC since they differ from the dense and banded cases.
1526!               JAC need not provide df/dy exactly. A crude
1527!          approximation (possibly with a smaller bandwidth) will do.
1528!               In either case, PD is preset to zero by the solver,
1529!          so that only the nonzero elements need be loaded by JAC.
1530!          Each call to JAC is preceded by a call to F with the same
1531!          arguments NEQ, T, and Y. Thus to gain some efficiency,
1532!          intermediate quantities shared by both calculations may be
1533!          saved in a user common block by F and not recomputed by JAC,
1534!          if desired. Also, JAC may alter the Y array, if desired.
1535!          JAC must be declared external in the calling program.
1536! MF     = The method flag. Used only for input. The legal values of
1537!          MF are 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24,
1538!          25, 26, 27, -11, -12, -14, -15, -21, -22, -24, -25, -26,
1539!          -27.
1540!          MF is a signed two-digit integer, MF = JSV*(10*METH+MITER).
1541!          JSV = SIGN(MF) indicates the Jacobian-saving strategy:
1542!            JSV =  1 means a copy of the Jacobian is saved for reuse
1543!                     in the corrector iteration algorithm.
1544!            JSV = -1 means a copy of the Jacobian is not saved
1545!                     (valid only for MITER = 1, 2, 4, or 5).
1546!          METH indicates the basic linear multistep method:
1547!            METH = 1 means the implicit Adams method.
1548!            METH = 2 means the method based on backward
1549!                     differentiation formulas (BDF-s).
1550!          MITER indicates the corrector iteration method:
1551!            MITER = 0 means functional iteration (no Jacobian matrix
1552!                      is involved).
1553!            MITER = 1 means chord iteration with a user-supplied
1554!                      full (NEQ by NEQ) Jacobian.
1555!            MITER = 2 means chord iteration with an internally
1556!                      generated (difference quotient) full Jacobian
1557!                      (using NEQ extra calls to F per df/dy value).
1558!            MITER = 3 means chord iteration with an internally
1559!                      generated diagonal Jacobian approximation
1560!                      (using 1 extra call to F per df/dy evaluation).
1561!            MITER = 4 means chord iteration with a user-supplied
1562!                      banded Jacobian.
1563!            MITER = 5 means chord iteration with an internally
1564!                      generated banded Jacobian (using ML+MU+1 extra
1565!                      calls to F per df/dy evaluation).
1566!            MITER = 6 means chord iteration with a user-supplied
1567!                      sparse Jacobian.
1568!            MITER = 7 means chord iteration with an internally
1569!                      generated sparse Jacobian
1570!          If MITER = 1, 4, or 6 the user must supply a subroutine
1571!          JAC(the name is arbitrary) as described above under JAC.
1572!          For other values of MITER, a dummy argument can be used.
1573!                         Optional Input
1574! The following is a list of the optional input provided for in the
1575! call sequence. (See also Part ii.)  For each such input variable,
1576! this table lists its name as used in this documentation, its
1577! location in the call sequence, its meaning, and the default value.
1578! The use of any of this input requires IOPT = 1, and in that
1579! case all of this input is examined. A value of zero for any of
1580! these optional input variables will cause the default value to be
1581! used. Thus to use a subset of the optional input, simply preload
1582! locations 5 to 10 in RUSER and IUSER to 0.0 and 0, respectively,
1583! and then set those of interest to nonzero values.
1584! NAME    LOCATION      MEANING AND DEFAULT VALUE
1585! H0      RUSER(5)  The step size to be attempted on the first step.
1586!                   The default value is determined by the solver.
1587! HMAX    RUSER(6)  The maximum absolute step size allowed.
1588!                   The default value is infinite.
1589! HMIN    RUSER(7)  The minimum absolute step size allowed.
1590!                   The default value is 0. (This lower bound is not
1591!                   enforced on the final step before reaching TCRIT
1592!                   when ITASK = 4 or 5.)
1593! MAXORD  IUSER(5)  The maximum order to be allowed. The default
1594!                   value is 12 if METH = 1, and 5 if METH = 2.
1595!                   If MAXORD exceeds the default value, it will
1596!                   be reduced to the default value.
1597!                   If MAXORD is changed during the problem, it may
1598!                   cause the current order to be reduced.
1599! MXSTEP  IUSER(6)  Maximum number of (internally defined) steps
1600!                   allowed during one call to the solver.
1601!                   The default value is 5000.
1602! MXHNIL  IUSER(7)  Maximum number of messages printed (per problem)
1603!                   warning that T + H = T on a step (H = step size).
1604!                   This must be positive to result in a non-default
1605!                   value. The default value is 10.
1606!                          Optional Output
1607! As optional additional output from DVODE, the variables listed
1608! below are quantities related to the performance of DVODE
1609! which are available to the user. These are communicated by way of
1610! the work arrays, but also have internal mnemonic names as shown.
1611! Except where stated otherwise, all of this output is defined
1612! on any successful return from DVODE, and on any return with
1613! ISTATE = -1, -2, -4, -5, or -6. On an illegal input return
1614! (ISTATE = -3), they will be unchanged from their existing values
1615! (if any), except possibly for TOLSF, LENRW, and LENIW.
1616! On any error return, output relevant to the error will be defined,
1617! as noted below.
1618! NAME    LOCATION      MEANING
1619! HU      RUSER(11) The step size in t last used (successfully).
1620! HCUR    RUSER(12) The step size to be attempted on the next step.
1621! TCUR    RUSER(13) The current value of the independent variable
1622!                   which the solver has actually reached, i.e. the
1623!                   current internal mesh point in t. In the output,
1624!                   TCUR will always be at least as far from the
1625!                   initial value of t as the current argument T,
1626!                   but may be farther (if interpolation was done).
1627! TOLSF   RUSER(14) A tolerance scale factor, greater than 1.0,
1628!                   computed when a request for too much accuracy was
1629!                   detected (ISTATE = -3 if detected at the start of
1630!                   the problem, ISTATE = -2 otherwise). If ITOL is
1631!                   left unaltered but RTOL and ATOL are uniformly
1632!                   scaled up by a factor of TOLSF for the next call,
1633!                   then the solver is deemed likely to succeed.
1634!                   (The user may also ignore TOLSF and alter the
1635!                   tolerance parameters in any other way appropriate.)
1636! NST     IUSER(11) The number of steps taken for the problem so far.
1637! NFE     IUSER(12) The number of f evaluations for the problem so far.
1638! NJE     IUSER(13) The number of Jacobian evaluations so far.
1639! NQU     IUSER(14) The method order last used (successfully).
1640! NQCUR   IUSER(15) The order to be attempted on the next step.
1641! IMXER   IUSER(16) The index of the component of largest magnitude in
1642!                   the weighted local error vector (e(i)/EWT(i)),
1643!                   on an error return with ISTATE = -4 or -5.
1644! LENRW   IUSER(17) The length of RUSER actually required.
1645!                   This is defined on normal returns and on an illegal
1646!                   input return for insufficient storage.
1647! LENIW   IUSER(18) The length of IUSER actually required.
1648!                   This is defined on normal returns and on an illegal
1649!                   input return for insufficient storage.
1650! NLU     IUSER(19) The number of matrix LU decompositions so far.
1651! NNI     IUSER(20) The number of nonlinear (Newton) iterations so far.
1652! NCFN    IUSER(21) The number of convergence failures of the nonlinear
1653!                   solver so far.
1654! NETF    IUSER(22) The number of error test failures of the integrator
1655!                   so far.
1656! The following two arrays are segments of the RUSER array which
1657! may also be of interest to the user as optional output.
1658! For each array, the table below gives its internal name,
1659! its base address in RUSER, and its description.
1660!                  Interrupting and Restarting
1661! If the integration of a given problem by DVODE is to be interrupted
1662! and then later continued, such as when restarting an interrupted run
1663! or alternating between two or more ODE problems, the user should save,
1664! following the return from the last DVODE call prior to the
1665! interruption, the contents of the call sequence variables and
1666! internal PRIVATE variables, and later restore these values before the
1667! next DVODE call for that problem. To save and restore the PRIVATE
1668! variables, use subroutine DVSRCO, as described below in part ii.
1669! In addition, if non-default values for either LUN or MFLAG are
1670! desired, an extra call to XSETUN and/or XSETF should be made just
1671! before continuing the integration. See Part ii below for details.
1672! Part ii. Other Routines Callable.
1673! The following are optional calls which the user may make to
1674! gain additional capabilities in conjunction with DVODE.
1675! (The routines XSETUN and XSETF are designed to conform to the
1676! SLATEC error handling package.)
1677!     FORM OF CALL                  FUNCTION
1678!  CALL XSETUN(LUN)           Set the logical unit number, LUN, for
1679!                             output of messages from DVODE, if
1680!                             the default is not desired.
1681!                             The default value of LUN is 6.
1682!  CALL XSETF(MFLAG)          Set a flag to control the printing of
1683!                             messages by DVODE.
1684!                             MFLAG = 0 means do not print. (Danger:
1685!                             This risks losing valuable information.)
1686!                             Either of the above calls may be made at
1687!                             any time and will take effect immediately.
1688!  CALL DVINDY(...)           Provide derivatives of y, of various
1689!                             orders, at a specified point T, if
1690!                             desired. It may be called only after
1691!                             a successful return from DVODE.
1692! The detailed instructions for using DVINDY are as follows.
1693! The form of the call is:
1694!      CALL DVINDY(T,K,DKY,IFLAG)
1695! The input parameters are:
1696! T         = Value of independent variable where answers are desired
1697!             (normally the same as the T last returned by DVODE).
1698!             For valid results, T must lie between TCUR - HU and TCUR.
1699!             (See optional output for TCUR and HU.)
1700! K         = Integer order of the derivative desired. K must satisfy
1701!             0 <= K <= NQCUR, where NQCUR is the current order
1702!             (see optional output). The capability corresponding
1703!             to K = 0, i.e. computing y(T), is already provided
1704!             by DVODE directly. Since NQCUR >= 1, the first
1705!             derivative dy/dt is always available with DVINDY.
1706! The output parameters are:
1707! DKY       = A real array of length NEQ containing the computed value
1708!             of the K-th derivative of y(t).
1709! IFLAG     = Integer flag, returned as 0 if K and T were legal,
1710!             -1 if K was illegal, and -2 if T was illegal.
1711!             On an error return, a message is also written.
1712! Part iii. Optionally Replaceable Solver Routines.
1713! Below are descriptions of two routines in the DVODE package which
1714! relate to the measurement of errors. Either routine can be
1715! replaced by a user-supplied version, if desired. However, since such
1716! a replacement may have a major impact on performance, it should be
1717! done only when absolutely necessary, and only with great caution.
1718! (Note: The means by which the package version of a routine is
1719! superseded by the user's version may be system-dependent.)
1720! (a) DEWSET.
1721! The following subroutine is called just before each internal
1722! integration step, and sets the array of error weights, EWT, as
1723! described under ITOL/RTOL/ATOL above:
1724!     SUBROUTINE DEWSET(NEQ, ITOL, RTOL, ATOL, YCUR, EWT)
1725! where NEQ, ITOL, RTOL, and ATOL are as in the DVODE call sequence,
1726! YCUR contains the current dependent variable vector, and
1727! EWT is the array of weights set by DEWSET.
1728! If the user supplies this subroutine, it must return in EWT(i)
1729! (i = 1,...,NEQ) a positive quantity suitable for comparison with
1730! errors in Y(i). The EWT array returned by DEWSET is passed to the
1731! DVNORM function (See below.), and also used by DVODE in the
1732! computation of the optional output IMXER, the diagonal Jacobian
1733! approximation, and the increments for difference quotient Jacobians.
1734! In the user-supplied version of DEWSET, it may be desirable to use
1735! the current values of derivatives of y. Derivatives up to order NQ
1736! are available from the history array YH, described above under
1737! Optional Output. In DEWSET, YH is identical to the YCUR array,
1738! extended to NQ + 1 columns with a column length of NYH and scale
1739! factors of h**j/factorial(j). On the first call for the problem,
1740! given by NST = 0, NQ is 1 and H is temporarily set to 1.0.
1741! NYH is the initial value of NEQ. Thus, for example, the current
1742! value of dy/dt can be obtained as YCUR(NYH+i)/H  (i=1,...,NEQ)
1743! (and the division by H is unnecessary when NST = 0).
1744! (b) DVNORM.
1745! The following is a function which computes the weighted
1746! root-mean-square norm of a vector v:
1747!     D = DVNORM(N, V, W)
1748! where:
1749!   N = the length of the vector,
1750!   V = real array of length N containing the vector,
1751!   W = real array of length N containing weights,
1752!   D = sqrt((1/N) * sum(V(i)*W(i))**2).
1753! DVNORM is called with N = NEQ and with W(i) = 1.0/EWT(i), where
1754! EWT is as set by subroutine DEWSET.
1755! If the user supplies this routine, it should return a nonnegative
1756! value of DVNORM suitable for use in the error control in DVODE.
1757! None of the arguments should be altered by DVNORM.
1758! For example, a user-supplied DVNORM function might:
1759!   -substitute a max-norm of (V(i)*W(i)) for the rms-norm, or
1760!   -ignore some components of V in the norm, with the effect of
1761!    suppressing the error control on those components of Y.
1762!_______________________________________________________________________
1763! Other Routines in the DVODE Package
1764
1765! In addition to subroutine DVODE, the DVODE package includes the
1766! following subroutines and function routines (not user callable):
1767!  DVHIN       computes an approximate step size for the initial step.
1768!  DVINDY_CORE computes an interpolated value of the y vector at t=TOUT.
1769!  DVINDY      computes an interpolated value of the y vector at t=TOUT.
1770!              (user callable)
1771!  DVSTEP      is the core integrator, which does one step of the
1772!              integration and the associated error control.
1773!  DVSET       sets all method coefficients and test constants.
1774!  DVNLSD,     solves the underlying nonlinear system -- the corrector.
1775!  DVNLSS28
1776!  DVJAC,      computes and preprocesses the Jacobian matrix J = df/dy
1777!  DVJACS28    and the Newton iteration matrix P = I - (h/l1)*J.
1778!  DVSOL,      manages solution of linear system in chord iteration.
1779!  DVSOLS28
1780!  DVJUST      adjusts the history array on a change of order.
1781!  DEWSET      sets the error weight vector EWT before each step.
1782!  DVNORM      computes the weighted r.m.s. norm of a vector.
1783!  DACOPY      is a routine to copy a two-dimensional array to another.
1784!  DGEFA_F90 and DGESL_F90 are routines from LINPACK for solving full
1785!              systems of linear algebraic equations.
1786!  DGBFA_F90 and DGBSL_F90 are routines from LINPACK for solving banded
1787!              linear systems.
1788!  DAXPY_F90, DSCAL_F90, and DCOPY_F90 are basic linear algebra modules
1789!              (BLAS).
1790!  DVCHECK     does preliminary checking for roots, and serves as an
1791!              interface between subroutine DVODE_F90 and subroutine
1792!              DVROOTS.
1793!  DVROOTS     finds the leftmost root of a set of functions.
1794! ______________________________________________________________________
1795! Section 10.  Example Usage
1796!
1797! MODULE example1
1798! The following is a simple example problem, with the coding
1799! needed for its solution by DVODE_F90. The problem is from
1800! chemical kinetics, and consists of the following three rate
1801! equations:
1802!     dy1/dt = -.04d0*y1 + 1.d4*y2*y3
1803!     dy2/dt = .04d0*y1 - 1.d4*y2*y3 - 3.d7*y2**2
1804!     dy3/dt = 3.d7*y2**2
1805! on the interval from t = 0.0d0 to t = 4.d10, with initial
1806! conditions y1 = 1.0d0, y2 = y3 = 0.0d0. The problem is stiff.
1807! The following coding solves this problem with DVODE_F90,
1808! using a user supplied Jacobian and printing results at
1809! t = .4, 4.,...,4.d10. It uses ITOL = 2 and ATOL much smaller
1810! for y2 than y1 or y3 because y2 has much smaller values. At
1811! the end of the run, statistical quantities of interest are
1812! printed. (See optional output in the full DVODE description
1813! below.) Output is written to the file example1.dat.
1814! CONTAINS
1815!     SUBROUTINE FEX(NEQ, T, Y, YDOT)
1816!     IMPLICIT NONE
1817!     INTEGER NEQ
1818!     DOUBLE PRECISION T, Y, YDOT
1819!     DIMENSION Y(NEQ), YDOT(NEQ)
1820!     YDOT(1) = -.04D0*Y(1) + 1.D4*Y(2)*Y(3)
1821!     YDOT(3) = 3.E7*Y(2)*Y(2)
1822!     YDOT(2) = -YDOT(1) - YDOT(3)
1823!     RETURN
1824!     END SUBROUTINE FEX
1825!     SUBROUTINE JEX(NEQ, T, Y, ML, MU, PD, NRPD)
1826!     IMPLICIT NONE
1827!     INTEGER NEQ,ML,MU,NRPD
1828!     DOUBLE PRECISION PD, T, Y
1829!     DIMENSION Y(NEQ), PD(NRPD,NEQ)
1830!     PD(1,1) = -.04D0
1831!     PD(1,2) = 1.D4*Y(3)
1832!     PD(1,3) = 1.D4*Y(2)
1833!     PD(2,1) = .04D0
1834!     PD(2,3) = -PD(1,3)
1835!     PD(3,2) = 6.E7*Y(2)
1836!     PD(2,2) = -PD(1,2) - PD(3,2)
1837!     RETURN
1838!     END SUBROUTINE JEX
1839! END MODULE example1
1840!******************************************************************
1841
1842!     PROGRAM runexample1
1843!     USE DVODE_F90_M
1844!     USE example1
1845!     IMPLICIT NONE
1846!     DOUBLE PRECISION ATOL, RTOL, T, TOUT, Y, RSTATS
1847!     INTEGER NEQ, ITASK, ISTATE, ISTATS, IOUT, IERROR, I
1848!     DIMENSION Y(3), ATOL(3), RSTATS(22), ISTATS(31)
1849!     TYPE(VODE_OPTS) :: OPTIONS
1850!     OPEN(UNIT=6, FILE = 'example1.dat')
1851!     IERROR = 0
1852!     NEQ = 3
1853!     Y(1) = 1.0D0
1854!     Y(2) = 0.0D0
1855!     Y(3) = 0.0D0
1856!     T = 0.0D0
1857!     TOUT = 0.4D0
1858!     RTOL = 1.D-4
1859!     ATOL(1) = 1.D-8
1860!     ATOL(2) = 1.D-14
1861!     ATOL(3) = 1.D-6
1862!     ITASK = 1
1863!     ISTATE = 1
1864!     OPTIONS = SET_OPTS(DENSE_J=.TRUE.,ABSERR_VECTOR=ATOL, &
1865!       RELERR=RTOL, USER_SUPPLIED_JACOBIAN=.TRUE.)
1866!     DO IOUT = 1,12
1867!       CALL DVODE_F90(FEX,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,J_FCN=JEX)
1868!       CALL GET_STATS(RSTATS,ISTATS)
1869!       WRITE(6,63)T,Y(1),Y(2),Y(3)
1870!       DO I = 1, NEQ
1871!          IF (Y(I) < 0.0D0) IERROR = 1
1872!       END DO
1873!       IF (ISTATE < 0) THEN
1874!          WRITE(6,64)ISTATE
1875!          STOP
1876!       END IF
1877!       TOUT = TOUT*10.0D0
1878!     END DO
1879!     WRITE(6,60) ISTATS(11),ISTATS(12),ISTATS(13),ISTATS(19), &
1880!                 ISTATS(20),ISTATS(21),ISTATS(22)
1881!     IF (IERROR == 1) THEN
1882!        WRITE(6,61)
1883!     ELSE
1884!        WRITE(6,62)
1885!     END IF
1886! 60  FORMAT(/'  No. steps =',I4,'   No. f-s =',I4,        &
1887!             '  No. J-s =',I4,'   No. LU-s =',I4/         &
1888!             '  No. nonlinear iterations =',I4/           &
1889!             '  No. nonlinear convergence failures =',I4/ &
1890!             '  No. error test failures =',I4/)
1891! 61  FORMAT(/' An error occurred.')
1892! 62  FORMAT(/' No errors occurred.')
1893! 63  FORMAT(' At t =',D12.4,'   y =',3D14.6)
1894! 64  FORMAT(///' Error halt: ISTATE =',I3)
1895!     STOP
1896!     END PROGRAM runexample1
1897!
1898! MODULE example2
1899! The following is a modification of the previous example
1900! program to illustrate root finding. The problem is from
1901! chemical kinetics, and consists of the following three
1902! rate equations:
1903!     dy1/dt = -.04d0*y1 + 1.d4*y2*y3
1904!     dy2/dt = .04d0*y1 - 1.d4*y2*y3 - 3.d7*y2**2
1905!     dy3/dt = 3.d7*y2**2
1906! on the interval from t = 0.0d0 to t = 4.d10, with initial
1907! conditions y1 = 1.0d0, y2 = y3 = 0.0d0. The problem is stiff.
1908! In addition, we want to find the values of t, y1, y2,
1909! and y3 at which:
1910!   (1) y1 reaches the value 1.d-4, and
1911!   (2) y3 reaches the value 1.d-2.
1912! The following coding solves this problem with DVODE_F90
1913! using an internally generated dense Jacobian and
1914! printing results at t = .4, 4., ..., 4.d10, and at the
1915! computed roots. It uses ITOL = 2 and ATOL much smaller
1916! for y2 than y1 or y3 because y2 has much smaller values.
1917! At the end of the run, statistical quantities of interest
1918! are printed (see optional outputs in the full description
1919! below). Output is written to the file example2.dat.
1920! CONTAINS
1921!     SUBROUTINE FEX (NEQ, T, Y, YDOT)
1922!     IMPLICIT NONE
1923!     INTEGER NEQ
1924!     DOUBLE PRECISION T, Y, YDOT
1925!     DIMENSION Y(3), YDOT(3)
1926!     YDOT(1) = -0.04D0*Y(1) + 1.0D4*Y(2)*Y(3)
1927!     YDOT(3) = 3.0D7*Y(2)*Y(2)
1928!     YDOT(2) = -YDOT(1) - YDOT(3)
1929!     RETURN
1930!     END SUBROUTINE FEX
1931!     SUBROUTINE GEX (NEQ, T, Y, NG, GOUT)
1932!     IMPLICIT NONE
1933!     INTEGER NEQ, NG
1934!     DOUBLE PRECISION T, Y, GOUT
1935!     DIMENSION Y(3), GOUT(2)
1936!     GOUT(1) = Y(1) - 1.0D-4
1937!     GOUT(2) = Y(3) - 1.0D-2
1938!     RETURN
1939!     END SUBROUTINE GEX
1940! END MODULE example2
1941!******************************************************************
1942!     PROGRAM runexample2
1943!     USE DVODE_F90_M
1944!     USE example2
1945!     IMPLICIT NONE
1946!     INTEGER ITASK, ISTATE, NG, NEQ, IOUT, JROOT, ISTATS, &
1947!     IERROR, I
1948!     DOUBLE PRECISION ATOL, RTOL, RSTATS, T, TOUT, Y
1949!     DIMENSION Y(3), ATOL(3), RSTATS(22), ISTATS(31), JROOT(2)
1950!     TYPE(VODE_OPTS) :: OPTIONS
1951!     OPEN (UNIT=6, FILE='example2.dat')
1952!     IERROR = 0
1953!     NEQ = 3
1954!     Y(1) = 1.0D0
1955!     Y(2) = 0.0D0
1956!     Y(3) = 0.0D0
1957!     T = 0.0D0
1958!     TOUT = 0.4D0
1959!     RTOL = 1.0D-4
1960!     ATOL(1) = 1.0D-8
1961!     ATOL(2) = 1.0D-12
1962!     ATOL(3) = 1.0D-8
1963!     ITASK = 1
1964!     ISTATE = 1
1965!     NG = 2
1966!     OPTIONS = SET_OPTS(DENSE_J=.TRUE.,RELERR=RTOL, &
1967!       ABSERR_VECTOR=ATOL,NEVENTS=NG)
1968!     DO 40 IOUT = 1,12
1969! 10    CONTINUE
1970!       CALL DVODE_F90(FEX,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS,G_FCN=GEX)
1971!       CALL GET_STATS(RSTATS, ISTATS, NG, JROOT)
1972!       WRITE(6,20) T, Y(1), Y(2), Y(3)
1973!       DO I = 1, NEQ
1974!          IF (Y(I) < 0.0D0) IERROR = 1
1975!       END DO
1976! 20    FORMAT(' At t =',D12.4,'   Y =',3D14.6)
1977!       IF (ISTATE < 0) GOTO 60
1978!       IF (ISTATE == 2) GOTO 40
1979!       WRITE(6,30) JROOT(1),JROOT(2)
1980! 30    FORMAT(5X,' The above line is a root, JROOT =',2I5)
1981!       ISTATE = 2
1982!       GOTO 10
1983! 40  TOUT = TOUT*10.0D0
1984!     WRITE(6,50) ISTATS(11), ISTATS(12), ISTATS(13), ISTATS(10)
1985!     IF (IERROR == 1) THEN
1986!        WRITE(6,61)
1987!     ELSE
1988!        WRITE(6,62)
1989!     END IF
1990! 50  FORMAT(/' No. steps =',I4,'  No. f-s =',I4,'  No. J-s =',I4, &
1991!     '  No. g-s =',I4/)
1992!     STOP
1993! 60  WRITE(6,70) ISTATE
1994! 61  FORMAT(/' An error occurred.')
1995! 62  FORMAT(/' No errors occurred.')
1996! 70  FORMAT(///' Error halt.. ISTATE =',I3)
1997!     STOP
1998!     END PROGRAM runexample2
1999!_______________________________________________________________________
2000! BEGINNING OF DVODE_F90_M PRIVATE SECTION.
2001! Note: This global information is used throughout DVODE_F90.
2002!_______________________________________________________________________
2003! JACSPDB arrays and parameters.
2004  LOGICAL, PRIVATE :: USE_JACSP, LIKE_ORIGINAL_VODE
2005  INTEGER, PRIVATE :: INFODS, LIWADS, MAXGRPDS, MINGRPDS, NRFJACDS,    &
2006    NCFJACDS, LWKDS, LIWKDS
2007  INTEGER, ALLOCATABLE, PRIVATE :: INDROWDS(:), INDCOLDS(:),           &
2008    NGRPDS(:), IPNTRDS(:), JPNTRDS(:), IWADS(:), IWKDS(:), IOPTDS(:)
2009  KPP_REAL, ALLOCATABLE, PRIVATE :: YSCALEDS(:), WKDS(:), FACDS(:)
2010  KPP_REAL, PRIVATE :: U125, U325
2011!_______________________________________________________________________
2012  LOGICAL, PARAMETER, PRIVATE :: USE_MA48_FOR_SPARSE=.FALSE.
2013!_______________________________________________________________________
2014! *****MA48 build change point. Replace the above statement.
2015! LOGICAL, PARAMETER, PRIVATE :: USE_MA48_FOR_SPARSE=.TRUE.
2016!_______________________________________________________________________
2017! *****MA48 build change point. Insert these statements.
2018! MA48 type declarations:
2019! TYPE(ZD01_TYPE) MATRIX
2020! TYPE(MA48_CONTROL) CONTROL
2021! TYPE(MA48_FACTORS) FACTORS
2022! TYPE(MA48_AINFO) AINFO
2023! TYPE(MA48_FINFO) FINFO
2024! TYPE(MA48_SINFO) SINFO
2025!_______________________________________________________________________
2026! .. Parameters ..
2027!     IPCUTH_MAX - maximum number of times the solver will halve the
2028!                  stepsize to prevent an infeasible prediction if
2029!                  solution bounds are used
2030!     KFC        - maximum number of consecutive convergence failures
2031!                  before crashing the order
2032!     KFH        - maximum number of consecutive error test failures
2033!                  before giving up (changed from 7 to 15)
2034!     MAXCOR     - maximum number of corrections
2035!     MSBP       - maximum number of steps before forming new P matrix
2036!     MXNCF      - maximum number of consecutive convergence failures
2037!                  before giving up
2038!     MXHNLO     - maximum number of T+H=T messages
2039!     MXSTP0     - maximum number of integration steps
2040!     L*****     - lengths and pointers for some internal arrays
2041!     INTEGER, PARAMETER, PRIVATE :: KFC = -3, KFH = -7, LENIV1 = 33,    &
2042      INTEGER, PARAMETER, PRIVATE :: IPCUTH_MAX = 100, KFC = -3,         &
2043        KFH = -15, LENIV1 = 33,                                          &
2044        LENIV2 = 8, LENRV1 = 48, LENRV2 = 1, LIWUSER = 30, LRWUSER = 22, &
2045        MAXCOR = 3, MAX_ARRAY_SIZE = 900000000, MSBP = 20, MXHNL0 = 10,  &
2046        MXNCF = 10, MXSTP0 = 5000
2047!_______________________________________________________________________
2048! *****LAPACK build change point. Use .TRUE. for LAPACK.
2049!     LOGICAL, PARAMETER, PRIVATE :: USE_LAPACK = .TRUE.
2050!_______________________________________________________________________
2051      KPP_REAL, PARAMETER, PRIVATE :: ADDON = 1.0E-6_dp
2052      KPP_REAL, PARAMETER, PRIVATE :: BIAS1 = 6.0_dp
2053      KPP_REAL, PARAMETER, PRIVATE :: BIAS2 = 6.0_dp
2054      KPP_REAL, PARAMETER, PRIVATE :: BIAS3 = 10.0_dp
2055      KPP_REAL, PARAMETER, PRIVATE :: CCMAX = 0.3_dp
2056      KPP_REAL, PARAMETER, PRIVATE :: CORTES = 0.1_dp
2057      KPP_REAL, PARAMETER, PRIVATE :: CRDOWN = 0.3_dp
2058      KPP_REAL, PARAMETER, PRIVATE :: ETACF = 0.25_dp
2059      KPP_REAL, PARAMETER, PRIVATE :: ETAMIN = 0.1_dp
2060      KPP_REAL, PARAMETER, PRIVATE :: ETAMX1 = 1.0E4_dp
2061      KPP_REAL, PARAMETER, PRIVATE :: ETAMX2 = 10.0_dp
2062      KPP_REAL, PARAMETER, PRIVATE :: ETAMX3 = 10.0_dp
2063      KPP_REAL, PARAMETER, PRIVATE :: ETAMXF = 0.2_dp
2064      KPP_REAL, PARAMETER, PRIVATE :: FIVE = 5.0_dp
2065      KPP_REAL, PARAMETER, PRIVATE :: FOUR = 4.0_dp
2066      KPP_REAL, PARAMETER, PRIVATE :: HALF = 0.5_dp
2067      KPP_REAL, PARAMETER, PRIVATE :: HUN = 100.0_dp
2068      KPP_REAL, PARAMETER, PRIVATE :: HUNDRETH = 0.01_dp
2069      KPP_REAL, PARAMETER, PRIVATE :: ONE = 1.0_dp
2070      KPP_REAL, PARAMETER, PRIVATE :: ONEPSM = 1.00001_dp
2071      KPP_REAL, PARAMETER, PRIVATE :: PT1 = 0.1_dp
2072      KPP_REAL, PARAMETER, PRIVATE :: PT2 = 0.2_dp
2073      KPP_REAL, PARAMETER, PRIVATE :: RDIV = 2.0_dp
2074      KPP_REAL, PARAMETER, PRIVATE :: SIX = 6.0_dp
2075      KPP_REAL, PARAMETER, PRIVATE :: TEN = 10.0_dp
2076      KPP_REAL, PARAMETER, PRIVATE :: TENTH = 0.1_dp
2077      KPP_REAL, PARAMETER, PRIVATE :: THOU = 1000.0_dp
2078      KPP_REAL, PARAMETER, PRIVATE :: THRESH = 1.5_dp
2079      KPP_REAL, PARAMETER, PRIVATE :: TWO = 2.0_dp
2080      KPP_REAL, PARAMETER, PRIVATE :: ZERO = 0.0_dp
2081
2082! Beginning of DVODE_F90 interface.
2083! ..
2084! .. Generic Interface Blocks ..
2085      INTERFACE DVODE_F90
2086
2087!         VODE_F90 is the interface subroutine that is actually invoked
2088!         when the user calls DVODE_F90. It in turn calls subroutine
2089!         DVODE which is the driver that directs all the work.
2090          MODULE PROCEDURE VODE_F90
2091
2092!         GET_STATS can be called to gather integration statistics.
2093          MODULE PROCEDURE GET_STATS
2094
2095!         DVINDY can be called to interpolate the solution and derivative.
2096          MODULE PROCEDURE DVINDY
2097
2098!         RELEASE_ARRAYS can be called to release/deallocate the work arrays.
2099          MODULE PROCEDURE RELEASE_ARRAYS
2100
2101!         SET_IAJA can be called to set sparse matrix descriptor arrays.
2102          MODULE PROCEDURE SET_IAJA
2103
2104!         USERSETS_IAJA can be called to set sparse matrix descriptor arrays.
2105          MODULE PROCEDURE USERSETS_IAJA
2106
2107!         CHECK_STAT can be called to stop if a storage allocation or
2108!         deallocation error occurs.
2109          MODULE PROCEDURE CHECK_STAT
2110
2111!         JACSP can be called to calculate a Jacobian using Doug Salane's
2112!         algoritm
2113          MODULE PROCEDURE JACSP
2114
2115!         DVDSM can be called to calculate sparse pointer arrays needed
2116!         by JACSP
2117          MODULE PROCEDURE DVDSM
2118
2119      END INTERFACE
2120! ..
2121! .. Derived Type Declarations ..
2122      TYPE, PUBLIC :: VODE_OPTS
2123        KPP_REAL, DIMENSION (:), POINTER :: ATOL, RTOL
2124        INTEGER :: MF, METH, MITER, MOSS, ITOL, IOPT, NG
2125        LOGICAL :: DENSE, BANDED, SPARSE
2126      END TYPE VODE_OPTS
2127! ..
2128! .. Local Scalars ..
2129!_______________________________________________________________________
2130! *****MA48 build change point. Insert these statements.
2131!     For communication with subroutine ma48_control_array:
2132!     KPP_REAL, PUBLIC :: COPY_OF_U_PIVOT
2133!_______________________________________________________________________
2134      KPP_REAL, PRIVATE :: ACNRM, ALPHA, BIG, BIG1, CCMXJ, CGCE, CONP, CRATE,  &
2135        DRC, DRES, DXMAX, EPS, ERRMAX, ETA, ETAMAX, FRACINT, FRACSUB, H, HMIN,  &
2136        HMXI, HNEW, HSCAL, HU, MEPS, MRESID, MRMIN, PRL1, RC, RESID, RL1,       &
2137        RMIN, SETH, T0ST, THEMAX, TLAST, TN, TOL, TOL1, TOUTC, UMAX, UROUND,    &
2138        U_PIVOT, X2, WM1, WM2
2139      INTEGER, PRIVATE :: ADDTOJA, ADDTONNZ, CONSECUTIVE_CFAILS,                &
2140        CONSECUTIVE_EFAILS, ELBOW_ROOM, IADIM, IANPIV, IAVPIV,                  &
2141        ICF, ICNCP, IFAIL, IMAX, IMIN, INEWJ, INIT, IPUP, IRANK, IRFND, IRNCP,  &
2142        ISTART, ISTATC, ITASKC, JADIM, JCUR, JMIN, JSTART, JSV, KFLAG, KOUNTL,  &
2143        KUTH, L, LARGE, LAST, LENIGP, LICN_ALL, LIRN_ALL, LIW, LIWM, LMAX,      &
2144        LOCJS, LP, LRW, LWM, LWMDIM, LWMTEMP, LYH, LYHTEMP, MANPIV, MAPIV, MAXG,&
2145        MAXIT, MAXORD, MB28, MB48, METH, MICN, MICNCP, MINICN, MINIRN, MIRANK,  &
2146        MIRN, MIRNCP, MITER, MLP, MOSS, MP, MSBG, MSBJ, MXHNIL, MXSTEP, N, NZB, &
2147        NCFN, NDROP, NDROP1, NDX, NETF, NEWH, NEWQ, NFE, NGC, NGE, NGP, NHNIL,  &
2148        NJE, NLP, NLU, NNI, NNZ, NOITER, NQ, NQNYH, NQU, NQWAIT, NSLG, NSLJ,    &
2149        NSLP, NSRCH, NSRCH1, NST, NSUBS, NSUPS, NUM, NUMNZ, NYH, NZ_ALL,        &
2150        NZ_SWAG, PREVIOUS_MAXORD, WPD, WPS, MA28AD_CALLS, MA28BD_CALLS,         &
2151        MA28CD_CALLS, MC19AD_CALLS, MAX_MINIRN, MAX_MINICN, MAX_NNZ, BNGRP
2152!       MA48AD_CALLS, MA48BD_CALLS, MA48CD_CALLS
2153! *****MA48 build change point. Insert the above line.
2154      LOGICAL, PRIVATE :: ABORT, ABORT1, ABORT2, ABORT3, ABORTA, ABORTB,        &
2155        ALLOW_DEFAULT_TOLS, BUILD_IAJA, BOUNDS, CHANGED_ACOR, GROW, IAJA_CALLED,&
2156        J_HAS_BEEN_COMPUTED, J_IS_CONSTANT, LBIG, LBIG1, LBLOCK, MA48_WAS_USED, &
2157        OK_TO_CALL_MA28, SUBS, SUPS, OPTS_CALLED, REDO_PIVOT_SEQUENCE,          &
2158        SCALE_MATRIX, SPARSE, USE_FAST_FACTOR, YMAXWARN 
2159! ..
2160! .. Local Arrays ..
2161      KPP_REAL, ALLOCATABLE, PRIVATE :: ACOR(:), CSCALEX(:), EWT(:),           &
2162        FPTEMP(:), FTEMP(:), FTEMP1(:), G0(:), G1(:), GX(:), JMAT(:),           &
2163        LB(:), PMAT(:), RSCALEX(:), RWORK(:), SAVF(:), UB(:), WM(:),            &
2164        WMTEMP(:), WSCALEX(:,:), YHNQP2(:), YHTEMP(:), YMAX(:), YNNEG(:),       &
2165        YTEMP(:), DTEMP(:)
2166      KPP_REAL, PRIVATE :: EL(13), RUSER(22), TAU(13), TQ(5)
2167      INTEGER, ALLOCATABLE, PRIVATE :: BIGP(:), BJGP(:), IA(:), IAB(:), IAN(:), &
2168        ICN(:), IDX(:), IGP(:), IKEEP28(:,:), IW28(:,:), IWORK(:), JA(:),       &
2169        JAB(:), JAN(:), JATEMP(:), JGP(:), JROOT(:), JVECT(:), SUBDS(:), SUPDS(:)
2170      INTEGER, PRIVATE :: IDISP(2), IUSER(30), LNPIV(10), LPIV(10)
2171      INTEGER, PRIVATE :: MORD(2) = (/ 12, 5 /)
2172! ..
2173! .. Public Subroutines and Functions ..
2174  PUBLIC ::                                                        &
2175  DAXPY_F90, DCOPY_F90, DDOT_F90, DGBFA_F90, DGBSL_F90, DGEFA_F90, &
2176  DGESL_F90, DSCAL_F90, IDAMAX_F90
2177! ..
2178! .. Private Subroutines and Functions ..
2179  PRIVATE ::                                                       &
2180  CHECK_DIAG    , DACOPY        , DEWSET        , DGROUP        ,  &
2181  DGROUPDS      , DVCHECK       , DVHIN         , DVINDY_BNDS   ,  &
2182  DVINDY_CORE   , DVJAC         , DVJACS28      , DVJUST        ,  &
2183  DVNLSD        , DVNLSS28      , DVNORM        , DVNRDN        ,  &
2184  DVNRDP        , DVNRDS        , DVODE         , DVPREPS       ,  &
2185  DVROOTS       , DVSET         , DVSOL         , DVSOLS28      ,  &
2186  DVSRCO        , DVSTEP        , GDUMMY        , IUMACH        ,  &
2187  IXSAV         , JACSPDB       , JDUMMY        , MA28AD        ,  &
2188  MA28BD        , MA28CD        , MA28DD        , MA28ID        ,  &
2189  MA30AD        , MA30BD        , MA30CD        , MA30DD        ,  &
2190  MC13E         , MC19AD        , MC20AD        , MC20BD        ,  &
2191  MC21A         , MC21B         , MC22AD        , MC23AD        ,  &
2192  MC24AD        , SET_ICN       , XERRDV        , XSETF         ,  &
2193  XSETUN        , DEGR          , IDO           , NUMSRT        ,  &
2194  SEQ           , SETR          , SLO           , SRTDAT        ,  &
2195  FDJS
2196! DVJACS48      , DVNLSS48      , DVPREPS48     , DVSOLS48
2197!_______________________________________________________________________
2198! *****MA48 build change point. Insert the above line.
2199!_______________________________________________________________________
2200! ..
2201! .. Intrinsic Functions ..
2202      INTRINSIC KIND
2203! ..
2204! .. Data Statements ..
2205      DATA OPTS_CALLED/ .FALSE./
2206      DATA MP/6/, NLP/6/, MLP/6/, NSRCH/32768/, ISTART/0/, MAXIT/16/, &
2207        LBIG/ .FALSE./, LBLOCK/ .TRUE./, GROW/ .TRUE./,               &
2208        TOL/0.0_dp/, CGCE/0.5_dp/, BIG/0.0_dp/, ABORT1/ .TRUE./,      &
2209        ABORT2/ .TRUE./, ABORT3/ .FALSE./, ABORT/ .FALSE./, MIRN/0/,  &
2210        MICN/0/, MIRNCP/0/, MICNCP/0/, MIRANK/0/, NDROP1/0/,          &
2211        MRMIN/0.0D0/, MRESID/0/, OK_TO_CALL_MA28/.FALSE./
2212! ..
2213! END OF DVODE_F90 PRIVATE SECTION.
2214!_______________________________________________________________________
2215
2216    CONTAINS
2217
2218      SUBROUTINE VODE_F90(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,J_FCN,G_FCN)
2219! ..
2220! This is an interface for DVODE to allow JAC and GFUN to be
2221! OPTIONAL arguments.
2222! ..
2223     IMPLICIT NONE
2224! ..
2225! .. Structure Arguments ..
2226        TYPE (VODE_OPTS) :: OPTS
2227! ..
2228! .. Scalar Arguments ..
2229        KPP_REAL, INTENT (INOUT) :: T, TOUT
2230        INTEGER, INTENT (INOUT) :: ISTATE
2231        INTEGER, INTENT (IN) :: ITASK, NEQ
2232! ..
2233! .. Array Arguments ..
2234        KPP_REAL, INTENT (INOUT) :: Y(*)
2235! ..
2236! .. Subroutine Arguments ..
2237        OPTIONAL :: G_FCN, J_FCN
2238        EXTERNAL J_FCN
2239! ..
2240! .. Subroutine Interfaces ..
2241     INTERFACE
2242       SUBROUTINE F(NEQ,T,Y,YDOT)
2243         INTEGER, PARAMETER :: WP = KIND(1.0D0)
2244         INTEGER NEQ
2245         REAL(WP) T
2246         REAL(WP), DIMENSION(NEQ) :: Y, YDOT
2247         INTENT(IN)  :: NEQ, T, Y
2248         INTENT(OUT) :: YDOT
2249       END SUBROUTINE F
2250     END INTERFACE
2251
2252     INTERFACE
2253       SUBROUTINE G_FCN(NEQ,T,Y,NG,GROOT)
2254         INTEGER, PARAMETER :: WP = KIND(1.0D0)
2255         INTEGER NEQ, NG
2256         REAL(WP) T
2257         REAL(WP), DIMENSION(NEQ) :: Y
2258         REAL(WP), DIMENSION(NG) :: GROOT(NG)
2259         INTENT(IN)  :: NEQ, T, Y, NG
2260         INTENT(OUT) :: GROOT
2261       END SUBROUTINE G_FCN
2262     END INTERFACE
2263
2264!    Note:
2265!    The best we can do here is to declare J_FCN to be
2266!    external. The interface for a sparse problem differs
2267!    from that for a banded or dense problem. The following
2268!    would suffuce for a banded or dense problem.
2269!    INTERFACE
2270!      SUBROUTINE J_FCN(NEQ,T,Y,ML,MU,PD,NROWPD)
2271!        INTEGER, PARAMETER :: WP = KIND(1.0D0)
2272!        INTEGER NEQ, ML, MU, NROWPD
2273!        REAL(WP) T
2274!        REAL(WP), DIMENSION(NEQ) :: Y
2275!        REAL(WP), DIMENSION(NEQ) :: PD(NROWPD,NEQ)
2276!        INTENT(IN)  :: NEQ, T, Y, ML, MU, NROWPD
2277!        INTENT(INOUT) :: PD
2278!      END SUBROUTINE J_FCN
2279!    END INTERFACE
2280!    The following would suffice for a sparse problem.
2281    INTERFACE
2282      SUBROUTINE J_FCN(NEQ,T,Y,IA,JA,NZ,P)
2283        INTEGER, PARAMETER :: WP = KIND(1.0D0)
2284        INTEGER NEQ, NZ
2285        REAL(WP) T
2286        REAL(WP), DIMENSION Y(*), P(*)
2287        INTEGER, DIMENSION IA(*), JA(*)
2288        INTENT(IN) :: NEQ, T, Y
2289        INTENT(INOUT) IA, JA, NZ, P
2290      END SUBROUTINE J_FCN
2291    END INTERFACE
2292! ..
2293! .. Local Scalars ..
2294        INTEGER :: HOWCALL, METH, MFA, MITER, MOSS, NG
2295        CHARACTER (80) :: MSG
2296! ..
2297! .. Intrinsic Functions ..
2298        INTRINSIC ABS, PRESENT
2299! ..
2300! .. FIRST EXECUTABLE STATEMENT VODE_F90
2301! ..
2302!       Check that SET_OPTS has been called.
2303        IF (.NOT.OPTS_CALLED) THEN
2304          MSG = 'You have not called SET_OPTS before'
2305          CALL XERRDV(MSG,10,1,0,0,0,0,ZERO,ZERO)
2306          MSG = 'calling DVODE_F90 the first time.'
2307          CALL XERRDV(MSG,10,2,0,0,0,0,ZERO,ZERO)
2308        END IF
2309
2310!       Check that JAC is present if it is needed.
2311        IF (PRESENT(J_FCN)) THEN
2312        ELSE
2313!         Note:
2314!         MOSS is irrelevant. OPTS%MF is two digits after the
2315!         call to SET_OPTS.
2316          MFA = ABS(OPTS%MF)
2317          MOSS = MFA/100
2318          METH = (MFA-100*MOSS)/10
2319          MITER = MFA - 100*MOSS - 10*METH
2320          IF (MITER==1 .OR. MITER==4 .OR. MITER==6) THEN
2321            MSG = 'You have specified a value of the integration'
2322            CALL XERRDV(MSG,20,1,0,0,0,0,ZERO,ZERO)
2323            MSG = 'method flag MF which requires that you supply'
2324            CALL XERRDV(MSG,20,1,0,0,0,0,ZERO,ZERO)
2325            MSG = 'a Jacobian subroutine JAC; but FAC is not'
2326            CALL XERRDV(MSG,20,1,0,0,0,0,ZERO,ZERO)
2327            MSG = 'present in the argument list.'
2328            CALL XERRDV(MSG,20,2,0,0,0,0,ZERO,ZERO)
2329          END IF
2330        END IF
2331
2332!       Check that GFUN is present if it is needed.
2333
2334        IF (PRESENT(G_FCN)) THEN
2335        ELSE
2336          NG = OPTS%NG
2337          IF (NG>0) THEN
2338            MSG = 'You have indicated that events are present but'
2339            CALL XERRDV(MSG,30,1,0,0,0,0,ZERO,ZERO)
2340            MSG = 'you have not supplied a GFUN subroutine.'
2341            CALL XERRDV(MSG,30,2,0,0,0,0,ZERO,ZERO)
2342          END IF
2343        END IF
2344
2345!     Determine how DVODE will be called.
2346
2347!     HOWCALL = 1: JDUMMY, GDUMMY
2348!               2: JAC, GFUN
2349!               3: JAC, GDUMMY
2350!               4: JDUMMY, GFUN
2351        HOWCALL = 1
2352        IF (PRESENT(J_FCN)) THEN
2353          IF (PRESENT(G_FCN)) THEN
2354            HOWCALL = 2
2355          ELSE
2356            HOWCALL = 3
2357          END IF
2358        ELSE
2359          IF (PRESENT(G_FCN)) THEN
2360            HOWCALL = 4
2361          ELSE
2362            HOWCALL = 1
2363          END IF
2364        END IF
2365
2366!       Call DVODE to do the integration.
2367
2368        IF (HOWCALL==1) THEN
2369          CALL DVODE(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,JDUMMY,GDUMMY)
2370        ELSE IF (HOWCALL==2) THEN
2371          CALL DVODE(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,J_FCN,G_FCN)
2372        ELSE IF (HOWCALL==3) THEN
2373          CALL DVODE(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,J_FCN,GDUMMY)
2374        ELSE IF (HOWCALL==4) THEN
2375          CALL DVODE(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,JDUMMY,G_FCN)
2376        END IF
2377        RETURN
2378
2379      END SUBROUTINE VODE_F90
2380!_______________________________________________________________________
2381
2382      SUBROUTINE JDUMMY(NEQ,T,Y,ML,MU,PD,NROWPD)
2383! ..
2384! This is a dummy Jacobian subroutine for VODE_F90 (never called).
2385! ..
2386     IMPLICIT NONE
2387! ..
2388! .. Scalar Arguments ..
2389        KPP_REAL :: T
2390        INTEGER :: ML, MU, NEQ, NROWPD, I
2391        LOGICAL DUMMY
2392! ..
2393! .. Array Arguments ..
2394        KPP_REAL :: PD(NROWPD,*), Y(*)
2395! ..
2396      INTENT(IN) T, Y, ML, MU, NROWPD
2397      INTENT(INOUT) PD
2398! ..
2399! .. FIRST EXECUTABLE STATEMENT JDUMMY
2400! ..
2401!       Get rid of some needless compiler warning messages.
2402        DUMMY = .FALSE.
2403        IF (DUMMY) THEN
2404          I = NEQ
2405          I = ML
2406          I = MU
2407          I = NROWPD
2408          PD(1,1) = T
2409          PD(1,1) = Y(1)
2410          PD(1,1) = DBLE(REAL(I))
2411        END IF
2412        RETURN
2413
2414      END SUBROUTINE JDUMMY
2415!_______________________________________________________________________
2416
2417      SUBROUTINE GDUMMY(NEQ,T,Y,NG,GOUT)
2418! ..
2419! This is a dummy event subroutine for VODE_F90 (never called).
2420! ..
2421     IMPLICIT NONE
2422! ..
2423! .. Scalar Arguments ..
2424        KPP_REAL :: T
2425        INTEGER :: NEQ, NG, I
2426        LOGICAL DUMMY
2427! ..
2428! .. Array Arguments ..
2429        KPP_REAL :: GOUT(*), Y(*)
2430! ..
2431      INTENT(IN) NEQ, T, Y, NG
2432      INTENT(OUT) GOUT
2433! ..
2434! .. FIRST EXECUTABLE STATEMENT JDUMMY
2435! ..
2436!       Get rid of some needless compiler warning messages.
2437        DUMMY = .FALSE.
2438        IF (DUMMY) THEN
2439          I = NEQ
2440          I = NG
2441          GOUT(1) = T
2442          GOUT(1) = Y(1)
2443          GOUT(1) = DBLE(REAL(I))
2444        END IF
2445        RETURN
2446
2447      END SUBROUTINE GDUMMY
2448!_______________________________________________________________________
2449
2450  SUBROUTINE SET_OPTS_2(HMAX,HMIN,MXSTEP)
2451! ..
2452! Allow the maximum step size, the minimum step size, and the maximum
2453! number of steps to be changed without restarting the integration.
2454! ..
2455!                     Quick Summary of Options
2456! HMAX                   - Maximum step size in DVODE
2457! HMIN                   - Minimum step size in DVODE
2458! MXSTEP                 - Maximum number of integration steps in DVODE
2459! ..
2460     IMPLICIT NONE
2461! ..
2462! .. Scalar Arguments ..
2463        KPP_REAL, OPTIONAL, INTENT (IN) :: HMAX, HMIN
2464        INTEGER, OPTIONAL, INTENT (IN) :: MXSTEP
2465! ..
2466! .. Local Scalars ..
2467        CHARACTER (80) :: MSG
2468! ..
2469! .. Intrinsic Functions ..
2470        INTRINSIC ALLOCATED, PRESENT
2471! ..
2472! .. FIRST EXECUTABLE STATEMENT SET_OPTS_2
2473! ..
2474!       Check that SET_OPTS has been called:
2475        IF (.NOT.OPTS_CALLED) THEN
2476          MSG = 'You have not called SET_OPTS before'
2477          CALL XERRDV(MSG,40,1,0,0,0,0,ZERO,ZERO)
2478          MSG = 'calling subroutine SET_OPTS_2.'
2479          CALL XERRDV(MSG,40,2,0,0,0,0,ZERO,ZERO)
2480        END IF
2481        IF (PRESENT(HMAX)) THEN
2482          RUSER(6) = HMAX
2483          MSG = 'HMAX changed in SET_OPTS_2.'
2484          CALL XERRDV(MSG,50,1,0,0,0,1,HMAX,ZERO)
2485        END IF
2486        IF (PRESENT(HMIN)) THEN
2487          RUSER(7) = HMIN
2488          MSG = 'HMIN changed in SET_OPTS_2.'
2489          CALL XERRDV(MSG,60,1,0,0,0,1,HMIN,ZERO)
2490        END IF
2491        IF (PRESENT(MXSTEP)) THEN
2492          IUSER(6) = MXSTEP
2493          MSG = 'MXSTEP changed in SET_OPTS_2.'
2494          CALL XERRDV(MSG,70,1,1,MXSTEP,0,0,ZERO,ZERO)
2495        END IF
2496
2497  END SUBROUTINE SET_OPTS_2
2498!_______________________________________________________________________
2499
2500  FUNCTION SET_NORMAL_OPTS(DENSE_J, BANDED_J, SPARSE_J,                &
2501    USER_SUPPLIED_JACOBIAN, LOWER_BANDWIDTH, UPPER_BANDWIDTH,          &
2502    RELERR, ABSERR, ABSERR_VECTOR, NEVENTS) RESULT(OPTS)
2503
2504! FUNCTION SET_NORMAL_OPTS:
2505!    Jacobian type:
2506!       DENSE_J, BANDED_J, SPARSE_J
2507!    Analytic Jacobian:
2508!       USER_SUPPLIED_JACOBIAN
2509!    If banded Jacobian:
2510!       LOWER_BANDWIDTH,UPPER_BANDWIDTH
2511!    Error tolerances:
2512!       RELERR, ABSERR, ABSERR_VECTOR
2513!    Rootfinding:
2514!       NEVENTS
2515! RESULT(OPTS)
2516
2517! Note:
2518! Invoking SET_NORMAL_OPTS causes an integration restart. A common
2519! situation is one in which all you wish to change is one of the
2520! vode.f77 optional parameters HMAX, HMIN, or MXSTEP. Once the
2521! integration is started and this is all you wish to do, you can
2522! change any of these parameters without restarting the integration
2523! simply by calling subroutine SET_OPTS_2:
2524!      CALL SET_OPTS_2(HMAX,HMIN,MXSTEP)
2525! Each of the three arguments is optional and only the ones actually
2526! supplied will be used. Changes will take effect in the same manner
2527! as in the VODE.f77 solver.
2528!
2529! NORMAL_OPTIONS sets user parameters for DVODE via keywords.
2530! Values that are defined herein will be used internally by
2531! DVODE. All option keywords are OPTIONAL and order is not
2532! important. These options should be adequate for most problems.
2533! If you wish to use more specialized options, you must use
2534! SET_INTERMEDIATE_OPTS or SET_OPTS rather than NORMAL_OPTS.
2535! If you wish to use SET_INTERMEDIATE_OPTS or SET_OPTS, you
2536! may use any of the SET_NORMAL_OPTS keywords or any of the
2537! keywords available for these two functions. Of course, you
2538! may opt to simply use SET_OPTS for all problems.
2539
2540! Note that DVODE_F90 requires that one of SET_NORMAL_OPTS or
2541! SET_INTERMEDIATE_OPTS or SET_OPTS is called before the first
2542! time DVODE_F90 is called.
2543!
2544! Important Note:
2545! If feasible, you should use the dense or banded option; but
2546! SET_NORMAL_OPTS allows you to use a sparse internal Jacobian
2547! (i.e., one that is determined using finite differences) and
2548! structure pointere array that are determined internally
2549! using finite differences. If any of the following are true
2550!    (1) DVODE_F90 doesn't perform satisfactorily for
2551!        your problem,
2552!    (2) you are solving a very large problem,
2553!    (3) you wish to supply the sparse pointer arrays
2554!        directly,
2555!    (4) you wish to supply an analytical sparse Jacobian,
2556! or
2557!    (5) you wish to use one of the specialized sparse
2558!        Jacobian options,
2559! you are encouraged to use SET_OPTS which contains several
2560! provisions for solving sparse problems more efficiently.
2561
2562! Option Types:
2563! DENSE_J                - logical
2564! BANDED_J               - logical
2565! SPARSE_J               - logical
2566! USER_SUPPLIED_JACOBIAN - logical
2567! LOWER_BANDWIDTH        - integer
2568! UPPER_BANDWIDTH        - integer
2569! RELERR                 - real(wp) scalar
2570! ABSERR                 - real(wp) scalar
2571! ABSERR_VECTOR          - real(wp) vector
2572! NEVENTS                - integer
2573! Options:
2574! ABSERR                 = Absolute error tolerance
2575! ABSERR_VECTOR          = Vector of absolute error tolerances
2576! RELERR                 = Scalar relative error tolerance
2577! NEVENTS                = Number of event functions (requires
2578!                          user-supplied GFUN)
2579! DENSE_J                = Use dense linear algebra if .TRUE.
2580! BANDED_J               = Use banded linear algebra if .TRUE.
2581!   LOWER_BANDWIDTH      = Lower bandwidth of the Jacobian
2582!                          (required if BANDED_J = .TRUE.)
2583!   UPPER_BANDWIDTH      = Upper bandwidth of the Jacobian
2584!                          (required if BANDED_J = .TRUE.)
2585! SPARSE_J               = Use sparse linear algebra if .TRUE.
2586! USER_SUPPLIED_JACOBIAN = Exact Jacobian option
2587!                          (requires user-supplied JAC;
2588!                          ignored for SPARSE_J=.TRUE.)
2589!
2590! Note: DENSE_J takes precedence over BANDED_J which in turn
2591! takes precedence over SPARSE_J if more than one is supplied.
2592! If neither of the three flags is present, the nonstiff Adams
2593! option will be used. Similiarly, ABSERR_VECTOR takes
2594! precedence over ABSERR.
2595!
2596! Note on Jacobian Storage Formats:
2597!
2598! If you supply an analytic Jacobian PD, load the
2599! Jacobian elements DF(I)/DY(J), the partial
2600! derivative of F(I) with respect to Y(J), using
2601! the following formats. Here, Y is the solution,
2602! F is the derivative, and PD is the Jacobian.
2603!
2604! For a full Jacobian, load PD(I,J) with DF(I)/DY(J).
2605! Your code might look like this:
2606!    DO J = 1, NEQ
2607!       DO I = 1, NEQ
2608!          PD(I,J) = ... DF(I)/DY(J)
2609!       END DO
2610!    END DO       
2611!
2612! For a banded Jacobian, load PD(I-J+MU+1,J) with
2613! DF(I)/DY(J) where ML is the lower bandwidth
2614! and MU is the upper bandwidth of the Jacobian.
2615! Your code might look like this:
2616!    DO J = 1, NEQ
2617!       I1 = MAX(1,J-ML)
2618!       I2 = MIN(N,J+MU)
2619!       DO I = I1, I2
2620!          K = I-J+MU+1
2621!          PD(K,J) = ... DF(I)/DY(J)
2622!       END DO
2623!    END DO
2624! ..
2625     IMPLICIT NONE
2626! ..
2627! .. Function Return Value ..
2628        TYPE (VODE_OPTS) :: OPTS
2629! ..
2630! .. Scalar Arguments ..
2631        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR,RELERR
2632        INTEGER, OPTIONAL, INTENT (IN) :: LOWER_BANDWIDTH,   &
2633          NEVENTS,UPPER_BANDWIDTH
2634        LOGICAL, OPTIONAL, INTENT (IN) :: BANDED_J, DENSE_J, &
2635          SPARSE_J, USER_SUPPLIED_JACOBIAN
2636! ..
2637! .. Array Arguments ..
2638        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR_VECTOR(:)
2639! ..
2640! .. Local Scalars ..
2641        INTEGER :: IER,IOPT,METH,MF,MFA,MFSIGN,MITER,ML,MOSS, &
2642          MU,NAE,NG,NRE
2643        LOGICAL :: BANDED,DENSE,SPARSE
2644        CHARACTER (80) :: MSG
2645! ..
2646! .. Intrinsic Functions ..
2647        INTRINSIC ALLOCATED, IABS, MAX, MINVAL, PRESENT, SIGN, SIZE
2648! ..
2649! .. FIRST EXECUTABLE STATEMENT SET_NORMAL_OPTS
2650! ..
2651        RUSER(1:LRWUSER) = ZERO
2652        IUSER(1:LIWUSER) = 0
2653       
2654!       Allow default error tolerances?
2655        ALLOW_DEFAULT_TOLS = .FALSE.
2656
2657!       Maximum number of consecutive error test failures?
2658        CONSECUTIVE_EFAILS = KFH
2659
2660!       Maximum number of consecutive corrector iteration failures?
2661        CONSECUTIVE_CFAILS = MXNCF
2662
2663!       Use JACSP to approximate Jacobian?
2664        USE_JACSP = .FALSE.
2665
2666!       Set the flag to indicate that SET_NORMAL_OPTS has been called.
2667        OPTS_CALLED = .TRUE.
2668
2669!       Set the MA48 storage cleanup flag.
2670        MA48_WAS_USED = .FALSE.
2671
2672!       Set the fast factor option for MA48,
2673        USE_FAST_FACTOR = .TRUE.
2674
2675!       Set the constant Jacobian flags.
2676        J_IS_CONSTANT = .FALSE.
2677        J_HAS_BEEN_COMPUTED = .FALSE.
2678
2679!       Determine the working precision and define the value for UMAX
2680!       expected by MA28. Note that it is different for single and
2681!       double precision.
2682        WPD = KIND(1.0D0)
2683        WPS = KIND(1.0E0)
2684        IF (WPD/=WP .AND. WPS/=WP) THEN
2685          MSG = 'Illegal working precision in SET_NORMAL_OPTS.'
2686          CALL XERRDV(MSG,80,2,0,0,0,0,ZERO,ZERO)
2687        END IF
2688        IF (WPD==WP) THEN
2689!       Working precision is double.
2690          UMAX = 0.999999999_dp
2691        ELSE
2692!       Working precision is single.
2693          UMAX = 0.9999_dp
2694        END IF
2695
2696        MA28AD_CALLS = 0
2697        MA28BD_CALLS = 0
2698        MA28CD_CALLS = 0
2699        MC19AD_CALLS = 0
2700!_______________________________________________________________________
2701! *****MA48 build change point. Insert these statements.
2702!       MA48AD_CALLS = 0
2703!       MA48BD_CALLS = 0
2704!       MA48CD_CALLS = 0
2705!_______________________________________________________________________
2706        IRNCP = 0
2707        ICNCP = 0
2708        MINIRN = 0
2709        MINICN = 0
2710        MAX_MINIRN = 0
2711        MAX_MINICN = 0
2712        MAX_NNZ = 0
2713
2714!       Set the flag to warn the user if |(y(t)| < abserr.
2715        YMAXWARN = .FALSE.
2716
2717!       Load defaults for the optional input arrays for DVODE.
2718        IUSER(1:8) = 0
2719        RUSER(1:8) = ZERO
2720
2721!       Set the method flag.
2722        MF = 10
2723        IF (PRESENT(SPARSE_J)) THEN
2724          IF (SPARSE_J) THEN
2725             MF = 227
2726             IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
2727               MSG = 'You have indicated you wish to supply an'
2728               CALL XERRDV(MSG,90,1,0,0,0,0,ZERO,ZERO)
2729               MSG = 'exact sparse Jacobian in function'
2730               CALL XERRDV(MSG,90,1,0,0,0,0,ZERO,ZERO)
2731               MSG = 'SET_NORMAL_OPTS. In order to do this,'
2732               CALL XERRDV(MSG,90,1,0,0,0,0,ZERO,ZERO)
2733               MSG = 'you must use SET_OPTS. Execution will'
2734               CALL XERRDV(MSG,90,1,0,0,0,0,ZERO,ZERO)
2735               MSG = 'continue.'
2736               CALL XERRDV(MSG,90,1,0,0,0,0,ZERO,ZERO)
2737             END IF
2738          END IF
2739        END IF
2740
2741        IF (PRESENT(BANDED_J)) THEN
2742          IF (BANDED_J) THEN
2743            IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
2744              IF (USER_SUPPLIED_JACOBIAN) THEN
2745                MF = 24
2746              ELSE
2747                MF = 25
2748              END IF
2749            ELSE
2750              MF = 25
2751            END IF
2752          END IF
2753        END IF
2754
2755        IF (PRESENT(DENSE_J)) THEN
2756          IF (DENSE_J) THEN
2757            IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
2758              IF (USER_SUPPLIED_JACOBIAN) THEN
2759                MF = 21
2760              ELSE
2761                MF = 22
2762              END IF
2763            ELSE
2764              MF = 22
2765            END IF
2766          END IF
2767        END IF
2768
2769!       Check for errors in MF.
2770        MFA = IABS(MF)
2771        MOSS = MFA/100
2772        METH = (MFA-100*MOSS)/10
2773        MITER = MFA - 100*MOSS - 10*METH
2774        IF (METH<1 .OR. METH>2) THEN
2775          MSG = 'Illegal value of METH in SET_NORMAL_OPTS.'
2776          CALL XERRDV(MSG,100,2,0,0,0,0,ZERO,ZERO)
2777        END IF
2778        IF (MITER<0 .OR. MITER>7) THEN
2779          MSG = 'Illegal value of MITER in SET_NORMAL_OPTS.'
2780          CALL XERRDV(MSG,110,2,0,0,0,0,ZERO,ZERO)
2781        END IF
2782        IF (MOSS<0 .OR. MOSS>2) THEN
2783          MSG = 'Illegal value of MOSS in SET_NORMAL_OPTS.'
2784          CALL XERRDV(MSG,120,2,0,0,0,0,ZERO,ZERO)
2785        END IF
2786
2787!       Reset MF, now that MOSS is known.
2788        MFSIGN = SIGN(1,MF)
2789        MF = MF - 100*MOSS*MFSIGN
2790
2791        IF (MITER==0) THEN
2792          DENSE = .FALSE.
2793          BANDED = .FALSE.
2794          SPARSE = .FALSE.
2795        ELSE IF (MITER==1 .OR. MITER==2) THEN
2796          DENSE = .TRUE.
2797          BANDED = .FALSE.
2798          SPARSE = .FALSE.
2799        ELSE IF (MITER==3) THEN
2800          DENSE = .FALSE.
2801          BANDED = .FALSE.
2802          SPARSE = .FALSE.
2803        ELSE IF (MITER==4 .OR. MITER==5) THEN
2804          DENSE = .FALSE.
2805          BANDED = .TRUE.
2806          SPARSE = .FALSE.
2807        ELSE IF (MITER==6 .OR. MITER==7) THEN
2808          DENSE = .FALSE.
2809          BANDED = .FALSE.
2810          SPARSE = .TRUE.
2811        END IF
2812
2813!       Define the banded Jacobian band widths.
2814        IF (BANDED) THEN
2815          IF (PRESENT(LOWER_BANDWIDTH)) THEN
2816            ML = LOWER_BANDWIDTH
2817            IUSER(1) = ML
2818          ELSE
2819            MSG = 'In SET_NORMAL_OPTS you have indicated a'
2820            CALL XERRDV(MSG,130,1,0,0,0,0,ZERO,ZERO)
2821            MSG = 'banded Jacobian but you have not supplied'
2822            CALL XERRDV(MSG,130,1,0,0,0,0,ZERO,ZERO)
2823            MSG = 'the lower bandwidth.'
2824            CALL XERRDV(MSG,130,2,0,0,0,0,ZERO,ZERO)
2825          END IF
2826          IF (PRESENT(UPPER_BANDWIDTH)) THEN
2827            MU = UPPER_BANDWIDTH
2828            IUSER(2) = MU
2829          ELSE
2830            MSG = 'In SET_NORMAL_OPTS you have indicated a'
2831            CALL XERRDV(MSG,140,1,0,0,0,0,ZERO,ZERO)
2832            MSG = 'banded Jacobian but you have not supplied'
2833            CALL XERRDV(MSG,140,1,0,0,0,0,ZERO,ZERO)
2834            MSG = 'the upper bandwidth.'
2835            CALL XERRDV(MSG,140,2,0,0,0,0,ZERO,ZERO)
2836          END IF
2837        END IF
2838
2839!       Define the sparse Jacobian options.
2840        IF (SPARSE) THEN
2841!         Set the MA28 message flag.
2842          LP = 0
2843!         Set the MA28 pivot sequence frequency flag.
2844          REDO_PIVOT_SEQUENCE = .FALSE.
2845!         Set the MA28 singularity threshold.
2846          EPS = 1.0E-4_dp
2847!         Use scaling of the iteration matrix.
2848          SCALE_MATRIX = .TRUE.
2849!         Define the elbow room factor for the MA28 sparse work arrays.
2850          ELBOW_ROOM = 2
2851!         NZSWAG is a swag for the number of nonzeros in the Jacobian.
2852          NZ_SWAG = 0
2853!         Use partial pivoting.
2854          U_PIVOT = ONE
2855!         Indicate that SET_IAJA has not yet been called successfully.
2856          IAJA_CALLED = .FALSE.
2857!         Check for illegal method flags.
2858          IF (MOSS==2 .AND. MITER/=7) THEN
2859            MSG = 'In SET_NORMAL_OPTS MOSS=2 but MITER is not 7.'
2860            CALL XERRDV(MSG,150,2,0,0,0,0,ZERO,ZERO)
2861          END IF
2862          IF (MOSS==1 .AND. MITER/=6) THEN
2863            MSG = 'In SET_NORMAL_OPTS MOSS=1 but MITER is not 6.'
2864            CALL XERRDV(MSG,160,2,0,0,0,0,ZERO,ZERO)
2865          END IF
2866!         IF (MOSS==0 .AND. MITER/=7) THEN
2867!           MSG = 'In SET_NORMAL_OPTS MOSS=0 but MITER is not 7.'
2868!           CALL XERRDV(MSG,170,2,0,0,0,0,ZERO,ZERO)
2869!         END IF
2870        END IF
2871
2872!       Define the number of event functions.
2873        IF (PRESENT(NEVENTS)) THEN
2874          IF (NEVENTS>0) THEN
2875            NG = NEVENTS
2876          ELSE
2877            NG = 0
2878          END IF
2879        ELSE
2880          NG = 0
2881        END IF
2882
2883!       No solution bounds will be imposed.
2884        BOUNDS = .FALSE.
2885
2886!       Load the user options into the solution structure.
2887        OPTS%MF = MF
2888        OPTS%METH = METH
2889        OPTS%MITER = MITER
2890        OPTS%MOSS = MOSS
2891        OPTS%DENSE = DENSE
2892        OPTS%BANDED = BANDED
2893        OPTS%SPARSE = SPARSE
2894        OPTS%NG = NG
2895
2896        IOPT = 1
2897        OPTS%IOPT = IOPT
2898
2899!       Process the error tolerances.
2900
2901!       Relative error tolerance.
2902        NRE = 1
2903        ALLOCATE (OPTS%RTOL(NRE),STAT=IER)
2904        CALL CHECK_STAT(IER,10)
2905        IF (PRESENT(RELERR)) THEN
2906          IF (RELERR<ZERO) THEN
2907            MSG = 'RELERR must be nonnegative.'
2908            CALL XERRDV(MSG,180,2,0,0,0,0,ZERO,ZERO)
2909          END IF
2910          OPTS%RTOL = RELERR
2911        ELSE
2912          IF (ALLOW_DEFAULT_TOLS) THEN
2913             OPTS%RTOL = 1.0E-4_dp
2914             MSG = 'By not specifying RELERR, you have elected to use a default'
2915             CALL XERRDV(MSG,190,1,0,0,0,0,ZERO,ZERO)
2916             MSG = 'relative error tolerance equal to 1.0D-4. Please be aware a'
2917             CALL XERRDV(MSG,190,1,0,0,0,0,ZERO,ZERO)
2918             MSG = 'tolerance this large is not appropriate for all problems.'
2919             CALL XERRDV(MSG,190,1,0,0,0,0,ZERO,ZERO)
2920             MSG = 'Execution will continue'
2921             CALL XERRDV(MSG,190,1,0,0,0,0,ZERO,ZERO)
2922          ELSE
2923             MSG = 'You must specify a nonzero relative error tolerance.'
2924             CALL XERRDV(MSG,200,2,0,0,0,0,ZERO,ZERO)
2925          END IF
2926        END IF
2927
2928!       Absolute error tolerance(s).
2929        IF (PRESENT(ABSERR_VECTOR)) THEN
2930          IF (MINVAL(ABSERR_VECTOR)<ZERO) THEN
2931            MSG = 'All components of ABSERR_VECTOR must'
2932            CALL XERRDV(MSG,210,1,0,0,0,0,ZERO,ZERO)
2933            MSG = 'be nonnegative.'
2934            CALL XERRDV(MSG,210,2,0,0,0,0,ZERO,ZERO)
2935          END IF
2936          NAE = SIZE(ABSERR_VECTOR)
2937        ELSE
2938          NAE = 1
2939        END IF
2940        ALLOCATE (OPTS%ATOL(NAE),STAT=IER)
2941        CALL CHECK_STAT(IER,20)
2942        IF (PRESENT(ABSERR_VECTOR)) THEN
2943          OPTS%ATOL = ABSERR_VECTOR
2944        ELSE IF (PRESENT(ABSERR)) THEN
2945          IF (ABSERR<ZERO) THEN
2946            MSG = 'ABSERR must be nonnegative.'
2947            CALL XERRDV(MSG,220,2,0,0,0,0,ZERO,ZERO)
2948          END IF
2949          OPTS%ATOL = ABSERR
2950        ELSE
2951          IF (ALLOW_DEFAULT_TOLS) THEN
2952             OPTS%ATOL = 1D-6
2953             MSG = 'By not specifying ABSERR, you have elected to use a default'
2954             CALL XERRDV(MSG,230,1,0,0,0,0,ZERO,ZERO)
2955             MSG = 'absolute error tolerance equal to 1.0D-6. Please be aware a'
2956             CALL XERRDV(MSG,230,1,0,0,0,0,ZERO,ZERO)
2957             MSG = 'tolerance this large is not appropriate for all problems.'
2958             CALL XERRDV(MSG,230,1,0,0,0,0,ZERO,ZERO)
2959             MSG = 'Execution will continue'
2960             CALL XERRDV(MSG,230,1,0,0,0,0,ZERO,ZERO)
2961          ELSE
2962             MSG = 'You must specify a vector of absolute error tolerances or'
2963             CALL XERRDV(MSG,240,1,0,0,0,0,ZERO,ZERO)
2964             MSG = 'a scalar error tolerance. It is recommended that you use'
2965             CALL XERRDV(MSG,240,1,0,0,0,0,ZERO,ZERO)
2966             MSG = 'a vector of absolute error tolerances.'
2967             CALL XERRDV(MSG,240,2,0,0,0,0,ZERO,ZERO)
2968          END IF
2969        END IF
2970
2971!       ITOL error tolerance flag.
2972!          ITOL   RTOL     ATOL            EWT(i)
2973!            1   scalar   scalar  RTOL*ABS(Y(i)) + ATOL
2974!            2   scalar   array   RTOL*ABS(Y(i)) + ATOL(i)
2975        IF (PRESENT(ABSERR_VECTOR)) THEN
2976           OPTS%ITOL = 2
2977        ELSE
2978           OPTS%ITOL = 1
2979        END IF
2980        RETURN
2981
2982  END FUNCTION SET_NORMAL_OPTS
2983!_______________________________________________________________________
2984
2985  FUNCTION SET_INTERMEDIATE_OPTS(DENSE_J, BANDED_J, SPARSE_J,          &
2986    USER_SUPPLIED_JACOBIAN,                                            &
2987    LOWER_BANDWIDTH, UPPER_BANDWIDTH,                                  &
2988    RELERR, ABSERR, ABSERR_VECTOR,                                     &
2989    TCRIT, H0, HMAX, HMIN, MAXORD, MXSTEP, MXHNIL,                     &
2990    NZSWAG, USER_SUPPLIED_SPARSITY, MA28_RPS,                          &
2991    NEVENTS, CONSTRAINED, CLOWER, CUPPER, CHANGE_ONLY_f77_OPTIONS)     &
2992  RESULT(OPTS)
2993
2994! FUNCTION SET_INTERMEDIATE_OPTS:
2995!    Jacobian type:
2996!       DENSE_J, BANDED_J, SPARSE_J
2997!    Analytic Jacobian:
2998!       USER_SUPPLIED_JACOBIAN
2999!    If banded Jacobian:
3000!       LOWER_BANDWIDTH, UPPER_BANDWIDTH
3001!    Error tolerances:
3002!       RELERR, ABSERR, ABSERR_VECTOR
3003!    VODE.f77 optional parameters:
3004!       TCRIT, H0, HMAX, HMIN, MAXORD, MXSTEP, MXHNIL
3005!    Sparse flags:
3006!       NZSWAG, USER_SUPPLIED_SPARSITY, MA28_RPS
3007!    Rootfinding:
3008!       NEVENTS
3009!    Impose bounds on solution:
3010!       CONSTRAINED, CLOWER, CUPPER
3011!    Change one or more of HMAX, HMIN, TCRIT, MXSTEP, MXHNIL, MAXORD
3012!       CHANGE_ONLY_f77_OPTIONS
3013! RESULT(OPTS)
3014
3015! SET_OPTIONS sets user parameters for DVODE via keywords. Values
3016! that are defined herein will be used internally by DVODE.
3017! All option keywords are OPTIONAL and order is not important.
3018
3019! Note that DVODE_F90 requires that one of SET_NORMAL_OPTS or
3020! SET_INTERMEDIATE_OPTS or SET_OPTS is called before the first
3021! time DVODE_F90 is called.
3022
3023!                     Quick Summary of Options
3024
3025! DENSE_J                - Jacobian is sparse alternative to MF
3026! BANDED_J               - Jacobian is banded alternative to MF
3027! SPARSE_J               - Jacobian is sparse alternative to MF   
3028! USER_SUPPLIED_JACOBIAN - User will supply Jacobian subroutine
3029!                          (user supplied subroutine JAC required)
3030! LOWER_BANDWIDTH        - Lower bandwidth ML in DVODE
3031! UPPER_BANDWIDTH        - Upper bandwidth MU in DVODE
3032! RELERR                 - Scalar relative error tolerance in DVODE
3033! ABSERR                 - Scalar absolute error tolerance in DVODE
3034! ABSERR_VECTOR          - Vector absolute error tolerance in DVODE
3035! TCRIT                  - Critical time TCRIT in DVODE
3036! H0                     - Starting step size in DVODE
3037! HMAX                   - Maximum step size in DVODE
3038! HMIN                   - Minimum step size in DVODE
3039! MAXORD                 - Maximum integration order in DVODE
3040! MXSTEP                 - Maximum number of integration steps
3041!                          in DVODE
3042! MXHNIL                 - Maximum number of T+H=T messages in DVODE
3043! NZSWAG                 - guess for the number of nonzeros in sparse
3044!                          Jacobian
3045! USER_SUPPLIED_SPARSITY - user will supply sparsity structure
3046!                          arrays by calling USERSETS_IAJA
3047! MA28_RPS               - Redo MA28AD pivot sequence if a singularity
3048!                          is encountered
3049! NEVENTS                - number of user defined root finding functions
3050!                          (user supplied subroutine G required)
3051! CONSTRAINED,           - array of solution component indices that
3052! CLOWER,                  are to be constrained by the lower and
3053! CUPPER                   upper bound arrays CLOWER and CUPPER so that
3054!                          CLOWER(I) <= Y(CONSTRAINED(I)) <= CUPPER(I)
3055!                     Options Types
3056! DENSE_J                - logical
3057! BANDED_J               - logical
3058! SPARSE_J               - logical
3059! USER_SUPPLIED_JACOBIAN - logical
3060! LOWER_BANDWIDTH        - integer
3061! UPPER_BANDWIDTH        - integer
3062! RELERR                 - real(wp) scalar
3063! ABSERR                 - real(wp) scalar
3064! ABSERR_VECTOR          - real(wp) vector
3065! TCRIT                  - real(wp) scalar
3066! H0                     - real(wp) scalar
3067! HMAX                   - real(wp) scalar
3068! HMIN                   - real(wp) scalar
3069! MAXORD                 - integer
3070! MXSTEP                 - integer
3071! MXHNIL                 - integer
3072! NZSWAG                 - integer
3073! USER_SUPPLIED_SPARSITY - logical
3074! MA28_RPS               - logical
3075! NEVENTS                - integer
3076! CONSTRAINED            - integer array
3077! CLOWER                 - real(wp) array
3078! CUPPER                 - real(wp) array
3079! CHANGE_ONLY_f77_OPTIONS- logical
3080! Argument list parameters:
3081! ABSERR                   = scalar absolute error tolerance
3082! ABSERR_VECTOR            = vector of absolute error tolerances
3083! RELERR                   = scalar relative error tolerance
3084! NEVENTS                  = Number of event functions (requires
3085!                            user-supplied GFUN)
3086! DENSE_J                  = use dense linear algebra if .TRUE.
3087! BANDED_J                 = use banded linear algebra if .TRUE.
3088!   LOWER_BANDWIDTH        = lower bandwidth of the Jacobian
3089!                            (required if BANDED_J = .TRUE.)
3090!   UPPER_BANDWIDTH        = upper bandwidth of the Jacobian
3091!                            (required if BANDED_J = .TRUE.)
3092! SPARSE_J                 = use sparse linear algebra if .TRUE.
3093!
3094!   NZSWAG                 = If you wish you may supply a guess,
3095!                            NZSWAG, at the number of nonzeros
3096!                            in the Jacobian matrix. In some cases
3097!                            this will speed up the determination
3098!                            of the necessary storage.
3099!   USER_SUPPLIED_SPARSITY = .TRUE. if you wish to supply the sparsity
3100!                            structure arrays directly by calling
3101!   MA28_RPS               = .TRUE. to force MA28AD to calculate a new
3102!                            pivot sequence for use in MA28BD if a
3103!                            singular iteration matrix is encountered
3104!                            is smaller than EPS, it will flag the
3105!                            Jacobian as singular and force MA28AD
3106!                            to calculate a new pivot sequence.
3107! USER_SUPPLIED_JACOBIAN   = exact Jacobian option
3108!                            (requires user-supplied JAC)
3109! TCRIT                    = critical time
3110! H0                       = initial step size to try
3111! HMAX                     = maximum allowable step size
3112! HMIN                     = minimum allowable step size
3113! MAXORD                   = maximum allowable integration order
3114! MXSTEP                   = maximum number of integration steps
3115!                            between calls to DVODE
3116! MXHNIL                   = maximum number of printed messages
3117!                            if the T+H=T condition occurs
3118! CONSTRAINED              = array containing the indices of
3119!                            solution components which are to be
3120!                            be constrained by CLOWER and CUPPER.
3121!                            The size of CONSTRAINED must be
3122!                            positive and not exceed NEQ, the
3123!                            number of ODEs. Each component of
3124!                            CONSTRAINED must be between 1 and NEQ.
3125!   CLOWER, CUPPER         = lower and upper bound arrays for the.
3126!                            solution. Each must be the same size
3127!                            as the CONSTRAINED vector.
3128!
3129!   User-callable Routines:
3130!   The following routines may be called by the user:
3131!   SET_INTERMEDIATE_OPTS      : Used to set options for DVODE_F90
3132!   GET_STATS     : Used to gather summary integration
3133!                   statistics following a successful
3134!                   return from DVODE_F90
3135!   DVINDY        : Used if the user wishes to interpolate
3136!                   solution or derivative following a
3137!                   successful return from DVODE_F90
3138!   USERSETS_IAJA : Used if the user wishes to supply the
3139!                   sparsity structure directly
3140!   Detailed Description of SET_INTERMEDIATE_OPTS
3141!   The following are defined in SET_INTERMEDIATE_OPTS:
3142!   OPTS%MF     = Integration method flag (MF)
3143!   OPTS%METH   = Integration family flag (METH)
3144!   OPTS%MITER  = Iteration type flag (MITER)
3145!   OPTS%MOSS   = Sparsity array type flag (MOSS)
3146!   OPTS%ITOL   = Error tolerance flag (ITOL) (ITOL)
3147!   OPTS%ATOL   = Absolute error tolerance(s) (ATOL)
3148!   OPTS%RTOL   = Relative error tolerance(s) (RTOL)
3149!   OPTS%DENSE  = Use dense linear algebra
3150!   OPTS%BANDED = Use banded linear algebra
3151!   OPTS%SPARSE = Use sparse linear algebra
3152!   OPTS%IOPT   = DVODE optional parameter input flag (IOPT)
3153!   OPTS%NG     = Number of event functions
3154!   RUSER(1)    = TCRIT (don't step past)
3155!   IUSER(1)    = Jacobian lower bandwidth (ML)
3156!   IUSER(2)    = Jacobian upper bandwidth (MU)
3157!   RUSER(5)    = Initial step size to try (H0)
3158!   RUSER(6)    = Maximum allowable step size (HMAX)
3159!   RUSER(7)    = Minimum allowable step size (HMIN)
3160!   IUSER(5)    = Maximum allowable integration order (MAXORD)
3161!   IUSER(6)    = Maximum number of integration steps (MXSTEP)
3162!   IUSER(7)    = Maximum number of T+H=T messages (MXHNIL)
3163!   NZ_SWAG     = Guess for the number of nonzeros in the
3164!                 sparse Jacobian
3165!   NG          = Number of user event functions
3166!   BOUNDS,     = Nonnegativity information
3167!   NDX, IDX
3168!   YMAXWARN    = Warning flag for |y(t)| < abserr
3169!   MA28_ELBOW_ROOM = Integer multiple by which to increase
3170!                     the elbow room in the MA28 sparse work
3171!                     arrays
3172!   MC19_SCALING    = logical flag to control MC19 sparse
3173!                     scaling of the Jacobian
3174!   MA28_MESSAGES   = logical flag to control printing of MA28
3175!                     messages.
3176!   MA28_EPS        = real(wp) MA28 singularity threshold
3177!
3178!                         All Options
3179!
3180! METHOD_FLAG
3181!
3182! Default:   Not used
3183! Change to: No need to specify if use one of next three parameters
3184!            but can be changed to any value of the MF method flag
3185!            in dvode.f77
3186!
3187! DENSE_J
3188!
3189! Default:   .FALSE.
3190! Change to: .TRUE. for dense linear algebra
3191!
3192! BANDED_J
3193!
3194! Default:   .FALSE.
3195! Change to: .TRUE. for banded linear algebra
3196!
3197! SPARSE_J
3198!
3199! Default:   .FALSE.
3200! Change to: .TRUE. for sparse linear algebra
3201
3202! USER_SUPPLIED_JACOBIAN
3203!
3204! Default:   .FALSE.
3205! Change to: .TRUE. if want to supply subroutine JAC to DVODE_F90
3206!
3207! LOWER_BANDWIDTH
3208!
3209! Default:   Not used
3210! Change to: Lower bandwidth if BANDED_J = .TRUE.
3211!
3212! UPPER_BANDWIDTH
3213!
3214! Default:   Not used
3215! Change to: Upper bandwidth if BANDED_J = .TRUE.
3216!
3217! RELERR
3218!
3219! Default:   None
3220! Change to: Specify a nonzero relative error tolerance
3221!
3222! ABSERR
3223!
3224! Default:   None
3225! Change to: Specify a scalar absolute error tolerance or
3226!            a vector of absolute error tolerances
3227!
3228! ABSERR_VECTOR
3229!
3230! Default:   Not used
3231! Change to: Vector of absolute error tolerances
3232!
3233! TCRIT
3234!
3235! Default:   Not used
3236! Change to: Value of T which DVODE_F90 is not to step past
3237!
3238!     H0
3239!
3240! Default:   Determined by DVODE_F90
3241! Change to: Guess for initial step size
3242!
3243! HMAX
3244!
3245! Default:   Infinity
3246! Change to: Maximum allowable step size
3247!
3248! HMIN
3249!
3250! Default:   0.0D0
3251! Change to: Minimum allowable step size
3252!
3253! MAXORD
3254!
3255! Default:   Determined by DVODE_F90
3256! Change to: Maximum integration order
3257!
3258! MXSTEP
3259!
3260! Default:   5000
3261!     Change to: Maximum number of steps between output points
3262!
3263! MXHNIL
3264!
3265! Default:   10
3266! Change to: Maximum number of times T+H=T message will be printed
3267!
3268! NZSWAG
3269!
3270! Default:   Determined by DVODE_F90
3271! Change to: Amount by which to increment sizes of sparse arrays
3272!
3273! USER_SUPPLIED_SPARSITY
3274!
3275! Default:   .FALSE.
3276! Change to: .TRUE. if wish to call subroutine USERSETS_IAJA to
3277!            define the sparse structure array pointers directly
3278!
3279! NEVENTS
3280!
3281! Default:   0
3282! Change to: Number of event functions if wish to supply subroutine
3283!            GFUN to DVODE_F90
3284!
3285! CONSTRAINED
3286!
3287! Default:   Bounds not imposed on solution
3288! Change to: Array of indices for components on which to impose
3289!            solution bounds
3290!
3291! CLOWER
3292!
3293! Default:   Not used
3294! Change to: Vector containing lower bounds corresponding to
3295!            CONSTRAINED
3296!
3297! CUPPER
3298!
3299! Default:   Not used
3300! Change to: Vector containing upper bounds corresponding to
3301!            CONSTRAINED
3302!
3303! MA28_RPS
3304!
3305! Default:   .FALSE.
3306! Change to: Redo the MA28AD sparse pivoting sequence any time
3307!            MA28BD considers the iteration matrix to be
3308!            numerically singularity
3309!
3310!
3311! Note on Jacobian Storage Formats:
3312!
3313! If you supply an analytic Jacobian PD, load the
3314! Jacobian elements DF(I)/DY(J), the partial
3315! derivative of F(I) with respect to Y(J), using
3316! the following formats. Here, Y is the solution,
3317! F is the derivative, and PD is the Jacobian.
3318!
3319! For a full Jacobian, load PD(I,J) with DF(I)/DY(J).
3320! Your code might look like this:
3321!    DO J = 1, NEQ
3322!       DO I = 1, NEQ
3323!          PD(I,J) = ... DF(I)/DY(J)
3324!       END DO
3325!    END DO       
3326!
3327! For a banded Jacobian, load PD(I-J+MU+1,J) with
3328! DF(I)/DY(J) where ML is the lower bandwidth
3329! and MU is the upper bandwidth of the Jacobian.
3330! Your code might look like this:
3331!    DO J = 1, NEQ
3332!       I1 = MAX(1,J-ML)
3333!       I2 = MIN(N,J+MU)
3334!       DO I = I1, I2
3335!          K = I-J+MU+1
3336!          PD(K,J) = ... DF(I)/DY(J)
3337!       END DO
3338!    END DO
3339!
3340! For a sparse Jacobian, IA(J+1)-IA(J) is the number
3341! of nonzeros in column change. JA(I) indicates the
3342! rows in which the nonzeros occur. For column J,
3343! the nonzeros occurs in rows I=JA(K) for K=I1,...,I2
3344! where I1=IA(J) and I2= IA(J+1)-1. Load DF(I)/DY(J)
3345! in PD(I). Your code might look like this:
3346!    DO J = 1, NEQ
3347!       I1 = IA(J)
3348!       I2 = IA(J+1) - 1
3349!       DO K = I1, I2
3350!          I = JA(K)
3351!          PD(I) = ... DF(I)/DY(J)
3352!       END DO
3353!    END DO
3354!
3355!                    More on Sparsity Options
3356!
3357! Two facts of life regarding the use of direct sparse solvers are
3358! (1) significant improvements are possible, and (2) the use of
3359! direct sparse solvers often is more demanding of the user.
3360! Although SET_NORMAL_OPTS provides modest provisions for solving
3361! problems with sparse Jacobians, using SET_INTERMEDIATE_OPTS rather than
3362! SET_NORMAL_OPTS provides several advanced options. These options
3363! are described below. The recommended manner in which to use
3364! these options is also provided. Note that each of these optional
3365! parameters have default values and need not be specified in your
3366! call to SET_INTERMEDIATE_OPTS if you wish to use the default values. Note
3367! also that the order in which the options are specified in a call
3368! to SET_INTERMEDIATE_OPTS is not important.
3369!
3370!  (1) First determine if it is feasible to use either the BANDED
3371!      or DENSE Jacobian option.
3372!         Recommendation:
3373!         Use the DENSE or BANDED option if possible. They do
3374!         not require use of most of the options described here.
3375!   
3376!  (2) The Jacobian is approximated internally using differences
3377!      if you do not provide an analytic Jacobian. The option
3378!      USER_SUPPLIED_JACOBIAN=.TRUE. may be used if you wish to
3379!      provide an analytic Jacobian.
3380!         Recommendation:
3381!         Use an internally generated Jacobian for most problems
3382!         but consider providing an analytic Jacobian if it not
3383!         too much trouble.
3384!
3385!  (3) If you do not provide the sparse structure arrays, they
3386!      are approximated internally by making NEQ calls to your
3387!      derivative subroutine and using differences to approximate
3388!      the structure of the Jacobian. The option
3389!      USER_SUPPLIED_SPARSITY and a call to USERSETS_IAJA can
3390!      be used to supply the arrays directly. You can also use
3391!      subroutine SET_IAJA to approximate the structure using
3392!      different perturbation factors than those used in DVODE_F90.
3393!         Recommendations:
3394!         Although allowing DVODE_F90 to approximate the Jacobian
3395!         structure suffices for most problems, if you know the
3396!         sparsity pattern provide it directly. This eliminates
3397!         the possibility that an important element that happens
3398!         to be 0 when the sparsity pattern is approximated is
3399!         later nonzero; and it avoids the NEQ extra calls to
3400!         your derivative subroutine to approximate the structure.
3401!         Note that a nemesis for any sparse ode solver is a
3402!         problem in which the sparsity pattern actually changes
3403!         during the integration. An example of such a problem
3404!         is provided in the demohum21.f90 demonstration program.
3405!         If you know the sparsity pattern changes or if you
3406!         suspect it does because DVODE_F90 is generating
3407!         nonconvergence error messages, consider having DVODE_F90
3408!         re-approximate the structure by calling SET_INTERMEDIATE_OPTS and
3409!         forcing an integration restart when control is returned
3410!         to your calling program. Please do not do this at every
3411!         output point since it will be extremely time consuming
3412!         and inefficient if it is not needed.
3413!
3414!  (4) The optional parameter NZSWAG may/should be used to speed
3415!      up the determination of acceptable array sizes for the
3416!      internal sparse working arrays and the sparse Jacobian.
3417!      Initially, DVODE_F90 allocates arrays of length
3418!      max(10*NEQ,NSZSWAG) and increases this amount by
3419!      max(10*NEQ,ELBOW_ROOM*NSZSWAG) as necessary. NZSWAG
3420!      has a default value of 1000 and ELBOW_ROOM has a default
3421!      value of 2.
3422!         Recommendation:
3423!         Provide a larger value for NZSWAG particularly if NEQ
3424!         is large and you suspect considerable fill-in due to
3425!         partial pivoting.
3426!
3427!  (5) MA28BD uses the pivot sequence initially determined by
3428!      MA28AD. When a singularity is diagnosed, the internal
3429!      procedure used by the DENSE and BANDED options is used
3430!      to reduce the step size and re-calulate the iteration
3431!      matrix. This works fine for most problems; but particularly
3432!      for badly scaled problems, the solution may be unsuccessful
3433!      or it may drag along using small step sizes. This is due
3434!      to the fact MA28BD will continue to use the out-of-date pivot
3435!      sequence until singularity is again diagnosed. An option not
3436!      available in previous sparse ode solvers may be used to
3437!      instruct DVODE_F90 to force MA28AD to calculate a new pivot
3438!      sequence when MA28BD encounters a singularity. Although
3439!      MA28AD is considerably slower than MA28BD, the additional
3440!      calls to MA28AD ensure that the pivot sequence is more
3441!      up to date. This can increase both the accuracy and the
3442!      efficiency very dramatically. The demodirn.f90 demonstration
3443!      program provides an illustration of the dramatic improvement
3444!      that is possible. The optional parameter MA28_RPS may be set
3445!      .TRUE. to force these pivot sequence updates.
3446!         Recommendation:
3447!         Use the default value MA28_RPS=.FALSE; but if DVODE_F90
3448!         encounters nonconvergence, use MA28_RPS=.TRUE. to force
3449!         pivot sequence updates.
3450! ..
3451     IMPLICIT NONE
3452! ..
3453! .. Function Return Value ..
3454        TYPE (VODE_OPTS) :: OPTS
3455! ..
3456! .. Scalar Arguments ..
3457        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR, H0, HMAX, HMIN,         &
3458        RELERR, TCRIT
3459        INTEGER, OPTIONAL, INTENT (IN) :: LOWER_BANDWIDTH, MAXORD,          &
3460          MXHNIL, MXSTEP, NEVENTS, NZSWAG, UPPER_BANDWIDTH
3461        LOGICAL, OPTIONAL, INTENT (IN) :: BANDED_J, CHANGE_ONLY_f77_OPTIONS,&
3462          DENSE_J, MA28_RPS, SPARSE_J, USER_SUPPLIED_JACOBIAN,              &
3463          USER_SUPPLIED_SPARSITY
3464! ..
3465! .. Array Arguments ..
3466        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR_VECTOR(:)
3467        KPP_REAL, OPTIONAL :: CLOWER(:), CUPPER(:)
3468        INTEGER, OPTIONAL, INTENT (IN) :: CONSTRAINED(:)
3469! ..
3470! .. Local Scalars ..
3471        INTEGER ::  IER, IOPT, METH, MF, MFA, MFSIGN, MITER, ML, MOSS, MU,  &
3472          NAE, NG, NRE
3473        LOGICAL :: BANDED, DENSE, SPARSE
3474        CHARACTER (80) :: MSG
3475! ..
3476! .. Intrinsic Functions ..
3477        INTRINSIC ALLOCATED, IABS, MAX, MINVAL, PRESENT, SIGN, SIZE
3478! ..
3479! .. FIRST EXECUTABLE STATEMENT SET_INTERMEDIATE_OPTS
3480! ..
3481    RUSER(1:LRWUSER) = ZERO
3482    IUSER(1:LIWUSER) = 0
3483   
3484!   Allow default error tolerances?
3485    ALLOW_DEFAULT_TOLS = .FALSE.
3486
3487!   Maximum number of consecutive error test failures?
3488    CONSECUTIVE_EFAILS = KFH
3489
3490!   Maximum number of consecutive corrector iteration failures?
3491    CONSECUTIVE_CFAILS = MXNCF
3492
3493!   Use JACSP to approximate Jacobian?
3494    USE_JACSP = .FALSE.
3495
3496!   If only f77 options are to be changed, do it and return.
3497    IF (PRESENT(CHANGE_ONLY_f77_OPTIONS)) THEN
3498       IF (CHANGE_ONLY_f77_OPTIONS) THEN
3499          IF (.NOT.OPTS_CALLED) THEN
3500             MSG = 'You have not previously called SET_OPTS before attempting'
3501             CALL XERRDV(MSG,250,1,0,0,0,0,ZERO,ZERO)
3502             MSG = 'to change one or more of the vode.f77 optional parameters.'
3503             CALL XERRDV(MSG,250,2,0,0,0,0,ZERO,ZERO)
3504          END IF
3505          IF (PRESENT(HMAX)) THEN
3506             IOPT = 1
3507             RUSER(6) = HMAX
3508             MSG = 'HMAX changed in SET_INTERMEDIATE_OPTS.'
3509             CALL XERRDV(MSG,260,1,0,0,0,1,HMAX,ZERO)
3510          END IF
3511          IF (PRESENT(HMIN)) THEN
3512             IOPT = 1
3513             RUSER(7) = HMIN
3514             MSG = 'HMIN changed in SET_INTERMEDIATE_OPTS.'
3515             CALL XERRDV(MSG,270,1,0,0,0,1,HMIN,ZERO)
3516          END IF
3517          IF (PRESENT(TCRIT)) THEN
3518             IOPT = 1
3519             RUSER(1) = TCRIT
3520             MSG = 'TCRIT changed in SET_INTERMEDIATE_OPTS.'
3521             CALL XERRDV(MSG,280,1,0,0,0,1,TCRIT,ZERO)
3522          END IF
3523          IF (PRESENT(MXSTEP)) THEN
3524             IOPT = 1
3525             IUSER(6) = MXSTEP
3526             MSG = 'MXSTEP changed in SET_INTERMEDIATE_OPTS.'
3527             CALL XERRDV(MSG,290,1,1,MXSTEP,0,0,ZERO,ZERO)
3528          END IF
3529          IF (PRESENT(MAXORD)) THEN
3530             IOPT = 1
3531             IUSER(5) = MAXORD
3532             MSG = 'MAXORD changed in SET_INTERMEDIATE_OPTS.'
3533             CALL XERRDV(MSG,300,1,1,MAXORD,0,0,ZERO,ZERO)
3534          END IF
3535          IF (PRESENT(MXHNIL)) THEN
3536             IOPT = 1
3537             IUSER(7) = MXHNIL
3538             MSG = 'MXHNIL changed in SET_INTERMEDIATE_OPTS.'
3539             CALL XERRDV(MSG,310,1,1,MXHNIL,0,0,ZERO,ZERO)
3540          END IF
3541       END IF
3542       RETURN
3543    END IF
3544
3545!       Set the flag to indicate that SET_INTERMEDIATE_OPTS has been called.
3546        OPTS_CALLED = .TRUE.
3547
3548!       Set the MA48 storage cleanup flag.
3549        MA48_WAS_USED = .FALSE.
3550
3551!       Set the fast factor option for MA48,
3552        USE_FAST_FACTOR = .TRUE.
3553
3554!       Determine the working precision and define the value for UMAX
3555!       expected by MA28. Note that it is different for single and
3556!       double precision.
3557        WPD = KIND(1.0D0)
3558        WPS = KIND(1.0E0)
3559        IF (WPD/=WP .AND. WPS/=WP) THEN
3560          MSG = 'Illegal working precision in SET_INTERMEDIATE_OPTS.'
3561          CALL XERRDV(MSG,320,2,0,0,0,0,ZERO,ZERO)
3562        END IF
3563        IF (WPD==WP) THEN
3564!       Working precision is double.
3565          UMAX = 0.999999999_dp
3566        ELSE
3567!       Working precision is single.
3568          UMAX = 0.9999_dp
3569        END IF
3570
3571!       Set the MA28 message flag.
3572        LP = 0
3573
3574!       Set the MA28 singularity threshold.
3575        EPS = 1.0E-4_dp
3576
3577!       Set the MA28 pivot sequence frequency flag.
3578        IF (PRESENT(MA28_RPS)) THEN
3579           IF (MA28_RPS) THEN
3580              REDO_PIVOT_SEQUENCE = MA28_RPS
3581           ELSE
3582              REDO_PIVOT_SEQUENCE = .FALSE.
3583           END IF
3584        ELSE
3585           REDO_PIVOT_SEQUENCE = .FALSE.
3586        END IF
3587
3588        MA28AD_CALLS = 0
3589        MA28BD_CALLS = 0
3590        MA28CD_CALLS = 0
3591        MC19AD_CALLS = 0
3592!_______________________________________________________________________
3593! *****MA48 build change point. Insert these statements.
3594!       MA48AD_CALLS = 0
3595!       MA48BD_CALLS = 0
3596!       MA48CD_CALLS = 0
3597!_______________________________________________________________________
3598        IRNCP = 0
3599        ICNCP = 0
3600        MINIRN = 0
3601        MINICN = 0
3602        MAX_MINIRN = 0
3603        MAX_MINICN = 0
3604        MAX_NNZ = 0
3605
3606!       Set the flag to warn the user if |(y(t)| < abserr.
3607        YMAXWARN = .FALSE.
3608
3609!       Load defaults for the optional input arrays for DVODE.
3610        IUSER(1:8) = 0
3611        RUSER(1:8) = ZERO
3612
3613        IF (PRESENT(SPARSE_J)) THEN
3614          IF (SPARSE_J) THEN
3615            IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
3616              IF (USER_SUPPLIED_JACOBIAN) THEN
3617                MF = 126
3618              ELSE
3619                MF = 227
3620              END IF
3621            ELSE
3622              MF = 227
3623            END IF
3624            IF (PRESENT(USER_SUPPLIED_SPARSITY)) THEN
3625              IF (USER_SUPPLIED_SPARSITY) THEN
3626                MF = MF - 100*(MF/100)
3627              END IF
3628            END IF
3629          END IF
3630        END IF
3631
3632        IF (PRESENT(BANDED_J)) THEN
3633          IF (BANDED_J) THEN
3634            IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
3635              IF (USER_SUPPLIED_JACOBIAN) THEN
3636                MF = 24
3637              ELSE
3638                MF = 25
3639              END IF
3640            ELSE
3641              MF = 25
3642            END IF
3643          END IF
3644        END IF
3645
3646        IF (PRESENT(DENSE_J)) THEN
3647          IF (DENSE_J) THEN
3648            IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
3649              IF (USER_SUPPLIED_JACOBIAN) THEN
3650                MF = 21
3651              ELSE
3652                MF = 22
3653              END IF
3654            ELSE
3655              MF = 22
3656            END IF
3657          END IF
3658        END IF
3659
3660!       Check for errors in MF.
3661        MFA = IABS(MF)
3662        MOSS = MFA/100
3663        METH = (MFA-100*MOSS)/10
3664        MITER = MFA - 100*MOSS - 10*METH
3665        IF (METH<1 .OR. METH>2) THEN
3666          MSG = 'Illegal value of METH in SET_INTERMEDIATE_OPTS.'
3667          CALL XERRDV(MSG,330,2,0,0,0,0,ZERO,ZERO)
3668        END IF
3669        IF (MITER<0 .OR. MITER>7) THEN
3670          MSG = 'Illegal value of MITER in SET_INTERMEDIATE_OPTS.'
3671          CALL XERRDV(MSG,340,2,0,0,0,0,ZERO,ZERO)
3672        END IF
3673        IF (MOSS<0 .OR. MOSS>2) THEN
3674          MSG = 'Illegal value of MOSS in SET_INTERMEDIATE_OPTS.'
3675          CALL XERRDV(MSG,350,2,0,0,0,0,ZERO,ZERO)
3676        END IF
3677
3678!       Reset MF, now that MOSS is known.
3679        MFSIGN = SIGN(1,MF)
3680        MF = MF - 100*MOSS*MFSIGN
3681
3682        IF (MITER==0) THEN
3683          DENSE = .FALSE.
3684          BANDED = .FALSE.
3685          SPARSE = .FALSE.
3686        ELSE IF (MITER==1 .OR. MITER==2) THEN
3687          DENSE = .TRUE.
3688          BANDED = .FALSE.
3689          SPARSE = .FALSE.
3690        ELSE IF (MITER==3) THEN
3691          DENSE = .FALSE.
3692          BANDED = .FALSE.
3693          SPARSE = .FALSE.
3694        ELSE IF (MITER==4 .OR. MITER==5) THEN
3695          DENSE = .FALSE.
3696          BANDED = .TRUE.
3697          SPARSE = .FALSE.
3698        ELSE IF (MITER==6 .OR. MITER==7) THEN
3699          DENSE = .FALSE.
3700          BANDED = .FALSE.
3701          SPARSE = .TRUE.
3702        END IF
3703
3704!       Define the banded Jacobian band widths.
3705        IF (BANDED) THEN
3706          IF (PRESENT(LOWER_BANDWIDTH)) THEN
3707            ML = LOWER_BANDWIDTH
3708            IUSER(1) = ML
3709          ELSE
3710            MSG = 'In SET_INTERMEDIATE_OPTS you have indicated a'
3711            CALL XERRDV(MSG,360,1,0,0,0,0,ZERO,ZERO)
3712            MSG = 'banded Jacobian but you have not'
3713            CALL XERRDV(MSG,360,1,0,0,0,0,ZERO,ZERO)
3714            MSG = 'supplied the lower bandwidth.'
3715            CALL XERRDV(MSG,360,2,0,0,0,0,ZERO,ZERO)
3716          END IF
3717          IF (PRESENT(UPPER_BANDWIDTH)) THEN
3718            MU = UPPER_BANDWIDTH
3719            IUSER(2) = MU
3720          ELSE
3721            MSG = 'In SET_INTERMEDIATE_OPTS you have indicated a'
3722            CALL XERRDV(MSG,370,1,0,0,0,0,ZERO,ZERO)
3723            MSG = 'banded Jacobian but you have not'
3724            CALL XERRDV(MSG,370,1,0,0,0,0,ZERO,ZERO)
3725            MSG = 'supplied the upper bandwidth.'
3726            CALL XERRDV(MSG,370,2,0,0,0,0,ZERO,ZERO)
3727          END IF
3728!         Define the nonzero diagonals.
3729          BNGRP = 0
3730          SUBS = .FALSE.
3731          SUPS = .FALSE.
3732          NSUBS  = 0
3733          NSUPS = 0
3734        END IF
3735
3736!       Define the sparse Jacobian options.
3737        SCALE_MATRIX = .FALSE.
3738        ELBOW_ROOM = 2
3739        IF (SPARSE) THEN
3740!         NZSWAG for the number of nonzeros in the Jacobian.
3741          IF (PRESENT(NZSWAG)) THEN
3742            NZ_SWAG = MAX(NZSWAG,0)
3743          ELSE
3744            NZ_SWAG = 0
3745          END IF
3746!         Indicate that SET_IAJA has not yet been called successfully.
3747          IAJA_CALLED = .FALSE.
3748!         Check for illegal method flags.
3749          IF (MOSS==2 .AND. MITER/=7) THEN
3750            MSG = 'In SET_INTERMEDIATE_OPTS MOSS=2 but MITER is not 7.'
3751            CALL XERRDV(MSG,380,2,0,0,0,0,ZERO,ZERO)
3752          END IF
3753          IF (MOSS==1 .AND. MITER/=6) THEN
3754            MSG = 'In SET_INTERMEDIATE_OPTS MOSS=1 but MITER is not 6.'
3755            CALL XERRDV(MSG,390,2,0,0,0,0,ZERO,ZERO)
3756          END IF
3757!         IF (MOSS==0 .AND. MITER/=7) THEN
3758!           MSG = 'In SET_INTERMEDIATE_OPTS MOSS=0 but MITER is not 7.'
3759!           CALL XERRDV(MSG,400,2,0,0,0,0,ZERO,ZERO)
3760!         END IF
3761!         Allow MC19 scaling for the Jacobian.
3762          SCALE_MATRIX = .FALSE.
3763        END IF
3764
3765!       Define the number of event functions.
3766        IF (PRESENT(NEVENTS)) THEN
3767          IF (NEVENTS>0) THEN
3768            NG = NEVENTS
3769          ELSE
3770            NG = 0
3771          END IF
3772        ELSE
3773          NG = 0
3774        END IF
3775
3776!       Process the constrained solution components.
3777        IF (PRESENT(CONSTRAINED)) THEN
3778          NDX = SIZE(CONSTRAINED)
3779          IF (NDX<1) THEN
3780            MSG = 'In SET_INTERMEDIATE_OPTS the size of CONSTRAINED < 1.'
3781            CALL XERRDV(MSG,410,2,0,0,0,0,ZERO,ZERO)
3782          END IF
3783          IF (.NOT.(PRESENT(CLOWER)) .OR. .NOT.(PRESENT(CUPPER))) THEN
3784            MSG = 'In SET_INTERMEDIATE_OPTS the arrays CLOWER and CUPPER'
3785            CALL XERRDV(MSG,420,1,0,0,0,0,ZERO,ZERO)
3786            MSG = 'are not present.'
3787            CALL XERRDV(MSG,420,2,0,0,0,0,ZERO,ZERO)
3788          END IF
3789          IF (SIZE(CLOWER)/=NDX .OR. SIZE(CUPPER)/=NDX) THEN
3790            MSG = 'In SET_INTERMEDIATE_OPTS the size of the solution bound'
3791            CALL XERRDV(MSG,430,1,0,0,0,0,ZERO,ZERO)
3792            MSG = 'arrays must be the same as the CONSTRAINED array.'
3793            CALL XERRDV(MSG,430,2,0,0,0,0,ZERO,ZERO)
3794          END IF
3795!         Note: The contents of CONSTRAINED will be checked
3796!         in subroutine DVODE after NEQ is known.
3797          IF (ALLOCATED(IDX)) THEN
3798            DEALLOCATE (IDX,LB,UB,STAT=IER)
3799            CALL CHECK_STAT(IER,30)
3800          END IF
3801          ALLOCATE (IDX(NDX),LB(NDX),UB(NDX),STAT=IER)
3802          CALL CHECK_STAT(IER,40)
3803          IDX(1:NDX) = CONSTRAINED(1:NDX)
3804          LB(1:NDX) = CLOWER(1:NDX)
3805          UB(1:NDX) = CUPPER(1:NDX)
3806          BOUNDS = .TRUE.
3807        ELSE
3808          IF (ALLOCATED(IDX)) THEN
3809            DEALLOCATE (IDX,LB,UB,STAT=IER)
3810            CALL CHECK_STAT(IER,50)
3811          END IF
3812          NDX = 0
3813          BOUNDS = .FALSE.
3814        END IF
3815
3816!       Is the Jacobian constant?
3817        J_IS_CONSTANT = .FALSE.
3818        J_HAS_BEEN_COMPUTED = .FALSE.
3819
3820!       Load the user options into the solution structure.
3821        OPTS%MF = MF
3822        OPTS%METH = METH
3823        OPTS%MITER = MITER
3824        OPTS%MOSS = MOSS
3825        OPTS%DENSE = DENSE
3826        OPTS%BANDED = BANDED
3827        OPTS%SPARSE = SPARSE
3828        OPTS%NG = NG
3829
3830!       Process the miscellaneous options.
3831
3832!       Don't step past TCRIT variable.
3833        IF (PRESENT(TCRIT)) THEN
3834          RUSER(1) = TCRIT
3835        ELSE
3836          RUSER(1) = ZERO
3837        END IF
3838
3839!       DVODE optional parameters.
3840        IOPT = 1
3841        IF (PRESENT(MAXORD)) THEN
3842          IUSER(5) = MAXORD
3843          IOPT = 1
3844        END IF
3845        IF (PRESENT(MXSTEP)) THEN
3846          IUSER(6) = MXSTEP
3847          IOPT = 1
3848        END IF
3849        IF (PRESENT(MXHNIL)) THEN
3850          IUSER(7) = MXHNIL
3851          IOPT = 1
3852        END IF
3853        IF (PRESENT(H0)) THEN
3854          RUSER(5) = H0
3855          IOPT = 1
3856        END IF
3857        IF (PRESENT(HMAX)) THEN
3858          RUSER(6) = HMAX
3859          IOPT = 1
3860        END IF
3861        IF (PRESENT(HMIN)) THEN
3862          RUSER(7) = HMIN
3863          IOPT = 1
3864        END IF
3865        U_PIVOT = ONE
3866        OPTS%IOPT = IOPT
3867
3868!       Define the error tolerances.
3869
3870!       Relative error tolerances.
3871        NRE = 1
3872        ALLOCATE (OPTS%RTOL(NRE),STAT=IER)
3873        CALL CHECK_STAT(IER,60)
3874        IF (PRESENT(RELERR)) THEN
3875          IF (RELERR<ZERO) THEN
3876            MSG = 'RELERR must be nonnegative.'
3877            CALL XERRDV(MSG,440,2,0,0,0,0,ZERO,ZERO)
3878          END IF
3879          OPTS%RTOL = RELERR
3880        ELSE
3881          IF (ALLOW_DEFAULT_TOLS) THEN
3882             OPTS%RTOL = 1.0E-4_dp
3883             MSG = 'By not specifying RELERR, you have elected to use a default'
3884             CALL XERRDV(MSG,450,1,0,0,0,0,ZERO,ZERO)
3885             MSG = 'relative error tolerance equal to 1.0D-4. Please be aware a'
3886             CALL XERRDV(MSG,450,1,0,0,0,0,ZERO,ZERO)
3887             MSG = 'tolerance this large is not appropriate for all problems.'
3888             CALL XERRDV(MSG,450,1,0,0,0,0,ZERO,ZERO)
3889             MSG = 'Execution will continue'
3890             CALL XERRDV(MSG,450,1,0,0,0,0,ZERO,ZERO)
3891          ELSE
3892             MSG = 'You must specify a nonzero relative error tolerance.'
3893             CALL XERRDV(MSG,460,2,0,0,0,0,ZERO,ZERO)
3894          END IF
3895        END IF
3896
3897!       Absolute error tolerances.
3898        IF (PRESENT(ABSERR_VECTOR)) THEN
3899          IF (MINVAL(ABSERR_VECTOR)<ZERO) THEN
3900            MSG = 'All components of ABSERR_VECTOR must'
3901            CALL XERRDV(MSG,460,1,0,0,0,0,ZERO,ZERO)
3902            MSG = 'be nonnegative.'
3903            CALL XERRDV(MSG,460,2,0,0,0,0,ZERO,ZERO)
3904          END IF
3905          NAE = SIZE(ABSERR_VECTOR)
3906        ELSE
3907          NAE = 1
3908        END IF
3909        ALLOCATE (OPTS%ATOL(NAE),STAT=IER)
3910        CALL CHECK_STAT(IER,70)
3911        IF (PRESENT(ABSERR_VECTOR)) THEN
3912          OPTS%ATOL = ABSERR_VECTOR
3913        ELSE IF (PRESENT(ABSERR)) THEN
3914          IF (ABSERR<ZERO) THEN
3915            MSG = 'ABSERR must be nonnegative.'
3916            CALL XERRDV(MSG,470,2,0,0,0,0,ZERO,ZERO)
3917          END IF
3918          OPTS%ATOL = ABSERR
3919        ELSE
3920          IF (ALLOW_DEFAULT_TOLS) THEN
3921             OPTS%ATOL = 1D-6
3922             MSG = 'By not specifying ABSERR, you have elected to use a default'
3923             CALL XERRDV(MSG,480,1,0,0,0,0,ZERO,ZERO)
3924             MSG = 'absolute error tolerance equal to 1.0D-6. Please be aware a'
3925             CALL XERRDV(MSG,480,1,0,0,0,0,ZERO,ZERO)
3926             MSG = 'tolerance this large is not appropriate for all problems.'
3927             CALL XERRDV(MSG,480,1,0,0,0,0,ZERO,ZERO)
3928             MSG = 'Execution will continue'
3929             CALL XERRDV(MSG,480,1,0,0,0,0,ZERO,ZERO)
3930          ELSE
3931             MSG = 'You must specify a vector of absolute error tolerances or'
3932             CALL XERRDV(MSG,490,1,0,0,0,0,ZERO,ZERO)
3933             MSG = 'a scalar error tolerance. It is recommended that you use'
3934             CALL XERRDV(MSG,490,1,0,0,0,0,ZERO,ZERO)
3935             MSG = 'a vector of absolute error tolerances.'
3936             CALL XERRDV(MSG,490,2,0,0,0,0,ZERO,ZERO)
3937          END IF
3938        END IF
3939
3940!       ITOL error tolerance flag.
3941!          ITOL   RTOL     ATOL            EWT(i)
3942!            1   scalar   scalar  RTOL*ABS(Y(i)) + ATOL
3943!            2   scalar   array   RTOL*ABS(Y(i)) + ATOL(i)
3944!            3   array    scalar  RTOL(i)*ABS(Y(i)) + ATOL
3945!            4   array    array   RTOL(i)*ABS(Y(i)) + ATOL(i)
3946        IF (PRESENT(ABSERR_VECTOR)) THEN
3947          OPTS%ITOL = 2
3948        ELSE
3949          OPTS%ITOL = 1
3950        END IF
3951        RETURN
3952
3953  END FUNCTION SET_INTERMEDIATE_OPTS
3954!_______________________________________________________________________
3955
3956  FUNCTION SET_OPTS(METHOD_FLAG, DENSE_J, BANDED_J, SPARSE_J,          &
3957    USER_SUPPLIED_JACOBIAN, SAVE_JACOBIAN, CONSTANT_JACOBIAN,          &
3958    LOWER_BANDWIDTH, UPPER_BANDWIDTH, SUB_DIAGONALS, SUP_DIAGONALS,    &
3959    RELERR, RELERR_VECTOR, ABSERR, ABSERR_VECTOR, TCRIT, H0, HMAX,     &
3960    HMIN, MAXORD, MXSTEP, MXHNIL, YMAGWARN, SETH, UPIVOT, NZSWAG,      &
3961    USER_SUPPLIED_SPARSITY, NEVENTS, CONSTRAINED, CLOWER, CUPPER,      &
3962    MA28_ELBOW_ROOM, MC19_SCALING, MA28_MESSAGES, MA28_EPS,            &
3963    MA28_RPS, CHANGE_ONLY_f77_OPTIONS,JACOBIAN_BY_JACSP)               &
3964  RESULT(OPTS)
3965
3966! FUNCTION SET_OPTS:
3967!    VODE.f77 method flag:
3968!       METHOD_FLAG
3969!    Jacobian type:
3970!       DENSE_J, BANDED_J, SPARSE_J
3971!    Analytic Jacobian:
3972!       USER_SUPPLIED_JACOBIAN
3973!    Jacobian options:
3974!       SAVE_JACOBIAN, CONSTANT_JACOBIAN. JACOBIAN_BY_JACSP
3975!    If banded Jacobian:
3976!       LOWER_BANDWIDTH, UPPER_BANDWIDTH
3977!    If specify the nonzero diagonals for banded Jacobian:
3978!       SUB_DIAGONALS, SUP_DIAGONALS
3979!    Error tolerances:
3980!       RELERR, RELERR_VECTOR, ABSERR, ABSERR_VECTOR
3981!    VODE.f77 optional parameters:
3982!       TCRIT, H0, HMAX, HMIN, MAXORD, MXSTEP, MXHNIL
3983!    Solution smaller than absolute error tolerance:
3984!       YMAGWARN
3985!    Sparse flags:
3986!       SETH, UPIVOT, NZSWAG, USER_SUPPLIED_SPARSITY
3987!       MA28_ELBOW_ROOM, MC19_SCALING, MA28_MESSAGES
3988!       MA28_EPS, MA28_RPS
3989!    Rootfinding:
3990!       NEVENTS
3991!    Impose bounds on solution:
3992!       CONSTRAINED, CLOWER, CUPPER
3993!    Change one or more of HMAX, HMIN, TCRIT, MXSTEP, MXHNIL, MAXORD
3994!       CHANGE_ONLY_f77_OPTIONS
3995! RESULT(OPTS)
3996
3997! SET_OPTIONS sets user parameters for DVODE via keywords. Values that
3998! are defined herein will be used internally by DVODE. All option
3999! keywords are OPTIONAL and order is not important.
4000
4001! Note that DVODE_F90 requires that one of SET_NORMAL_OPTS or
4002! SET_INTERMEDIATE_OPTS or SET_OPTS is called before the first
4003! time DVODE_F90 is called.
4004
4005!                     Quick Summary of Options
4006
4007! METHOD_FLAG            - any legal value of MF as in DVODE
4008! DENSE_J                - Jacobian is sparse alternative to MF
4009! BANDED_J               - Jacobian is banded alternative to MF
4010! SPARSE_J               - Jacobian is sparse alternative to MF   
4011! USER_SUPPLIED_JACOBIAN - User will supply Jacobian subroutine
4012!                          (user supplied subroutine JAC required)
4013! SAVE_JACOBIAN          - Jacobian will be saved and reused
4014! CONSTANT_JACOBIAN      - Jacobian is constant
4015! JACOBIAN_BY_JACSP      - Use Doug Salane's approximate Jacobian
4016!                          algorithm
4017! LOWER_BANDWIDTH        - Lower bandwidth ML in DVODE
4018! UPPER_BANDWIDTH        - Upper bandwidth MU in DVODE
4019! SUB_DIAGONALS          - Nonzero sub diagonals in Jacobian
4020! SUP_DIAGONALS          - Nonzero super diagonals in Jacobian
4021! RELERR                 - Scalar relative error tolerance in DVODE
4022! RELERR_VECTOR          - Vector relative error tolerance in DVODE
4023! ABSERR                 - Scalar absolute error tolerance in DVODE
4024! ABSERR_VECTOR          - Vector absolute error tolerance in DVODE
4025! TCRIT                  - Critical time TCRIT in DVODE
4026! H0                     - Starting step size in DVODE
4027! HMAX                   - Maximum step size in DVODE
4028! HMIN                   - Minimum step size in DVODE
4029! MAXORD                 - Maximum integration order in DVODE
4030! MXSTEP                 - Maximum number of integration steps
4031!                          in DVODE
4032! MXHNIL                 - Maximum number of T+H=T messages in DVODE
4033! YMAGWARN               - Warn if magnitude of solution is smaller
4034!                          than absolute error tolerance
4035! SETH                   - Sparse Jacobian element threshold value
4036! UPIVOT                 - MA28 partial pivoting parameter
4037! NZSWAG                 - guess for the number of nonzeros in sparse
4038!                          Jacobian
4039! USER_SUPPLIED_SPARSITY - user will supply sparsity structure
4040!                          arrays by calling USERSETS_IAJA
4041! MA28_ELBOW_ROOM        - Supply an integer greater than 2 if you
4042!                          wish to increase the elbow room in the
4043!                          MA28 work arrays (by MA28_ELBOW_ROOM * NZA).
4044! MC19_SCALING           - .TRUE. if you wish to invoke sparse scaling
4045!                           of the Jacobian.
4046! MA28_MESSAGES          - Control printing of MA28 messages
4047! MA28_RPS               - Redo MA28AD pivot sequence if a singularity
4048!                          is encountered
4049! NEVENTS                - number of user defined root finding functions
4050!                          (user supplied subroutine G required)
4051! CONSTRAINED,           - array of solution component indices that
4052! CLOWER,                  are to be constrained by the lower and
4053! CUPPER                   upper bound arrays CLOWER and CUPPER so that
4054!                          CLOWER(I) <= Y(CONSTRAINED(I)) <= CUPPER(I)
4055! CHANGE_ONLY_f77_OPTIONS- flag to indicate whether to only change any
4056!                          of the parameters MXSTEP, MXHNIL, MAXORD,
4057!                          HMAX, HMIN, TCRIT
4058!                     Options Types
4059! METHOD_FLAG            - integer
4060! DENSE_J                - logical
4061! BANDED_J               - logical
4062! SPARSE_J               - logical
4063! USER_SUPPLIED_JACOBIAN - logical
4064! SAVE_JACOBIAN          - logical
4065! CONSTANT_JACOBIAN      - logical
4066! JACOBIAN_BY_JACSP      - logical
4067! LOWER_BANDWIDTH        - integer
4068! UPPER_BANDWIDTH        - integer
4069! SUB_DIAGONALS          - integer array
4070! SUP_DIAGONALS          - integer array
4071! RELERR                 - real(wp) scalar
4072! RELERR_VECTOR          - real(wp) vector
4073! ABSERR                 - real(wp) scalar
4074! ABSERR_VECTOR          - real(wp) vector
4075! TCRIT                  - real(wp) scalar
4076! H0                     - real(wp) scalar
4077! HMAX                   - real(wp) scalar
4078! HMIN                   - real(wp) scalar
4079! MAXORD                 - integer
4080! MXSTEP                 - integer
4081! MXHNIL                 - integer
4082! YMAGWARN               - logical
4083! SETH                   - real(wp) scalar
4084! UPIVOT                 - real(wp) scalar
4085! NZSWAG                 - integer
4086! USER_SUPPLIED_SPARSITY - logical
4087! NEVENTS                - integer
4088! CONSTRAINED            - integer array
4089! CLOWER                 - real(wp) array
4090! CUPPER                 - real(wp) array
4091! CHANGE_ONLY_f77_OPTIONS- logical
4092
4093! Argument list parameters:
4094! METHOD_FLAG              = integration method flag
4095! ABSERR                   = scalar absolute error tolerance
4096! ABSERR_VECTOR            = vector of absolute error tolerances
4097! RELERR                   = scalar relative error tolerance
4098! RELERR_VECTOR            = vector of relative error tolerances
4099! NEVENTS                  = Number of event functions (requires
4100!                            user-supplied GFUN)
4101! DENSE_J                  = use dense linear algebra if .TRUE.
4102! BANDED_J                 = use banded linear algebra if .TRUE.
4103!   LOWER_BANDWIDTH        = lower bandwidth of the Jacobian
4104!                            (required if BANDED_J = .TRUE.)
4105!   UPPER_BANDWIDTH        = upper bandwidth of the Jacobian
4106!                            (required if BANDED_J = .TRUE.)
4107!   SUB_DIAGONALS          = starting row numbers of nonzero sub
4108!                            diagonals counting up from the lowest
4109!                            sub diagonal
4110!   SUP_DIAGONALS          = starting column numbers of nonzero
4111!                            super diagonals counting up from the
4112!                            lowest super diagonal
4113! SPARSE_J                 = use sparse linear algebra if .TRUE.
4114!   UPIVOT                 = partial pivot control flag (default=ONE)
4115!                          = 0.0D0 for no partial pivoting
4116!                          = ONE for (full) partial pivoting
4117!                            Values between 0.0D0 and ONE yield
4118!                            MA28 (partial) partial pivoting.
4119!   NZSWAG                 = If you wish you may supply a guess,
4120!                            NZSWAG, at the number of nonzeros
4121!                            in the Jacobian matrix. In some cases
4122!                            this will speed up the determination
4123!                            of the necessary storage.
4124!   USER_SUPPLIED_SPARSITY = .TRUE. if you wish to supply the sparsity
4125!                            structure arrays directly by calling
4126!                            USERSETS_IAJA
4127!   MA28_ELBOW_ROOM        = Supply an integer greater than 2 if you
4128!                            wish to increase the elbow room in the
4129!                            MA28 work arrays (by MA28_ELBOW_ROOM * NZA).
4130!   MC19_SCALING           = .TRUE. if you wish to invoke sparse scaling
4131!                            of the Jacobian.
4132!   MA28_MESSAGES          = .TRUE. to print all MA28 messages.
4133!   MA28_EPS               = MA28 singularity threshold. If MA28BD
4134!                            determines that the ratio of the current
4135!                            pivot to the largest element in the row
4136!                            is smaller than EPS, it will flag the
4137!                            Jacobian as singular and force MA28AD
4138!                            to calculate a new pivot sequence.
4139!   MA28_RPS               = .TRUE. to force MA28AD to calculate a new
4140!                            pivot sequence for use in MA28BD if a
4141!                            singular iteration matrix is encountered
4142!                            is smaller than EPS, it will flag the
4143!                            Jacobian as singular and force MA28AD
4144!                            to calculate a new pivot sequence.
4145! USER_SUPPLIED_JACOBIAN   = exact Jacobian option
4146!                            (requires user-supplied JAC)
4147! SAVE_JACOBIAN            = reuse saved Jacobians
4148! JACOBIAN_BY_JACSP        = use Doug Salane's Jacobian algorithm
4149! TCRIT                    = critical time
4150! H0                       = initial step size to try
4151! HMAX                     = maximum allowable step size
4152! HMIN                     = minimum allowable step size
4153! MAXORD                   = maximum allowable integration order
4154! MXSTEP                   = maximum number of integration steps
4155!                            between calls to DVODE
4156! MXHNIL                   = maximum number of printed messages
4157!                            if the T+H=T condition occurs
4158! CONSTRAINED              = array containing the indices of
4159!                            solution components which are to be
4160!                            be constrained by CLOWER and CUPPER.
4161!                            The size of CONSTRAINED must be
4162!                            positive and not exceed NEQ, the
4163!                            number of ODEs. Each component of
4164!                            CONSTRAINED must be between 1 and NEQ.
4165! CLOWER, CUPPER           = lower and upper bound arrays for the.
4166!                            solution. Each must be the same size
4167!                            as the CONSTRAINED vector.
4168! YMAGWARN                 = If .TRUE., a warning will be issued
4169!                            before any return from DVODE for any
4170!                            solution component whose magnitude
4171!                            is smaller than the absolute error
4172!                            tolerance for that component.
4173!   User-callable Routines:
4174!   The following routines may be called by the user:
4175!   SET_OPTS      : Used to set options for DVODE_F90
4176!   GET_STATS     : Used to gather summary integration
4177!                   statistics following a successful
4178!                   return from DVODE_F90
4179!   DVINDY        : Used if the user wishes to interpolate
4180!                   solution or derivative following a
4181!                   successful return from DVODE_F90
4182!   USERSETS_IAJA : Used if the user wishes to supply the
4183!                   sparsity structure directly
4184!   Detailed Description of SET_OPTS
4185!   The following are defined in SET_OPTS:
4186!   OPTS%MF     = Integration method flag (MF)
4187!   OPTS%METH   = Integration family flag (METH)
4188!   OPTS%MITER  = Iteration type flag (MITER)
4189!   OPTS%MOSS   = Sparsity array type flag (MOSS)
4190!   OPTS%ITOL   = Error tolerance flag (ITOL) (ITOL)
4191!   OPTS%ATOL   = Absolute error tolerance(s) (ATOL)
4192!   OPTS%RTOL   = Relative error tolerance(s) (RTOL)
4193!   OPTS%DENSE  = Use dense linear algebra
4194!   OPTS%BANDED = Use banded linear algebra
4195!   OPTS%SPARSE = Use sparse linear algebra
4196!   OPTS%IOPT   = DVODE optional parameter input flag (IOPT)
4197!   OPTS%NG     = Number of event functions
4198!   RUSER(1)    = TCRIT (don't step past)
4199!   IUSER(1)    = Jacobian lower bandwidth (ML)
4200!   IUSER(2)    = Jacobian upper bandwidth (MU)
4201!   RUSER(5)    = Initial step size to try (H0)
4202!   RUSER(6)    = Maximum allowable step size (HMAX)
4203!   RUSER(7)    = Minimum allowable step size (HMIN)
4204!   IUSER(5)    = Maximum allowable integration order (MAXORD)
4205!   IUSER(6)    = Maximum number of integration steps (MXSTEP)
4206!   IUSER(7)    = Maximum number of T+H=T messages (MXHNIL)
4207!   NZ_SWAG     = Guess for the number of nonzeros in the
4208!                 sparse Jacobian
4209!   NG          = Number of user event functions
4210!   BOUNDS,     = Nonnegativity information
4211!   NDX, IDX
4212!   YMAXWARN    = Warning flag for |y(t)| < abserr
4213!   MA28_ELBOW_ROOM = Integer multiple by which to increase
4214!                     the elbow room in the MA28 sparse work
4215!                     arrays
4216!   MC19_SCALING    = logical flag to control MC19 sparse
4217!                     scaling of the Jacobian
4218!   MA28_MESSAGES   = logical flag to control printing of MA28
4219!                     messages.
4220!   MA28_EPS        = real(wp) MA28 singularity threshold
4221!
4222!                         All Options
4223!
4224! METHOD_FLAG
4225!
4226! Default:   Not used
4227! Change to: No need to specify if use one of next three parameters
4228!            but can be changed to any value of the MF method flag
4229!            in dvode.f77
4230!
4231! DENSE_J
4232!
4233! Default:   .FALSE.
4234! Change to: .TRUE. for dense linear algebra
4235!
4236! BANDED_J
4237!
4238! Default:   .FALSE.
4239! Change to: .TRUE. for banded linear algebra
4240!
4241! SPARSE_J
4242!
4243! Default:   .FALSE.
4244! Change to: .TRUE. for sparse linear algebra
4245
4246! USER_SUPPLIED_JACOBIAN
4247!
4248! Default:   .FALSE.
4249! Change to: .TRUE. if want to supply subroutine JAC to DVODE_F90
4250!
4251! SAVE_JACOBIAN
4252!
4253! Default:   .TRUE.
4254! Change to: .FALSE. if do not want DVODE_F90 to reuse saved
4255!            Jacobians
4256!
4257! JACOBIAN_BY_JACSP
4258!
4259! Default:   .FALSE.
4260! Change to: .TRUE. to approximate the Jacobian using Doug Salane's
4261!            JACSP Jacobian subroutine
4262!
4263! CONSTANT_JACOBIAN
4264!
4265! Default:   .FALSE.
4266! Change to: .TRUE. if Jacobian is constant
4267!
4268! LOWER_BANDWIDTH
4269!
4270! Default:   Not used
4271! Change to: Lower bandwidth if BANDED_J = .TRUE.
4272!
4273! UPPER_BANDWIDTH
4274!
4275! Default:   Not used
4276! Change to: Upper bandwidth if BANDED_J = .TRUE.
4277!
4278! SUB_DIAGONALS
4279!
4280! Default:   Not used
4281! Change to: Starting row locations for sub diagonals in
4282!            banded Jacobian
4283!
4284! SUP_DIAGONALS
4285!
4286! Default:   Not used
4287! Change to: Starting columns locations for super diagonals
4288!            in banded Jacobian
4289!
4290! RELERR
4291!
4292! Default:   None
4293! Change to: Specify a nonzero relative error tolerance
4294!
4295! RELERR_VECTOR
4296!
4297! Default:   Not used
4298! Change to: Vector of relative error tolerances
4299!
4300! ABSERR
4301!
4302! Default:   None
4303! Change to: Specify a scalar absolute error tolerance or
4304!            a vector of absolute error tolerances
4305!
4306! ABSERR_VECTOR
4307!
4308! Default:   Not used
4309! Change to: Vector of absolute error tolerances
4310!
4311! TCRIT
4312!
4313! Default:   Not used
4314! Change to: Value of T which DVODE_F90 is not to step past
4315!
4316!     H0
4317!
4318! Default:   Determined by DVODE_F90
4319! Change to: Guess for initial step size
4320!
4321! HMAX
4322!
4323! Default:   Infinity
4324! Change to: Maximum allowable step size
4325!
4326! HMIN
4327!
4328! Default:   0.0D0
4329! Change to: Minimum allowable step size
4330!
4331! MAXORD
4332!
4333! Default:   Determined by DVODE_F90
4334! Change to: Maximum integration order
4335!
4336! MXSTEP
4337!
4338! Default:   5000
4339!     Change to: Maximum number of steps between output points
4340!
4341! MXHNIL
4342!
4343! Default:   10
4344! Change to: Maximum number of times T+H=T message will be printed
4345!
4346! YMAGWARN
4347!
4348! Default:   .FALSE.
4349! Change to: .TRUE. if wish to be warned when the magnitude of the
4350!            solution is smaller than the absolute error tolerance
4351!
4352! SETH
4353!
4354! Default:   0.0D0
4355! Change to: Threshold value below which Jacobian elements in the
4356!            sparse Jacobian are considered to be zero
4357!
4358! UPIVOT
4359!
4360! Default:   1.0D0
4361! Change to: partial pivoting factor between 0.0d0 and 1.0d0 to
4362!            control the degree of partial pivoting used in sparse
4363!            Gaussian Elimination
4364!
4365! NZSWAG
4366!
4367! Default:   Determined by DVODE_F90
4368! Change to: Amount by which to increment sizes of sparse arrays
4369!
4370! USER_SUPPLIED_SPARSITY
4371!
4372! Default:   .FALSE.
4373! Change to: .TRUE. if wish to call subroutine USERSETS_IAJA to
4374!            define the sparse structure array pointers directly
4375!
4376! NEVENTS
4377!
4378! Default:   0
4379! Change to: Number of event functions if wish to supply subroutine
4380!            GFUN to DVODE_F90
4381!
4382! CONSTRAINED
4383!
4384! Default:   Bounds not imposed on solution
4385! Change to: Array of indices for components on which to impose
4386!            solution bounds
4387!
4388! CLOWER
4389!
4390! Default:   Not used
4391! Change to: Vector containing lower bounds corresponding to
4392!            CONSTRAINED
4393!
4394! CUPPER
4395!
4396! Default:   Not used
4397! Change to: Vector containing upper bounds corresponding to
4398!            CONSTRAINED
4399!
4400! MA28_ELBOW_ROOM
4401!
4402! Default:   2
4403! Change to: Larger value to allow the sparse arrays more
4404!            elbow room
4405!
4406! MC19_SCALING
4407!
4408! Default:   .FALSE.
4409! Change to: .TRUE. to invoke scaling of the sparse solution
4410!
4411! MA28_MESSAGES
4412!
4413! Default:   .FALSE.
4414! Change to: .TRUE. to have MA28 diagnostic messages written
4415!            to unit 6
4416!
4417! MA28_EPS
4418!
4419! Default:   1.0D-4
4420! Change to: Smaller positive value to allow the ratio of the
4421!            magnitude of pivot elements and remaining row
4422!            entries to be smaller before the iteration matrix
4423!            is considered to be numerically singularity
4424!
4425! MA28_RPS
4426!
4427! Default:   .FALSE.
4428! Change to: Redo the MA28AD sparse pivoting sequence any time
4429!            MA28BD considers the iteration matrix to be
4430!            numerically singularity
4431!
4432! Note on Jacobian Storage Formats:
4433!
4434! If you supply an analytic Jacobian PD, load the
4435! Jacobian elements DF(I)/DY(J), the partial
4436! derivative of F(I) with respect to Y(J), using
4437! the following formats. Here, Y is the solution,
4438! F is the derivative, and PD is the Jacobian.
4439!
4440! For a full Jacobian, load PD(I,J) with DF(I)/DY(J).
4441! Your code might look like this:
4442!    DO J = 1, NEQ
4443!       DO I = 1, NEQ
4444!          PD(I,J) = ... DF(I)/DY(J)
4445!       END DO
4446!    END DO       
4447!
4448! For a banded Jacobian, load PD(I-J+MU+1,J) with
4449! DF(I)/DY(J) where ML is the lower bandwidth
4450! and MU is the upper bandwidth of the Jacobian.
4451! Your code might look like this:
4452!    DO J = 1, NEQ
4453!       I1 = MAX(1,J-ML)
4454!       I2 = MIN(N,J+MU)
4455!       DO I = I1, I2
4456!          K = I-J+MU+1
4457!          PD(K,J) = ... DF(I)/DY(J)
4458!       END DO
4459!    END DO
4460!
4461! For a sparse Jacobian, IA(J+1)-IA(J) is the number
4462! of nonzeros in column change. JA(I) indicates the
4463! rows in which the nonzeros occur. For column J,
4464! the nonzeros occurs in rows I=JA(K) for K=I1,...,I2
4465! where I1=IA(J) and I2= IA(J+1)-1. Load DF(I)/DY(J)
4466! in PD(I). Your code might look like this:
4467!    DO J = 1, NEQ
4468!       I1 = IA(J)
4469!       I2 = IA(J+1) - 1
4470!       DO K = I1, I2
4471!          I = JA(K)
4472!          PD(I) = ... DF(I)/DY(J)
4473!       END DO
4474!    END DO
4475!
4476!                    More on Sparsity Options
4477!
4478! Two facts of life regarding the use of direct sparse solvers are
4479! (1) significant improvements are possible, and (2) the use of
4480! direct sparse solvers often is more demanding of the user.
4481! Although SET_NORMAL_OPTS provides modest provisions for solving
4482! problems with sparse Jacobians, using SET_OPTS rather than
4483! SET_NORMAL_OPTS provides several advanced options. These options
4484! are described below. The recommended manner in which to use
4485! these options is also provided. Note that each of these optional
4486! parameters have default values and need not be specified in your
4487! call to SET_OPTS if you wish to use the default values. Note
4488! also that the order in which the options are specified in a call
4489! to SET_OPTS is not important.
4490!
4491!  (1) First determine if it is feasible to use either the BANDED
4492!      or DENSE Jacobian option.
4493!         Recommendation:
4494!         Use the DENSE or BANDED option if possible. They do
4495!         not require use of most of the options described here.
4496!   
4497!  (2) The Jacobian is approximated internally using differences
4498!      if you do not provide an analytic Jacobian. The option
4499!      USER_SUPPLIED_JACOBIAN=.TRUE. may be used if you wish to
4500!      provide an analytic Jacobian.
4501!         Recommendation:
4502!         Use an internally generated Jacobian for most problems
4503!         but consider providing an analytic Jacobian if it not
4504!         too much trouble.
4505!
4506!  (3) If you do not provide the sparse structure arrays, they
4507!      are approximated internally by making NEQ calls to your
4508!      derivative subroutine and using differences to approximate
4509!      the structure of the Jacobian. The option
4510!      USER_SUPPLIED_SPARSITY and a call to USERSETS_IAJA can
4511!      be used to supply the arrays directly. You can also use
4512!      subroutine SET_IAJA to approximate the structure using
4513!      different perturbation factors than those used in DVODE_F90.
4514!         Recommendations:
4515!         Although allowing DVODE_F90 to approximate the Jacobian
4516!         structure suffices for most problems, if you know the
4517!         sparsity pattern provide it directly. This eliminates
4518!         the possibility that an important element that happens
4519!         to be 0 when the sparsity pattern is approximated is
4520!         later nonzero; and it avoids the NEQ extra calls to
4521!         your derivative subroutine to approximate the structure.
4522!         Note that a nemesis for any sparse ode solver is a
4523!         problem in which the sparsity pattern actually changes
4524!         during the integration. An example of such a problem
4525!         is provided in the demohum21.f90 demonstration program.
4526!         If you know the sparsity pattern changes or if you
4527!         suspect it does because DVODE_F90 is generating
4528!         nonconvergence error messages, consider having DVODE_F90
4529!         re-approximate the structure by calling SET_OPTS and
4530!         forcing an integration restart when control is returned
4531!         to your calling program. Please do not do this at every
4532!         output point since it will be extremely time consuming
4533!         and inefficient if it is not needed.
4534!
4535!  (4) The optional parameter UPIVOT is used to control the type
4536!      of partial pivoting pivoting in MA28AD. UPIVOT=0.0D0
4537!      corresponds to no pivoting; and UPIVOT=1.0D0 corresponds
4538!      to partial pivoting. UPIVOT may be assigned any value
4539!      between 0 and 1. The pivoting strategy used in MA28AD is
4540!      to accept a pivot for which the magnitude of the pivot
4541!      element is greater than or equal to UPIVOT times the
4542!      magnitude of the largest remaining element in the pivot
4543!      row. The default value is UPIVOT=1.DO
4544!         Recommendation:
4545!         Use the default value UPIVOT=1.0D0.
4546!
4547!  (5) The optional parameter NZSWAG may/should be used to speed
4548!      up the determination of acceptable array sizes for the
4549!      internal sparse working arrays and the sparse Jacobian.
4550!      Initially, DVODE_F90 allocates arrays of length
4551!      max(10*NEQ,NSZSWAG) and increases this amount by
4552!      max(10*NEQ,ELBOW_ROOM*NSZSWAG) as necessary. NZSWAG
4553!      has a default value of 1000 and ELBOW_ROOM has a default
4554!      value of 2.
4555!         Recommendation:
4556!         Provide a larger value for NZSWAG particularly if NEQ
4557!         is large and you suspect considerable fill-in due to
4558!         partial pivoting.
4559!
4560!  (6) The optional parameter ELBOW_ROOM may be used to control
4561!      the amount of "elbow room" needed in the MA28 sparse arrays.
4562!      The default value is 2 but a larger value can sometimes
4563!      speed up the determination of sparse array sizes.
4564!         Recommendation:
4565!         MA28 error and diagnostic messages are turned off by
4566!         default. The optional parameter MA28_MESSAGES may be
4567!         used to turn them on if it is assigned a nonzero value.
4568!         If you see several messages that state that LIRN_ALL
4569!         or LICN_ALL is too small and that additional storage
4570!         is being allocated for another try, and you have
4571!         provided a large value for NZSWAG, increase the size
4572!         of ELBOW_ROOM.
4573!
4574!  (7) The optional parameter SETH may be assigned a nonzero value
4575!      that represents a threshhold value for the magitude of
4576!      elements in the Jacobian below which the element will be
4577!      treated as being zero. The default value is SETH=0.0D0.
4578!         Recommendation:
4579!         Use the default value SETH=0.0D0.
4580!
4581!  (8) MA28AD determines the pivot sequence to be used in subsequent
4582!      calls to MA28BD. When MA28BD is called it considers the
4583!      iteration matrix to be numerically singular if the magnitude
4584!      of the ratio of the largest remaining element in the pivot
4585!      row to the pivot element is less than EPS. This condition
4586!      can arise since MA28BD is using an out-of-date pivot sequence.
4587!      The default value used is EPS=1.0D-4. A smaller value
4588!      of EPS may be appropriate for some problems. The optional
4589!      parameter MA28_EPS may be used to change the default value.
4590!         Recommendation:
4591!         Use the default value EPS=1.0D-4.
4592!
4593!  (9) Badly scaled Jacobians can cause problems for sparse solvers.
4594!      The parameter MA28_SCALING may be set .TRUE. to instruct
4595!      DVODE_F90 to scale the iteration matrix using MC19AD. This
4596!      can positively impact the performance of MA28AD. The default
4597!      setting is MA28_SCALING=.FALSE.
4598!         Recommendation:
4599!         Unless the solution is not successful, use the default
4600!         setting for MA29_SCALING; but consider using scaling
4601!         if you know the problem is badly scaled (e.g., if the
4602!         magnitudes of the components differ greatly).
4603!
4604! (10) As mentioned above, MA28BD uses the pivot sequence initially
4605!      determined by MA28AD. When a singularity is diagnosed, the
4606!      internal procedure used by the DENSE and BANDED options is
4607!      used to reduce the step size and re-calulate the iteration
4608!      matrix. This works fine for most problems; but particularly
4609!      for badly scaled problems, the solution may be unsuccessful
4610!      or it may drag along using small step sizes. This is due
4611!      to the fact MA28BD will continue to use the out-of-date pivot
4612!      sequence until singularity is again diagnosed. An option not
4613!      available in previous sparse ode solvers may be used to
4614!      instruct DVODE_F90 to force MA28AD to calculate a new pivot
4615!      sequence when MA28BD encounters a singularity. Although
4616!      MA28AD is considerably slower than MA28BD, the additional
4617!      calls to MA28AD ensure that the pivot sequence is more
4618!      up to date. This can increase both the accuracy and the
4619!      efficiency very dramatically. The demodirn.f90 demonstration
4620!      program provides an illustration of the dramatic improvement
4621!      that is possible. The optional parameter MA28_RPS may be set
4622!      .TRUE. to force these pivot sequence updates.
4623!         Recommendation:
4624!         Use the default value MA28_RPS=.FALSE; but if DVODE_F90
4625!         encounters nonconvergence, use MA28_RPS=.TRUE. to force
4626!         pivot sequence updates. Note that use of this option
4627!         will usually obviate the necessity to use the other
4628!         options described above. Note that we decided not to
4629!         use MA28_RPS=.TRUE. as default simply because other
4630!         sparse ode solvers are averse to calling MA28AD more
4631!         than is absolutely necessary for a given problem.
4632! ..
4633     IMPLICIT NONE
4634! ..
4635! .. Function Return Value ..
4636        TYPE (VODE_OPTS) :: OPTS
4637! ..
4638! .. Scalar Arguments ..
4639        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR, H0, HMAX, HMIN,         &
4640        MA28_EPS, RELERR, SETH, TCRIT, UPIVOT
4641        INTEGER, OPTIONAL, INTENT (IN) :: LOWER_BANDWIDTH, MAXORD,          &
4642          MA28_ELBOW_ROOM, METHOD_FLAG, MXHNIL, MXSTEP, NEVENTS, NZSWAG,    &
4643          UPPER_BANDWIDTH
4644        LOGICAL, OPTIONAL, INTENT (IN) :: BANDED_J, CHANGE_ONLY_f77_OPTIONS,&
4645          CONSTANT_JACOBIAN, DENSE_J, JACOBIAN_BY_JACSP, MA28_MESSAGES,     &
4646          MA28_RPS, MC19_SCALING, SAVE_JACOBIAN, SPARSE_J,                  &
4647          USER_SUPPLIED_JACOBIAN, USER_SUPPLIED_SPARSITY, YMAGWARN
4648! ..
4649! .. Array Arguments ..
4650        KPP_REAL, OPTIONAL, INTENT (IN) :: ABSERR_VECTOR(:), RELERR_VECTOR(:)
4651        KPP_REAL, OPTIONAL :: CLOWER(:), CUPPER(:)
4652        INTEGER, OPTIONAL, INTENT (IN) :: CONSTRAINED(:), SUB_DIAGONALS(:), &
4653        SUP_DIAGONALS(:)
4654! ..
4655! .. Local Scalars ..
4656        INTEGER ::  IER, IOPT, METH, MF, MFA, MFSIGN, MITER, ML, MOSS, MU,  &
4657          NAE, NG, NRE
4658        LOGICAL :: BANDED, DENSE, SPARSE
4659        CHARACTER (80) :: MSG
4660! ..
4661! .. Intrinsic Functions ..
4662        INTRINSIC ALLOCATED, IABS, MAX, MINVAL, PRESENT, SIGN, SIZE
4663! ..
4664! .. FIRST EXECUTABLE STATEMENT SET_OPTS
4665! ..
4666    RUSER(1:LRWUSER) = ZERO
4667    IUSER(1:LIWUSER) = 0
4668   
4669!   Allow default error tolerances?
4670    ALLOW_DEFAULT_TOLS = .FALSE.
4671
4672!   Maximum number of consecutive error test failures?
4673    CONSECUTIVE_EFAILS = KFH
4674
4675!   Maximum number of consecutive corrector iteration failures?
4676    CONSECUTIVE_CFAILS = MXNCF
4677
4678!   Use JACSP to approximate Jacobian?
4679    USE_JACSP = .FALSE.
4680    IF (PRESENT(JACOBIAN_BY_JACSP)) THEN
4681       IF (JACOBIAN_BY_JACSP) USE_JACSP = .TRUE.
4682    END IF
4683
4684!   If only f77 options are to be changed, do it and return.
4685    IF (PRESENT(CHANGE_ONLY_f77_OPTIONS)) THEN
4686       IF (CHANGE_ONLY_f77_OPTIONS) THEN
4687          IF (.NOT.OPTS_CALLED) THEN
4688             MSG = 'You have not previously called SET_OPTS before attempting'
4689             CALL XERRDV(MSG,500,1,0,0,0,0,ZERO,ZERO)
4690             MSG = 'to change one or more of the vode.f77 optional parameters.'
4691             CALL XERRDV(MSG,500,2,0,0,0,0,ZERO,ZERO)
4692          END IF
4693          IF (PRESENT(HMAX)) THEN
4694             IOPT = 1
4695             RUSER(6) = HMAX
4696             MSG = 'HMAX changed in SET_OPTS.'
4697             CALL XERRDV(MSG,510,1,0,0,0,1,HMAX,ZERO)
4698          END IF
4699          IF (PRESENT(HMIN)) THEN
4700             IOPT = 1
4701             RUSER(7) = HMIN
4702             MSG = 'HMIN changed in SET_OPTS.'
4703             CALL XERRDV(MSG,520,1,0,0,0,1,HMIN,ZERO)
4704          END IF
4705          IF (PRESENT(TCRIT)) THEN
4706             IOPT = 1
4707             RUSER(1) = TCRIT
4708             MSG = 'TCRIT changed in SET_OPTS.'
4709             CALL XERRDV(MSG,530,1,0,0,0,1,TCRIT,ZERO)
4710          END IF
4711          IF (PRESENT(MXSTEP)) THEN
4712             IOPT = 1
4713             IUSER(6) = MXSTEP
4714             MSG = 'MXSTEP changed in SET_OPTS.'
4715             CALL XERRDV(MSG,530,1,1,MXSTEP,0,0,ZERO,ZERO)
4716          END IF
4717          IF (PRESENT(MAXORD)) THEN
4718             IOPT = 1
4719             IUSER(5) = MAXORD
4720             MSG = 'MAXORD changed in SET_OPTS.'
4721             CALL XERRDV(MSG,540,1,1,MAXORD,0,0,ZERO,ZERO)
4722          END IF
4723          IF (PRESENT(MXHNIL)) THEN
4724             IOPT = 1
4725             IUSER(7) = MXHNIL
4726             MSG = 'MXHNIL changed in SET_OPTS.'
4727             CALL XERRDV(MSG,550,1,1,MXHNIL,0,0,ZERO,ZERO)
4728          END IF
4729       END IF
4730       RETURN
4731    END IF
4732
4733!   Set the flag to indicate that SET_OPTS has been called.
4734    OPTS_CALLED = .TRUE.
4735
4736!   Set the MA48 storage cleanup flag.
4737    MA48_WAS_USED = .FALSE.
4738
4739!   Set the fast factor option for MA48,
4740    USE_FAST_FACTOR = .TRUE.
4741
4742!   Determine the working precision and define the value for UMAX
4743!   expected by MA28. Note that it is different for single and
4744!   double precision.
4745    WPD = KIND(1.0D0)
4746    WPS = KIND(1.0E0)
4747    IF (WPD/=WP .AND. WPS/=WP) THEN
4748      MSG = 'Illegal working precision in SET_OPTS.'
4749      CALL XERRDV(MSG,560,2,0,0,0,0,ZERO,ZERO)
4750    END IF
4751    IF (WPD==WP) THEN
4752!   Working precision is double.
4753      UMAX = 0.999999999_dp
4754    ELSE
4755!     Working precision is single.
4756      UMAX = 0.9999_dp
4757    END IF
4758
4759!   Set the MA28 message flag.
4760    IF (PRESENT(MA28_MESSAGES)) THEN
4761       LP = 0
4762       IF (MA28_MESSAGES) LP = 6
4763    ELSE
4764       LP = 0
4765    END IF
4766
4767!   Set the MA28 singularity threshold.
4768    IF (PRESENT(MA28_EPS)) THEN
4769       IF (MA28_EPS > ZERO) THEN
4770          EPS = MA28_EPS
4771       ELSE
4772          EPS = 1.0E-4_dp
4773       END IF
4774     ELSE
4775       EPS = 1.0E-4_dp
4776     END IF
4777
4778!   Set the MA28 pivot sequence frequency flag.
4779    IF (PRESENT(MA28_RPS)) THEN
4780       IF (MA28_RPS) THEN
4781          REDO_PIVOT_SEQUENCE = MA28_RPS
4782       ELSE
4783          REDO_PIVOT_SEQUENCE = .FALSE.
4784       END IF
4785     ELSE
4786       REDO_PIVOT_SEQUENCE = .FALSE.
4787     END IF
4788
4789     MA28AD_CALLS = 0
4790     MA28BD_CALLS = 0
4791     MA28CD_CALLS = 0
4792     MC19AD_CALLS = 0
4793!_______________________________________________________________________
4794! *****MA48 build change point. Insert these statements.
4795!    MA48AD_CALLS = 0
4796!    MA48BD_CALLS = 0
4797!    MA48CD_CALLS = 0
4798!_______________________________________________________________________
4799     IRNCP = 0
4800     ICNCP = 0
4801     MINIRN = 0
4802     MINICN = 0
4803     MAX_MINIRN = 0
4804     MAX_MINICN = 0
4805     MAX_NNZ = 0
4806
4807!   Set the flag to warn the user if |(y(t)| < abserr.
4808     IF (PRESENT(YMAGWARN)) THEN
4809       IF (YMAGWARN) THEN
4810         YMAXWARN = .TRUE.
4811       ELSE
4812         YMAXWARN = .FALSE.
4813       END IF
4814     ELSE
4815       YMAXWARN = .FALSE.
4816     END IF
4817
4818!    Load defaults for the optional input arrays for DVODE.
4819     IUSER(1:8) = 0
4820     RUSER(1:8) = ZERO
4821
4822!    Set the method flag.
4823     IF (.NOT.(PRESENT(METHOD_FLAG))) THEN
4824       MF = 10
4825       IF (PRESENT(SPARSE_J)) THEN
4826         IF (SPARSE_J) THEN
4827           IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
4828             IF (USER_SUPPLIED_JACOBIAN) THEN
4829               MF = 126
4830             ELSE
4831               MF = 227
4832             END IF
4833           ELSE
4834             MF = 227
4835           END IF
4836           IF (PRESENT(USER_SUPPLIED_SPARSITY)) THEN
4837             IF (USER_SUPPLIED_SPARSITY) THEN
4838               MF = MF - 100*(MF/100)
4839             END IF
4840           END IF
4841           IF (PRESENT(SAVE_JACOBIAN)) THEN
4842             IF (.NOT.SAVE_JACOBIAN) THEN
4843               MF = -MF
4844             END IF
4845           END IF
4846          END IF
4847          END IF
4848
4849          IF (PRESENT(BANDED_J)) THEN
4850            IF (BANDED_J) THEN
4851              IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
4852                IF (USER_SUPPLIED_JACOBIAN) THEN
4853                  MF = 24
4854                ELSE
4855                  MF = 25
4856                END IF
4857              ELSE
4858                MF = 25
4859              END IF
4860              IF (PRESENT(SAVE_JACOBIAN)) THEN
4861                IF (.NOT.SAVE_JACOBIAN) THEN
4862                  MF = -MF
4863                END IF
4864              END IF
4865            END IF
4866          END IF
4867
4868          IF (PRESENT(DENSE_J)) THEN
4869            IF (DENSE_J) THEN
4870              IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
4871                IF (USER_SUPPLIED_JACOBIAN) THEN
4872                  MF = 21
4873                ELSE
4874                  MF = 22
4875                END IF
4876              ELSE
4877                MF = 22
4878              END IF
4879              IF (PRESENT(SAVE_JACOBIAN)) THEN
4880                IF (.NOT.SAVE_JACOBIAN) THEN
4881                  MF = -MF
4882                END IF
4883              END IF
4884            END IF
4885          END IF
4886     ELSE
4887       MF = METHOD_FLAG
4888     END IF
4889
4890!    Check for errors in MF.
4891     MFA = IABS(MF)
4892     MOSS = MFA/100
4893     METH = (MFA-100*MOSS)/10
4894     MITER = MFA - 100*MOSS - 10*METH
4895     IF (METH<1 .OR. METH>2) THEN
4896       MSG = 'Illegal value of METH in SET_OPTS.'
4897       CALL XERRDV(MSG,570,2,0,0,0,0,ZERO,ZERO)
4898     END IF
4899     IF (MITER<0 .OR. MITER>7) THEN
4900       MSG = 'Illegal value of MITER in SET_OPTS.'
4901       CALL XERRDV(MSG,580,2,0,0,0,0,ZERO,ZERO)
4902     END IF
4903     IF (MOSS<0 .OR. MOSS>2) THEN
4904       MSG = 'Illegal value of MOSS in SET_OPTS.'
4905       CALL XERRDV(MSG,580,2,0,0,0,0,ZERO,ZERO)
4906     END IF
4907
4908!    Reset MF, now that MOSS is known.
4909     MFSIGN = SIGN(1,MF)
4910     MF = MF - 100*MOSS*MFSIGN
4911
4912     IF (MITER==0) THEN
4913       DENSE = .FALSE.
4914       BANDED = .FALSE.
4915       SPARSE = .FALSE.
4916     ELSE IF (MITER==1 .OR. MITER==2) THEN
4917       DENSE = .TRUE.
4918       BANDED = .FALSE.
4919       SPARSE = .FALSE.
4920     ELSE IF (MITER==3) THEN
4921       DENSE = .FALSE.
4922       BANDED = .FALSE.
4923       SPARSE = .FALSE.
4924     ELSE IF (MITER==4 .OR. MITER==5) THEN
4925       DENSE = .FALSE.
4926       BANDED = .TRUE.
4927       SPARSE = .FALSE.
4928     ELSE IF (MITER==6 .OR. MITER==7) THEN
4929       DENSE = .FALSE.
4930       BANDED = .FALSE.
4931       SPARSE = .TRUE.
4932     END IF
4933
4934!    Define the banded Jacobian band widths.
4935     IF (BANDED) THEN
4936       IF (PRESENT(LOWER_BANDWIDTH)) THEN
4937         ML = LOWER_BANDWIDTH
4938         IUSER(1) = ML
4939       ELSE
4940         MSG = 'In SET_OPTS you have indicated a'
4941         CALL XERRDV(MSG,590,1,0,0,0,0,ZERO,ZERO)
4942         MSG = 'banded Jacobian but you have not'
4943         CALL XERRDV(MSG,590,1,0,0,0,0,ZERO,ZERO)
4944         MSG = 'supplied the lower bandwidth.'
4945         CALL XERRDV(MSG,590,2,0,0,0,0,ZERO,ZERO)
4946       END IF
4947       IF (PRESENT(UPPER_BANDWIDTH)) THEN
4948         MU = UPPER_BANDWIDTH
4949         IUSER(2) = MU
4950       ELSE
4951         MSG = 'In SET_OPTS you have indicated a'
4952         CALL XERRDV(MSG,600,1,0,0,0,0,ZERO,ZERO)
4953         MSG = 'banded Jacobian but you have not'
4954         CALL XERRDV(MSG,600,1,0,0,0,0,ZERO,ZERO)
4955         MSG = 'supplied the upper bandwidth.'
4956         CALL XERRDV(MSG,600,2,0,0,0,0,ZERO,ZERO)
4957       END IF
4958!      Define the nonzero diagonals.
4959       BNGRP = 0
4960       SUBS = .FALSE.
4961       SUPS = .FALSE.
4962       NSUBS  = 0
4963       NSUPS = 0
4964       IF (PRESENT(SUB_DIAGONALS)) THEN
4965         SUBS = .TRUE.
4966         NSUBS = SIZE(SUB_DIAGONALS)
4967         IF (NSUBS > 0) THEN
4968            IF (ALLOCATED(SUBDS)) THEN
4969               DEALLOCATE(SUBDS,STAT=IER)
4970               CALL CHECK_STAT(IER,80)
4971            END IF
4972            ALLOCATE(SUBDS(NSUBS),STAT=IER)
4973            CALL CHECK_STAT(IER,90)
4974            SUBDS(1:NSUBS) = SUB_DIAGONALS(1:NSUBS)
4975         ELSE
4976            IF (ML > 0) THEN
4977               MSG = 'You must indicated that the lower bandwidth'
4978               CALL XERRDV(MSG,610,1,0,0,0,0,ZERO,ZERO)
4979               MSG = 'is positive but you have not specified the'
4980               CALL XERRDV(MSG,610,1,0,0,0,0,ZERO,ZERO)
4981               MSG = 'indices for the lower sub diagonals.'
4982               CALL XERRDV(MSG,610,2,0,0,0,0,ZERO,ZERO)
4983            END IF
4984         END IF
4985       END IF
4986       IF (PRESENT(SUP_DIAGONALS)) THEN
4987         SUPS = .TRUE.
4988         NSUPS = SIZE(SUP_DIAGONALS)
4989         IF (NSUPS > 0) THEN
4990            IF (ALLOCATED(SUPDS)) THEN
4991               DEALLOCATE(SUPDS,STAT=IER)
4992               CALL CHECK_STAT(IER,100)
4993            END IF
4994            ALLOCATE(SUPDS(NSUPS),STAT=IER)
4995            CALL CHECK_STAT(IER,110)
4996            SUPDS(1:NSUPS) = SUP_DIAGONALS(1:NSUPS)
4997         ELSE
4998            IF (ML > 0) THEN
4999               MSG = 'You must indicated that the upper bandwidth'
5000               CALL XERRDV(MSG,620,1,0,0,0,0,ZERO,ZERO)
5001               MSG = 'is positive but you have not specified the'
5002               CALL XERRDV(MSG,620,1,0,0,0,0,ZERO,ZERO)
5003               MSG = 'indices for the upper sub diagonals.'
5004               CALL XERRDV(MSG,620,2,0,0,0,0,ZERO,ZERO)
5005            END IF
5006         END IF
5007       END IF
5008     END IF
5009
5010!    Define the sparse Jacobian options.
5011     SCALE_MATRIX = .FALSE.
5012     ELBOW_ROOM = 2
5013     IF (SPARSE) THEN
5014!      NZSWAG for the number of nonzeros in the Jacobian.
5015       IF (PRESENT(NZSWAG)) THEN
5016         NZ_SWAG = MAX(NZSWAG,0)
5017
5018       ELSE
5019         NZ_SWAG = 0
5020       END IF
5021!      Indicate that SET_IAJA has not yet been called successfully.
5022       IAJA_CALLED = .FALSE.
5023!      Check for illegal method flags.
5024       IF (MOSS==2 .AND. MITER/=7) THEN
5025         MSG = 'In SET_OPTS MOSS=2 but MITER is not 7.'
5026            CALL XERRDV(MSG,630,2,0,0,0,0,ZERO,ZERO)
5027         END IF
5028         IF (MOSS==1 .AND. MITER/=6) THEN
5029           MSG = 'In SET_OPTS MOSS=1 but MITER is not 6.'
5030           CALL XERRDV(MSG,640,2,0,0,0,0,ZERO,ZERO)
5031         END IF
5032!        IF (MOSS==0 .AND. MITER/=7) THEN
5033!          MSG = 'In SET_OPTS MOSS=0 but MITER is not 7.'
5034!          CALL XERRDV(MSG,650,2,0,0,0,0,ZERO,ZERO)
5035!        END IF
5036!        Allow the work array elbow room to be increased.
5037         IF (PRESENT(MA28_ELBOW_ROOM)) THEN
5038            ELBOW_ROOM = MAX(MA28_ELBOW_ROOM, ELBOW_ROOM)
5039         END IF
5040!      Allow MC19 scaling for the Jacobian.
5041       SCALE_MATRIX = .FALSE.
5042       IF (PRESENT(MC19_SCALING)) THEN
5043          IF (MC19_SCALING) THEN
5044!_______________________________________________________________________
5045! *****MA48 build change point. Insert these statements.
5046!         IF (USE_MA48_FOR_SPARSE) THEN
5047!            MSG = 'MC29AD scaling is not available at this time.'
5048!            CALL XERRDV(MSG,660,1,0,0,0,0,ZERO,ZERO)
5049!            MSG = 'Execution will continue.'
5050!            CALL XERRDV(MSG,660,1,0,0,0,0,ZERO,ZERO)
5051!         END IF
5052!_______________________________________________________________________
5053             SCALE_MATRIX = MC19_SCALING
5054!            SCALE_MATRIX = .FALSE.
5055          END IF
5056       END IF
5057
5058!_______________________________________________________________________
5059! *****MA48 build change point. Replace above with these statements.
5060!      IF (PRESENT(MC19_SCALING)) THEN
5061!         IF (MC19_SCALING) THEN
5062!            IF (USE_MA48_FOR_SPARSE) THEN
5063!               MSG = 'Please note that this version uses MC19AD rather'
5064!               CALL XERRDV(MSG,670,1,0,0,0,0,ZERO,ZERO)
5065!               MSG = 'than MC29AD to sacle the iteration matrix.'
5066!               CALL XERRDV(MSG,670,1,0,0,0,0,ZERO,ZERO)
5067!               MSG = 'Execution will continue.'
5068!               CALL XERRDV(MSG,670,1,0,0,0,0,ZERO,ZERO)
5069!            END IF
5070!            SCALE_MATRIX = MC19_SCALING
5071!         END IF
5072!       END IF
5073!_______________________________________________________________________
5074
5075       END IF
5076
5077!       Define the number of event functions.
5078        IF (PRESENT(NEVENTS)) THEN
5079          IF (NEVENTS>0) THEN
5080            NG = NEVENTS
5081          ELSE
5082            NG = 0
5083          END IF
5084        ELSE
5085          NG = 0
5086        END IF
5087
5088!       Process the constrained solution components.
5089        IF (PRESENT(CONSTRAINED)) THEN
5090          NDX = SIZE(CONSTRAINED)
5091          IF (NDX<1) THEN
5092            MSG = 'In SET_OPTS the size of CONSTRAINED < 1.'
5093            CALL XERRDV(MSG,680,2,0,0,0,0,ZERO,ZERO)
5094          END IF
5095          IF (.NOT.(PRESENT(CLOWER)) .OR. .NOT.(PRESENT(CUPPER))) THEN
5096            MSG = 'In SET_OPTS the arrays CLOWER and CUPPER are'
5097            CALL XERRDV(MSG,690,1,0,0,0,0,ZERO,ZERO)
5098            MSG = 'not present.'
5099            CALL XERRDV(MSG,690,2,0,0,0,0,ZERO,ZERO)
5100          END IF
5101          IF (SIZE(CLOWER)/=NDX .OR. SIZE(CUPPER)/=NDX) THEN
5102            MSG = 'In SET_OPTS the size of the solution bound arrays'
5103            CALL XERRDV(MSG,700,1,0,0,0,0,ZERO,ZERO)
5104            MSG = 'must be the same as the CONSTRAINED array.'
5105            CALL XERRDV(MSG,700,2,0,0,0,0,ZERO,ZERO)
5106          END IF
5107!         Note: The contents of CONSTRAINED will be checked
5108!         in subroutine DVODE after NEQ is known.
5109          IF (ALLOCATED(IDX)) THEN
5110            DEALLOCATE (IDX,LB,UB,STAT=IER)
5111            CALL CHECK_STAT(IER,120)
5112          END IF
5113          ALLOCATE (IDX(NDX),LB(NDX),UB(NDX),STAT=IER)
5114          CALL CHECK_STAT(IER,130)
5115          IDX(1:NDX) = CONSTRAINED(1:NDX)
5116          LB(1:NDX) = CLOWER(1:NDX)
5117          UB(1:NDX) = CUPPER(1:NDX)
5118          BOUNDS = .TRUE.
5119        ELSE
5120          IF (ALLOCATED(IDX)) THEN
5121            DEALLOCATE (IDX,LB,UB,STAT=IER)
5122            CALL CHECK_STAT(IER,140)
5123          END IF
5124          NDX = 0
5125          BOUNDS = .FALSE.
5126        END IF
5127
5128!       Is the Jacobian constant?
5129        J_IS_CONSTANT = .FALSE.
5130        J_HAS_BEEN_COMPUTED = .FALSE.
5131
5132!_______________________________________________________________________
5133        IF (PRESENT(CONSTANT_JACOBIAN)) THEN
5134           IF (CONSTANT_JACOBIAN) THEN
5135              J_IS_CONSTANT = .TRUE.
5136!_______________________________________________________________________
5137! *****MA48 build change point. Insert these statements.
5138              IF (USE_MA48_FOR_SPARSE .AND. SPARSE) THEN
5139                 MSG = 'The constant Jacobian option is not yet available'
5140                 CALL XERRDV(MSG,710,1,0,0,0,0,ZERO,ZERO)
5141                 MSG = 'with the sparse MA48 solution option. Execution'
5142                 CALL XERRDV(MSG,710,1,0,0,0,0,ZERO,ZERO)
5143                 MSG = 'will continue.'
5144                 CALL XERRDV(MSG,710,1,0,0,0,0,ZERO,ZERO)
5145                 J_IS_CONSTANT = .FALSE.
5146              END IF
5147!_______________________________________________________________________
5148           END IF
5149        END IF
5150! *****MA48 build change point. Replace above with these statements.
5151!       IF (PRESENT(CONSTANT_JACOBIAN)) THEN
5152!          IF (CONSTANT_JACOBIAN) THEN
5153!             IF (USE_MA48_FOR_SPARSE) THEN
5154!                MSG = 'The constant Jacobian option is not yet available'
5155!                CALL XERRDV(MSG,720,1,0,0,0,0,ZERO,ZERO)
5156!                MSG = 'with the sparse MA48 solution option. Execution'
5157!                CALL XERRDV(MSG,720,1,0,0,0,0,ZERO,ZERO)
5158!                MSG = 'will continue.'
5159!                CALL XERRDV(MSG,720,1,0,0,0,0,ZERO,ZERO)
5160!             END IF
5161!          ELSE
5162!             J_IS_CONSTANT = .TRUE.
5163!          END IF
5164!       END IF
5165!_______________________________________________________________________
5166        IF (J_IS_CONSTANT) THEN
5167           IF (PRESENT(SAVE_JACOBIAN)) THEN
5168              IF (.NOT.SAVE_JACOBIAN) THEN
5169                 MSG = 'You have specified that the Jacobian is constant.'
5170                 CALL XERRDV(MSG,730,1,0,0,0,0,ZERO,ZERO)
5171                 MSG = 'In this case you cannot also specify that'
5172                 CALL XERRDV(MSG,730,1,0,0,0,0,ZERO,ZERO)
5173                 MSG = 'SAVE_JACOBIAN=.FALSE.'
5174                 CALL XERRDV(MSG,730,2,0,0,0,0,ZERO,ZERO)
5175              END IF
5176           END IF
5177           IF (PRESENT(USER_SUPPLIED_JACOBIAN)) THEN
5178              IF (USER_SUPPLIED_JACOBIAN .AND. SPARSE) THEN
5179                 MSG = 'You have specified that the Jacobian is constant'
5180                 CALL XERRDV(MSG,740,1,0,0,0,0,ZERO,ZERO)
5181                 MSG = 'and that you wish to supply an analytic Jacobian'
5182                 CALL XERRDV(MSG,740,1,0,0,0,0,ZERO,ZERO)
5183                 MSG = 'for a sparse problem. In this case your request'
5184                 CALL XERRDV(MSG,740,1,0,0,0,0,ZERO,ZERO)
5185                 MSG = 'to use a constant Jacobian will be ignored.'
5186                 CALL XERRDV(MSG,740,1,0,0,0,0,ZERO,ZERO)
5187                 MSG = 'Execution will continue.'
5188                 CALL XERRDV(MSG,740,1,0,0,0,0,ZERO,ZERO)
5189              END IF
5190           END IF
5191        END IF
5192
5193!       Load the user options into the solution structure.
5194        OPTS%MF = MF
5195        OPTS%METH = METH
5196        OPTS%MITER = MITER
5197        OPTS%MOSS = MOSS
5198        OPTS%DENSE = DENSE
5199        OPTS%BANDED = BANDED
5200        OPTS%SPARSE = SPARSE
5201        OPTS%NG = NG
5202
5203!       Process the miscellaneous options.
5204
5205!       Don't step past TCRIT variable.
5206        IF (PRESENT(TCRIT)) THEN
5207          RUSER(1) = TCRIT
5208        ELSE
5209          RUSER(1) = ZERO
5210        END IF
5211
5212!       DVODE optional parameters.
5213        IOPT = 1
5214        IF (PRESENT(MAXORD)) THEN
5215          IUSER(5) = MAXORD
5216          IOPT = 1
5217        END IF
5218        IF (PRESENT(MXSTEP)) THEN
5219          IUSER(6) = MXSTEP
5220          IOPT = 1
5221        END IF
5222        IF (PRESENT(MXHNIL)) THEN
5223          IUSER(7) = MXHNIL
5224          IOPT = 1
5225        END IF
5226        IF (PRESENT(H0)) THEN
5227          RUSER(5) = H0
5228          IOPT = 1
5229        END IF
5230        IF (PRESENT(HMAX)) THEN
5231          RUSER(6) = HMAX
5232          IOPT = 1
5233        END IF
5234        IF (PRESENT(HMIN)) THEN
5235          RUSER(7) = HMIN
5236          IOPT = 1
5237        END IF
5238        IF (PRESENT(SETH)) THEN
5239          RUSER(8) = SETH
5240          IOPT = 1
5241        END IF
5242        IF (PRESENT(UPIVOT)) THEN
5243          U_PIVOT = UPIVOT
5244          IF (U_PIVOT<ZERO) U_PIVOT = ZERO
5245          IF (U_PIVOT>ONE) U_PIVOT = ONE
5246        ELSE
5247          U_PIVOT = ONE
5248        END IF
5249!_______________________________________________________________________
5250! *****MA48 build change point. Insert this statement.
5251!       COPY_OF_U_PIVOT = U_PIVOT
5252!_______________________________________________________________________
5253        OPTS%IOPT = IOPT
5254
5255!       Define the error tolerances.
5256
5257!       Relative error tolerances.
5258        IF (PRESENT(RELERR_VECTOR)) THEN
5259          IF (MINVAL(RELERR_VECTOR)<ZERO) THEN
5260            MSG = 'All components of RELERR_VECTOR must'
5261            CALL XERRDV(MSG,750,1,0,0,0,0,ZERO,ZERO)
5262            MSG = 'be nonnegative.'
5263            CALL XERRDV(MSG,750,2,0,0,0,0,ZERO,ZERO)
5264          END IF
5265          NRE = SIZE(RELERR_VECTOR)
5266        ELSE
5267          NRE = 1
5268        END IF
5269        ALLOCATE (OPTS%RTOL(NRE),STAT=IER)
5270        CALL CHECK_STAT(IER,150)
5271        IF (PRESENT(RELERR_VECTOR)) THEN
5272          OPTS%RTOL = RELERR_VECTOR
5273        ELSE IF (PRESENT(RELERR)) THEN
5274          IF (RELERR<ZERO) THEN
5275            MSG = 'RELERR must be nonnegative.'
5276            CALL XERRDV(MSG,760,2,0,0,0,0,ZERO,ZERO)
5277          END IF
5278          OPTS%RTOL = RELERR
5279        ELSE
5280          IF (ALLOW_DEFAULT_TOLS) THEN
5281             OPTS%RTOL = 1.0E-4_dp
5282             MSG = 'By not specifying RELERR, you have elected to use a default'
5283             CALL XERRDV(MSG,770,1,0,0,0,0,ZERO,ZERO)
5284             MSG = 'relative error tolerance equal to 1.0D-4. Please be aware a'
5285             CALL XERRDV(MSG,770,1,0,0,0,0,ZERO,ZERO)
5286             MSG = 'tolerance this large is not appropriate for all problems.'
5287             CALL XERRDV(MSG,770,1,0,0,0,0,ZERO,ZERO)
5288             MSG = 'Execution will continue'
5289             CALL XERRDV(MSG,770,1,0,0,0,0,ZERO,ZERO)
5290          ELSE
5291             MSG = 'You must specify a nonzero relative error tolerance.'
5292             CALL XERRDV(MSG,780,2,0,0,0,0,ZERO,ZERO)
5293          END IF
5294        END IF
5295
5296!       Absolute error tolerances.
5297        IF (PRESENT(ABSERR_VECTOR)) THEN
5298          IF (MINVAL(ABSERR_VECTOR)<ZERO) THEN
5299            MSG = 'All components of ABSERR_VECTOR must'
5300            CALL XERRDV(MSG,790,1,0,0,0,0,ZERO,ZERO)
5301            MSG = 'be nonnegative.'
5302            CALL XERRDV(MSG,790,2,0,0,0,0,ZERO,ZERO)
5303          END IF
5304          NAE = SIZE(ABSERR_VECTOR)
5305        ELSE
5306          NAE = 1
5307        END IF
5308        ALLOCATE (OPTS%ATOL(NAE),STAT=IER)
5309        CALL CHECK_STAT(IER,160)
5310        IF (PRESENT(ABSERR_VECTOR)) THEN
5311          OPTS%ATOL = ABSERR_VECTOR
5312        ELSE IF (PRESENT(ABSERR)) THEN
5313          IF (ABSERR<ZERO) THEN
5314            MSG = 'ABSERR must be nonnegative.'
5315            CALL XERRDV(MSG,800,2,0,0,0,0,ZERO,ZERO)
5316          END IF
5317          OPTS%ATOL = ABSERR
5318        ELSE
5319          IF (ALLOW_DEFAULT_TOLS) THEN
5320             OPTS%ATOL = 1D-6
5321             MSG = 'By not specifying ABSERR, you have elected to use a default'
5322             CALL XERRDV(MSG,810,1,0,0,0,0,ZERO,ZERO)
5323             MSG = 'absolute error tolerance equal to 1.0D-6. Please be aware a'
5324             CALL XERRDV(MSG,810,1,0,0,0,0,ZERO,ZERO)
5325             MSG = 'tolerance this large is not appropriate for all problems.'
5326             CALL XERRDV(MSG,810,1,0,0,0,0,ZERO,ZERO)
5327             MSG = 'Execution will continue'
5328             CALL XERRDV(MSG,810,1,0,0,0,0,ZERO,ZERO)
5329          ELSE
5330             MSG = 'You must specify a vector of absolute error tolerances or'
5331             CALL XERRDV(MSG,820,1,0,0,0,0,ZERO,ZERO)
5332             MSG = 'a scalar error tolerance. It is recommended that you use'
5333             CALL XERRDV(MSG,820,1,0,0,0,0,ZERO,ZERO)
5334             MSG = 'a vector of absolute error tolerances.'
5335             CALL XERRDV(MSG,820,2,0,0,0,0,ZERO,ZERO)
5336          END IF
5337        END IF
5338
5339!       ITOL error tolerance flag.
5340!          ITOL   RTOL     ATOL            EWT(i)
5341!            1   scalar   scalar  RTOL*ABS(Y(i)) + ATOL
5342!            2   scalar   array   RTOL*ABS(Y(i)) + ATOL(i)
5343!            3   array    scalar  RTOL(i)*ABS(Y(i)) + ATOL
5344!            4   array    array   RTOL(i)*ABS(Y(i)) + ATOL(i)
5345        IF (PRESENT(ABSERR_VECTOR)) THEN
5346          IF (PRESENT(RELERR_VECTOR)) THEN
5347            OPTS%ITOL = 4
5348          ELSE
5349            OPTS%ITOL = 2
5350          END IF
5351        ELSE
5352          IF (PRESENT(RELERR_VECTOR)) THEN
5353            OPTS%ITOL = 3
5354          ELSE
5355            OPTS%ITOL = 1
5356          END IF
5357        END IF
5358        RETURN
5359
5360  END FUNCTION SET_OPTS
5361!_______________________________________________________________________
5362
5363      SUBROUTINE GET_STATS(RSTATS,ISTATS,NUMEVENTS,JROOTS)
5364! ..
5365! Return the user portions of the DVODE RUSER and IUSER arrays;
5366! and if root finding is being done, return the JROOT vector
5367! (not called by DVODE_F90).
5368! ..
5369! Available Integration Statistics.
5370! HU      RUSER(11) The step size in t last used (successfully).
5371! HCUR    RUSER(12) The step size to be attempted on the next step.
5372! TCUR    RUSER(13) The current value of the independent variable
5373!                   which the solver has actually reached, i.e. the
5374!                   current internal mesh point in t. In the output,
5375!                   TCUR will always be at least as far from the
5376!                   initial value of t as the current argument T,
5377!                   but may be farther (if interpolation was done).
5378! TOLSF   RUSER(14) A tolerance scale factor, greater than 1.0,
5379!                   computed when a request for too much accuracy was
5380!                   detected (ISTATE = -3 if detected at the start of
5381!                   the problem, ISTATE = -2 otherwise). If ITOL is
5382!                   left unaltered but RTOL and ATOL are uniformly
5383!                   scaled up by a factor of TOLSF for the next call,
5384!                   then the solver is deemed likely to succeed.
5385!                   (The user may also ignore TOLSF and alter the
5386!                   tolerance parameters in any other way appropriate.)
5387! NST     IUSER(11) The number of steps taken for the problem so far.
5388! NFE     IUSER(12) The number of f evaluations for the problem so far.
5389! NJE     IUSER(13) The number of Jacobian evaluations so far.
5390! NQU     IUSER(14) The method order last used (successfully).
5391! NQCUR   IUSER(15) The order to be attempted on the next step.
5392! IMXER   IUSER(16) The index of the component of largest magnitude in
5393!                   the weighted local error vector (e(i)/EWT(i)),
5394!                   on an error return with ISTATE = -4 or -5.
5395! LENRW   IUSER(17) The length of RUSER actually required.
5396!                   This is defined on normal returns and on an illegal
5397!                   input return for insufficient storage.
5398! LENIW   IUSER(18) The length of IUSER actually required.
5399!                   This is defined on normal returns and on an illegal
5400!                   input return for insufficient storage.
5401! NLU     IUSER(19) The number of matrix LU decompositions so far.
5402! NNI     IUSER(20) The number of nonlinear (Newton) iterations so far.
5403! NCFN    IUSER(21) The number of convergence failures of the nonlinear
5404!                   solver so far.
5405! NETF    IUSER(22) The number of error test failures of the integrator
5406!                   so far.
5407! MA28AD_CALLS      IUSER(23) The number of calls made to MA28AD
5408! MA28BD_CALLS      IUSER(24) The number of calls made to MA28BD
5409! MA28CD_CALLS      IUSER(25) The number of calls made to MA28CD
5410! MC19AD_CALLS      IUSER(26) The number of calls made to MC19AD
5411! IRNCP             IUSER(27) The number of compressions done on array JAN
5412! ICNCP             IUSER(28) The number of compressions done on array ICN
5413! MINIRN            IUSER(29) Minimum size for JAN array
5414! MINICN            IUSER(30) Minimum size for ICN array
5415! JROOTS  JROOTS    Optional array of component indices for components
5416!                   having a zero at the current time
5417! ..
5418     IMPLICIT NONE
5419! ..
5420! .. Scalar Arguments ..
5421        INTEGER, OPTIONAL, INTENT (IN) :: NUMEVENTS
5422! ..
5423! .. Array Arguments ..
5424        KPP_REAL, INTENT (INOUT) :: RSTATS(22)
5425        INTEGER, INTENT (INOUT) :: ISTATS(31)
5426        INTEGER, OPTIONAL, INTENT (INOUT) :: JROOTS(:)
5427! ..
5428! .. Local Scalars ..
5429        CHARACTER (80) :: MSG
5430! ..
5431! .. Intrinsic Functions ..
5432        INTRINSIC ALLOCATED, PRESENT, SIZE
5433! ..
5434!   Caution:
5435!   It is assumed that the size of RSTATS is 22.
5436!   It is assumed that the size of ISTATS is 31.
5437!   Refer to the documentation prologue for a description
5438!   the optional output contained in RUSER and IUSER.
5439! ..
5440! .. FIRST EXECUTABLE STATEMENT GET_STATS
5441! ..
5442!       Check if DVODE_F90 has been called yet.
5443        IF (.NOT.OPTS_CALLED) THEN
5444          MSG = 'You have called GET_STATS before'
5445          CALL XERRDV(MSG,830,1,0,0,0,0,ZERO,ZERO)
5446          MSG = 'calling DVODE_F90 the first time.'
5447          CALL XERRDV(MSG,830,1,0,0,0,0,ZERO,ZERO)
5448          RETURN
5449        END IF
5450
5451!       Check that the arrays are large enough to hold the statistics.
5452!       Some compilers don't like this use of SIZE.
5453!       IF (SIZE(RSTATS)<LRWUSER) THEN
5454!       IF (SIZE(RSTATS)<31) THEN
5455!         MSG = 'In GET_STATS, RSTATS array is too small.'
5456!         CALL XERRDV(MSG,840,1,0,0,0,0,ZERO,ZERO)
5457!         RETURN
5458!       END IF
5459!       IF (SIZE(ISTATS)<LIWUSER) THEN
5460!       IF (SIZE(ISTATS)<31) THEN
5461!         MSG = 'In GET_STATS, ISTATS array is too small.'
5462!         CALL XERRDV(MSG,850,1,0,0,0,0,ZERO,ZERO)
5463!         RETURN
5464!       END IF
5465
5466!       Copy the statistics.
5467        RSTATS(1:LRWUSER) = RUSER(1:LRWUSER)
5468!       ISTATS(1:LIWUSER) = IUSER(1:LIWUSER)
5469        ISTATS(1:22) = IUSER(1:22)
5470        ISTATS(23) = MA28AD_CALLS
5471        ISTATS(24) = MA28BD_CALLS
5472        ISTATS(25) = MA28CD_CALLS
5473!_______________________________________________________________________
5474! *****MA48 build change point.Replace the three previous statements
5475!      with these statements.
5476!       IF (USE_MA48_FOR_SPARSE) THEN
5477!          ISTATS(23) = MA48AD_CALLS
5478!          ISTATS(24) = MA48BD_CALLS
5479!          ISTATS(25) = MA48CD_CALLS
5480!       ELSE
5481!          ISTATS(23) = MA28AD_CALLS
5482!          ISTATS(24) = MA28BD_CALLS
5483!          ISTATS(25) = MA28CD_CALLS
5484!       END IF
5485!_______________________________________________________________________
5486        ISTATS(26) = MC19AD_CALLS
5487        ISTATS(27) = IRNCP
5488        ISTATS(28) = ICNCP
5489!       ISTATS(29) = MINIRN
5490!       ISTATS(30) = MINICN
5491!       ISTATS(31) = NZ_ALL
5492        ISTATS(29) = MAX_MINIRN
5493        ISTATS(30) = MAX_MINICN
5494        ISTATS(31) = MAX_NNZ
5495!       If root finding is being used return the JROOT vector.
5496        IF (PRESENT(NUMEVENTS)) THEN
5497          IF (PRESENT(JROOTS)) THEN
5498            IF (ALLOCATED(JROOT)) THEN
5499              JROOTS(1:NUMEVENTS) = JROOT(1:NUMEVENTS)
5500            END IF
5501          END IF
5502        END IF
5503        RETURN
5504
5505      END SUBROUTINE GET_STATS
5506!_______________________________________________________________________
5507
5508      SUBROUTINE USERSETS_IAJA(IAUSER,NIAUSER,JAUSER,NJAUSER)
5509! ..
5510! Approximate or allow the user to supply the sparse Jacobian
5511! structure pointer arrays IA and JA directly for DVODE_F90
5512! (not called by DVODE_F90).
5513! ..
5514! Used if the user wishes to supply the sparsity structure
5515! directly.
5516!     Caution:
5517!     If it is called, USERSETS_IAJA must be called after the
5518!     call to SET_OPTS.
5519!     Usage:
5520!     CALL SET_IAJA(IAUSER,NIAUSER,JAUSER,NJAUSER)
5521!       In this case, IAUSER of length NIAUSER will be used for
5522!       IA; and JAUSER of length NJAUSER will be used for JA.
5523!     Arguments:
5524!     IAUSER  = user supplied IA array
5525!     NIAUSER = length of IAUSER array
5526!     JAUSER  = user supplied JA vector
5527!     NJAUSER = length of JAUSER array
5528!     Results:
5529!     IA(IADIM), IADIM, JA(JADIM), JAMIN, SPARSE
5530! ..
5531     IMPLICIT NONE
5532! ..
5533! .. Scalar Arguments ..
5534        INTEGER, INTENT (IN) :: NIAUSER, NJAUSER
5535! ..
5536! .. Array Arguments ..
5537        INTEGER, INTENT (IN) :: IAUSER(NIAUSER), JAUSER(NJAUSER)
5538! ..
5539! .. Local Scalars ..
5540        INTEGER :: JER
5541        CHARACTER (80) :: MSG
5542! ..
5543! .. Intrinsic Functions ..
5544        INTRINSIC ALLOCATED
5545! ..
5546! .. FIRST EXECUTABLE STATEMENT USERSETS_IAJA
5547! ..
5548!       Check that SET_OPTS has been called:
5549        IF (.NOT.OPTS_CALLED) THEN
5550          MSG = 'You have not called SET_OPTS before'
5551          CALL XERRDV(MSG,860,1,0,0,0,0,ZERO,ZERO)
5552          MSG = 'calling USERSETS_IAJA.'
5553          CALL XERRDV(MSG,860,2,0,0,0,0,ZERO,ZERO)
5554        END IF
5555        SPARSE = .FALSE.
5556        IAJA_CALLED = .FALSE.
5557        IADIM = NIAUSER
5558        JADIM = NJAUSER
5559        IF (ALLOCATED(IA)) THEN
5560          DEALLOCATE (IA,JA,STAT=JER)
5561          CALL CHECK_STAT(JER,170)
5562        END IF
5563        ALLOCATE (IA(IADIM),JA(JADIM),STAT=JER)
5564        IF (JER/=0) THEN
5565          MSG = 'Check your values of NIAUSER and NJAUSER'
5566          CALL XERRDV(MSG,870,1,0,0,0,0,ZERO,ZERO)
5567          MSG = 'in your call to USERSETS_IAJA.'
5568          CALL XERRDV(MSG,870,2,0,0,0,0,ZERO,ZERO)
5569        END IF
5570        CALL CHECK_STAT(JER,180)
5571        IA(1:IADIM) = IAUSER(1:IADIM)
5572        JA(1:JADIM) = JAUSER(1:JADIM)
5573!       Set the flags to indicate to DVODE_F90 that IA and JA have
5574!       been loaded successfully.
5575        SPARSE = .TRUE.
5576        IAJA_CALLED = .TRUE.
5577        RETURN
5578
5579      END SUBROUTINE USERSETS_IAJA
5580!_______________________________________________________________________
5581
5582      SUBROUTINE SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB,IAUSER,NIAUSER, &
5583        JAUSER,NJAUSER)
5584! ..
5585!     Approximate or allow the user to supply the sparse Jacobian
5586!     structure pointer arrays IA and JA for DVODE_F90 (not called
5587!     by DVODE_F90).
5588! ..
5589!     Caution:
5590!     If it is called, SET_IAJA must be called after the call to
5591!     SET_OPTS.
5592!     Usage:
5593!     SET_IAJA may be called in one of two ways:
5594!     CALL SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB)
5595!       In this case IA and JA will be determined using calls
5596!       to your derivative routine DFN.
5597!     CALL SET_IAJA(DFN,NEQ,T,Y,FMIN,NTURB,DTURB,IAUSER,NIAUSER, &
5598!       JAUSER,NJAUSER)
5599!       In this case, IAUSER of length NIAUSER will be used for
5600!       IA; and JAUSER of length NJAUSER will be used for JA.
5601!       T, Y, FMIN, NTURB, and DTURB will be ignored (though
5602!       they must be present in the argument list).
5603!
5604!     Arguments:
5605!     DFN     = VODE derivative subroutine
5606!     NEQ     = Number of odes
5607!     T       = independent variable t
5608!     Y       = solution y(t)
5609!     FMIN    = Jacobian threshold value. Elements of the Jacobian
5610!               with magnitude smaller than FMIN will be ignored.
5611!               FMIN will be ignored if it is less than or equal
5612!               to ZERO.
5613!     NTURB   = Perturbation flag. If NTURB=1, component I of Y
5614!               will be perturbed by by 1.01D0.
5615!               If NTURB=NEQ, component I of Y will be perturbed
5616!               by ONE + DTURB(I).
5617!     DTURB   = perturbation vector of length 1 or NEQ.
5618!     If these four optional parameters are present, IAUSER and JAUSER
5619!     will be copied to IA and JA rather than making derivative calls
5620!     to approximate IA and JA:
5621!     IAUSER  = user supplied IA array
5622!     NIAUSER = length of IAUSER array
5623!     JAUSER  = user supplied JA vector
5624!     NJAUSER = length of JAUSER array
5625!     Results:
5626!     IA(IADIM), IADIM, IMIN, JA(JADIM), JAMIN, JMIN, SPARSE
5627!     Allocated but free for further use by DVODE_F90:
5628!     FTEMP(NEQ), FPTEMP(NEQ)
5629! ..
5630     IMPLICIT NONE
5631! ..
5632! .. Scalar Arguments ..
5633        KPP_REAL, INTENT (IN) :: FMIN, T
5634        INTEGER, INTENT (IN) :: NEQ, NTURB
5635        INTEGER, OPTIONAL, INTENT (IN) :: NIAUSER, NJAUSER
5636! ..
5637! .. Array Arguments ..
5638        KPP_REAL, INTENT (INOUT) :: DTURB(*), Y(NEQ)
5639        INTEGER, OPTIONAL, INTENT (IN) :: IAUSER(:), JAUSER(:)
5640! ..
5641! .. Subroutine Arguments ..
5642        EXTERNAL DFN
5643! ..
5644! .. Local Scalars ..
5645        KPP_REAL :: AIJ, DTRB, EMIN, RJ, YJ, YJSAVE, YPJ
5646        INTEGER :: I, J, JER, JP1, K, MTURB
5647        CHARACTER (80) :: MSG
5648! ..
5649! .. Intrinsic Functions ..
5650        INTRINSIC ABS, ALLOCATED, EPSILON, MAX, MIN, PRESENT
5651! ..
5652! .. FIRST EXECUTABLE STATEMENT SET_IAJA
5653! ..
5654        SPARSE = .FALSE.
5655        IAJA_CALLED = .FALSE.
5656        IF (NEQ<1) GOTO 30
5657
5658!       Check if the user is supplying the IA and JA arrays.
5659        IF (PRESENT(IAUSER)) THEN
5660!         If IAUSER is present, so must be NIAUSER, JAUSER,
5661!         and NJAUSER.
5662          IF (.NOT.(PRESENT(NIAUSER))) GOTO 30
5663          IF (.NOT.(PRESENT(JAUSER))) GOTO 30
5664          IF (.NOT.(PRESENT(NJAUSER))) GOTO 30
5665          IF (NIAUSER<NEQ+1 .OR. NJAUSER<1) GOTO 30
5666          IADIM = MIN(NIAUSER,NEQ+1)
5667          IMIN = IADIM
5668          JADIM = NJAUSER
5669          JMIN = NJAUSER
5670          IF (ALLOCATED(IA)) THEN
5671            DEALLOCATE (IA,JA,FTEMP,FPTEMP,STAT=JER)
5672            CALL CHECK_STAT(JER,190)
5673          END IF
5674          ALLOCATE (IA(IADIM),JA(JADIM),FTEMP(NEQ),FPTEMP(NEQ),STAT=JER)
5675          CALL CHECK_STAT(JER,200)
5676          IA(1:IADIM) = IAUSER(1:IADIM)
5677          JA(1:JADIM) = JAUSER(1:JADIM)
5678          GOTO 40
5679        END IF
5680
5681!       Determine IA and JA using derivative calls.
5682
5683!       Jacobian element magnitude threshold value.
5684        IF (FMIN>ZERO) THEN
5685          EMIN = MAX(FMIN,ZERO)
5686        ELSE
5687          EMIN = ZERO
5688        END IF
5689
5690!       Solution perturbation factors.
5691        IF (NTURB>0) THEN
5692          IF (NTURB<1 .OR. (NTURB>1 .AND. NTURB/=NEQ)) GOTO 30
5693          IF (NTURB==NEQ) THEN
5694            DO I = 1, NEQ
5695              DTURB(I) = MAX(DTURB(I),HUNDRETH)
5696            END DO
5697          ELSE
5698            MTURB = 1
5699            DTRB = MAX(DTURB(1),HUNDRETH)
5700          END IF
5701        ELSE
5702          MTURB = 1
5703          DTRB = HUNDRETH
5704        END IF
5705
5706        JADIM = MIN(NEQ*NEQ,MAX(1000,NZ_SWAG))
5707        ADDTOJA = MAX(1000,NZ_SWAG)
5708!       Loop point for array allocation.
570910      CONTINUE
5710        IF (ALLOCATED(IA)) THEN
5711          DEALLOCATE (IA,JA,FTEMP,FPTEMP,STAT=JER)
5712          CALL CHECK_STAT(JER,210)
5713        END IF
5714        IMIN = NEQ + 1
5715        IADIM = NEQ + 1
5716        JMIN = 0
5717        JADIM = JADIM + ADDTOJA
5718        IF (JADIM>MAX_ARRAY_SIZE) THEN
5719          MSG = 'Maximum array size exceeded. Stopping.'
5720          CALL XERRDV(MSG,880,2,0,0,0,0,ZERO,ZERO)
5721        END IF
5722        ALLOCATE (IA(IADIM),JA(JADIM),FTEMP(NEQ),FPTEMP(NEQ),STAT=JER)
5723        CALL CHECK_STAT(JER,220)
5724
5725!       f = y'(t,y).
5726        CALL DFN(NEQ,T,Y,FTEMP)
5727        IA(1) = 1
5728        K = 1
5729
5730!       Calculate unit roundoff and powers of it used if JACSP
5731!       is used.
5732        UROUND = EPSILON(ONE)
5733
5734!       Successively perturb each of the solution components and
5735!       calculate the corresponding derivatives.
5736        DO J = 1, NEQ
5737          IF (MTURB==NEQ) DTRB = DTURB(J)
5738          YJ = Y(J)
5739          YJSAVE = YJ
5740          IF (ABS(YJ)<=ZERO) YJ = HUN*UROUND
5741          YPJ = YJ*(ONE+DTRB)
5742          RJ = ABS(YPJ-YJ)
5743          IF (ABS(RJ)<=ZERO) RJ = HUN*UROUND
5744          IF (ABS(RJ)<=ZERO) GOTO 30
5745          Y(J) = YPJ
5746          CALL DFN(NEQ,T,Y,FPTEMP)
5747          DO 20 I = 1, NEQ
5748!           Estimate the Jacobian element.
5749            AIJ = ABS(FPTEMP(I)-FTEMP(I))/RJ
5750            IF ((AIJ<=EMIN) .AND. (I/=J)) GOTO 20
5751!           Need more storage for JA.
5752            IF (K>JADIM) GOTO 10
5753            JMIN = K
5754            JA(K) = I
5755            K = K + 1
575620        CONTINUE
5757          JP1 = J + 1
5758          IA(JP1) = K
5759          Y(J) = YJSAVE
5760        END DO
5761        GOTO 40
576230      CONTINUE
5763        MSG = 'An error occurred in subroutine SET_IAJA.'
5764        CALL XERRDV(MSG,890,2,0,0,0,0,ZERO,ZERO)
5765
576640      CONTINUE
5767!       Set the flags to indicate to DVODE_F90 that IA and JA have
5768!       been calculated successfully.
5769        SPARSE = .TRUE.
5770        IAJA_CALLED = .TRUE.
5771
5772!       Trim JA.
5773        ALLOCATE (JATEMP(JMIN),STAT=JER)
5774        CALL CHECK_STAT(JER,230)
5775        JATEMP(1:JMIN) = JA(1:JMIN)
5776        DEALLOCATE (JA,STAT=JER)
5777        CALL CHECK_STAT(JER,240)
5778        ALLOCATE (JA(JMIN),STAT=JER)
5779        CALL CHECK_STAT(JER,250)
5780        JA(1:JMIN) = JATEMP(1:JMIN)
5781        DEALLOCATE (JATEMP,STAT=JER)
5782        CALL CHECK_STAT(JER,260)
5783        JADIM = JMIN
5784        RETURN
5785
5786      END SUBROUTINE SET_IAJA
5787!_______________________________________________________________________
5788
5789      SUBROUTINE DVODE(F,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTS,JAC,GFUN)
5790! ..
5791! This is the core driver (modified original DVODE.F driver).
5792! ..
5793! The documentation prologue was moved nearer the top of the file.
5794! ..
5795     IMPLICIT NONE
5796! ..
5797! .. Structure Arguments ..
5798        TYPE (VODE_OPTS) :: OPTS
5799! ..
5800! .. Scalar Arguments ..
5801        KPP_REAL, INTENT (INOUT) :: T, TOUT
5802        INTEGER, INTENT (INOUT) :: ISTATE
5803        INTEGER, INTENT (IN) :: ITASK, NEQ
5804! ..
5805! .. Array Arguments ..
5806        KPP_REAL, INTENT (INOUT) :: Y(*)
5807! ..
5808! .. Subroutine Arguments ..
5809        EXTERNAL F, GFUN, JAC
5810! ..
5811! .. Local Scalars ..
5812        KPP_REAL :: ATOLI, BIG, EWTI, H0, HMAX, HMX, RH, RTOLI, SIZEST, &
5813          TCRIT, TNEXT, TOLSF, TP
5814        INTEGER :: I, IER, IFLAG, IMXER, IOPT, IPCUTH, IRFP, IRT, ITOL, JCO, &
5815          JER, KGO, LENIW, LENJ, LENP, LENRW, LENWM, LF0, MBAND, MF, MFA, ML, &
5816          MU, NG, NITER, NSLAST
5817        LOGICAL :: IHIT
5818        CHARACTER (80) :: MSG
5819! ..
5820! .. Intrinsic Functions ..
5821        INTRINSIC ABS, ALLOCATED, EPSILON, MAX, MIN, SIGN, SQRT
5822! ..
5823! The following internal PRIVATE variable blocks contain variables which
5824! are communicated between subroutines in the DVODE package, or which
5825! are to be saved between calls to DVODE.
5826! In each block, real variables precede integers.
5827! The variables stored in the internal PRIVATE variable blocks are as
5828! follows:
5829! ACNRM  = Weighted r.m.s. norm of accumulated correction vectors.
5830! CCMXJ  = Threshhold on DRC for updating the Jacobian. (See DRC.)
5831! CONP   = The saved value of TQ(5).
5832! CRATE  = Estimated corrector convergence rate constant.
5833! DRC    = Relative change in H*RL1 since last DVJAC call.
5834! EL     = Real array of integration coefficients. See DVSET.
5835! ETA    = Saved tentative ratio of new to old H.
5836! ETAMAX = Saved maximum value of ETA to be allowed.
5837! H      = The step size.
5838! HMIN   = The minimum absolute value of the step size H to be used.
5839! HMXI   = Inverse of the maximum absolute value of H to be used.
5840!          HMXI = 0.0 is allowed and corresponds to an infinite HMAX.
5841! HNEW   = The step size to be attempted on the next step.
5842! HSCAL  = Stepsize in scaling of YH array.
5843! PRL1   = The saved value of RL1.
5844! RC     = Ratio of current H*RL1 to value on last DVJAC call.
5845! RL1    = The reciprocal of the coefficient EL(2).
5846! TAU    = Real vector of past NQ step sizes, length 13.
5847! TQ     = A real vector of length 5 in which DVSET stores constants
5848!          used for the convergence test, the error test, and the
5849!          selection of H at a new order.
5850! TN     = The independent variable, updated on each step taken.
5851! UROUND = The machine unit roundoff. The smallest positive real number
5852!          such that  1.0 + UROUND /= 1.0
5853! ICF    = Integer flag for convergence failure in DVNLSD:
5854!            0 means no failures.
5855!            1 means convergence failure with out of date Jacobian
5856!                   (recoverable error).
5857!            2 means convergence failure with current Jacobian or
5858!                   singular matrix (unrecoverable error).
5859! INIT   = Saved integer flag indicating whether initialization of the
5860!          problem has been done (INIT = 1) or not.
5861! IPUP   = Saved flag to signal updating of Newton matrix.
5862! JCUR   = Output flag from DVJAC showing Jacobian status:
5863!            JCUR = 0 means J is not current.
5864!            JCUR = 1 means J is current.
5865! JSTART = Integer flag used as input to DVSTEP:
5866!            0  means perform the first step.
5867!            1  means take a new step continuing from the last.
5868!           -1  means take the next step with a new value of MAXORD,
5869!               HMIN, HMXI, N, METH, MITER, and/or matrix parameters.
5870!          On return, DVSTEP sets JSTART = 1.
5871! JSV    = Integer flag for Jacobian saving, = sign(MF).
5872! KFLAG  = A completion code from DVSTEP with the following meanings:
5873!               0      the step was successful.
5874!              -1      the requested error could not be achieved.
5875!              -2      corrector convergence could not be achieved.
5876!              -3, -4  fatal error in DVNLSD(can not occur here).
5877! KUTH   = Input flag to DVSTEP showing whether H was reduced by the
5878!          driver. KUTH = 1 if H was reduced, = 0 otherwise.
5879! L      = Integer variable, NQ + 1, current order plus one.
5880! LMAX   = MAXORD + 1 (used for dimensioning).
5881! LOCJS  = A pointer to the saved Jacobian, whose storage starts at
5882!          WM(LOCJS), if JSV = 1.
5883! LYH    = Saved integer pointer to segments of RWORK and IWORK.
5884! MAXORD = The maximum order of integration method to be allowed.
5885! METH/MITER = The method flags. See MF.
5886! MSBJ   = The maximum number of steps between J evaluations, = 50.
5887! MXHNIL = Saved value of optional input MXHNIL.
5888! MXSTEP = Saved value of optional input MXSTEP.
5889! N      = The number of first-order ODEs, = NEQ.
5890! NEWH   = Saved integer to flag change of H.
5891! NEWQ   = The method order to be used on the next step.
5892! NHNIL  = Saved counter for occurrences of T + H = T.
5893! NQ     = Integer variable, the current integration method order.
5894! NQNYH  = Saved value of NQ*NYH.
5895! NQWAIT = A counter controlling the frequency of order changes.
5896!          An order change is about to be considered if NQWAIT = 1.
5897! NSLJ   = The number of steps taken as of the last Jacobian update.
5898! NSLP   = Saved value of NST as of last Newton matrix update.
5899! NYH    = Saved value of the initial value of NEQ.
5900! HU     = The step size in t last used.
5901! NCFN   = Number of nonlinear convergence failures so far.
5902! NETF   = The number of error test failures of the integrator so far.
5903! NFE    = The number of f evaluations for the problem so far.
5904! NJE    = The number of Jacobian evaluations so far.
5905! NLU    = The number of matrix LU decompositions so far.
5906! NNI    = Number of nonlinear iterations so far.
5907! NQU    = The method order last used.
5908! NST    = The number of steps taken for the problem so far.
5909! Block 0.
5910! Retrieve the necessary flags from the OPTIONS structure and manage
5911! the storage allocation.
5912! ..
5913! .. FIRST EXECUTABLE STATEMENT DVODE
5914! ..
5915!       Retrieve the local flags from the options structure.
5916        IOPT = OPTS%IOPT
5917        ITOL = OPTS%ITOL
5918        MF = OPTS%MF
5919        METH = OPTS%METH
5920        MITER = OPTS%MITER
5921        MOSS = OPTS%MOSS
5922        NG = OPTS%NG
5923
5924!       Allocate the necessary storage for RWORK and IWORK. (Assume that
5925!       both or neither of the arrays are allocated.)
5926
5927!       If we are starting a new problem, deallocate the old RWORK and
5928!       IWORK arrays if they were allocated in a previous call. Also
5929!       manage the event residual arrays.
5930
5931        IF (ISTATE==1) THEN
5932          IF (ALLOCATED(DTEMP)) THEN
5933            DEALLOCATE (DTEMP,YTEMP,STAT=JER)
5934            CALL CHECK_STAT(JER,270)
5935          END IF
5936          IF (ALLOCATED(RWORK)) THEN
5937            DEALLOCATE (RWORK,IWORK,ACOR,SAVF,EWT,WM,STAT=JER)
5938            CALL CHECK_STAT(JER,280)
5939          END IF
5940          IF (ALLOCATED(JROOT)) THEN
5941            DEALLOCATE (JROOT,G0,G1,GX,STAT=JER)
5942            CALL CHECK_STAT(JER,290)
5943          END IF
5944          IF (ALLOCATED(YMAX)) THEN
5945            DEALLOCATE (YMAX,STAT=JER)
5946            CALL CHECK_STAT(JER,300)
5947          END IF
5948        END IF
5949
5950!       If the user has made changes and called DVODE_F90 with ISTATE=3,
5951!       temporarily save the necessary portion of the Nordsieck array
5952!       and then release RWORK and IWORK. Also, save the contents of
5953!       the WM array and release WM. Note: ACOR, SAVF, and EWT do not
5954!       need to be saved.
5955
5956        IF (ISTATE==3) THEN
5957          IF (IOPT/=1) THEN
5958            MAXORD = MORD(METH)
5959          ELSE
5960            MAXORD = IUSER(5)
5961            IF (MAXORD<0) GOTO 520
5962            IF (MAXORD==0) MAXORD = 100
5963            MAXORD = MIN(MAXORD,MORD(METH))
5964          END IF
5965          IF (MAXORD<NQ) THEN
5966!           If MAXORD is less than NQ, save column NQ+2 of YH for
5967!           later use.
5968            IF (ALLOCATED(YHNQP2)) THEN
5969              DEALLOCATE (YHNQP2,STAT=JER)
5970              CALL CHECK_STAT(JER,310)
5971            END IF
5972            ALLOCATE (YHNQP2(NEQ),STAT=JER)
5973            CALL CHECK_STAT(JER,320)
5974            CALL DCOPY_F90(NEQ,RWORK(LYH+NYH*(MAXORD+1)),1,YHNQP2,1)
5975          END IF
5976          LYHTEMP = MIN((PREVIOUS_MAXORD+1)*NYH+LYH-1,(MAXORD+1)*NYH+LYH-1)
5977          ALLOCATE (YHTEMP(LYHTEMP),STAT=JER)
5978          CALL CHECK_STAT(JER,330)
5979!         Save YH.
5980          YHTEMP(1:LYHTEMP) = RWORK(1:LYHTEMP)
5981!         Save WM.
5982          LWMTEMP = LWMDIM
5983          ALLOCATE (WMTEMP(LWMTEMP),STAT=JER)
5984          CALL CHECK_STAT(JER,340)
5985          WMTEMP(1:LWMTEMP) = WM(1:LWMTEMP)
5986          IF (ALLOCATED(DTEMP)) THEN
5987             DEALLOCATE (DTEMP,YTEMP,STAT=JER)
5988             CALL CHECK_STAT(JER,350)
5989          END IF
5990          DEALLOCATE (RWORK,IWORK,YMAX,ACOR,SAVF,EWT,WM,STAT=JER)
5991          CALL CHECK_STAT(JER,360)
5992        END IF
5993
5994!     Allocate the RWORK and WM work arrays if they haven't already
5995!     been allocated in a previous call.
5996!     LRW = 20 + (MAXORD + 1) * NEQ
5997!     LWMDIM =     
5998!            0                        for MF = 10,
5999!            2 * NEQ**2               for MF = 11 or 12,
6000!            NEQ**2                   for MF = -11 or -12,
6001!            NEQ                      for MF = 13,
6002!            (3*ML + 2*MU + 2) * NEQ  for MF = 14 or 15,
6003!            (2*ML + MU + 1) * NEQ    for MF = -14 or -15,
6004!            0                        for MF = 16 or 17,
6005!            0                        for MF = -16 or -17,
6006!            0                        for MF = 20,
6007!            2 * NEQ**2               for MF = 21 or 22,
6008!            NEQ**2                   for MF = -21 or -22,
6009!            NEQ                      for MF = 23,
6010!            (3*ML + 2*MU + 2) * NEQ  for MF = 24 or 25,
6011!            (2*ML + MU + 1) * NEQ    for MF = -24 or -25,
6012!            0                        for MF = 26 or 27,
6013!            0                        for MF = -26 or -27.
6014        IF (ALLOCATED(RWORK)) THEN
6015        ELSE
6016          MFA = ABS(MF)
6017          IF (IOPT/=1) THEN
6018            MAXORD = MORD(METH)
6019          ELSE
6020            MAXORD = IUSER(5)
6021            IF (MAXORD<0) GOTO 520
6022            IF (MAXORD==0) MAXORD = 100
6023            MAXORD = MIN(MAXORD,MORD(METH))
6024          END IF
6025          LRW = LRWUSER + (MAXORD+1)*NEQ
6026!        IF (MITER == 0) LRW = LRW - 2
6027          LRW = LRW - 2
6028          IF (MF==10) THEN
6029            LWMDIM = 0
6030          ELSE IF (MF==11 .OR. MF==12) THEN
6031            LWMDIM = 2*NEQ**2
6032          ELSE IF (MF==-11 .OR. MF==-12) THEN
6033            LWMDIM = NEQ**2
6034          ELSE IF (MF==13) THEN
6035            LWMDIM = NEQ
6036          ELSE IF (MF==14 .OR. MF==15) THEN
6037            ML = IUSER(1)
6038            MU = IUSER(2)
6039            IF (ML<0 .OR. ML>=NEQ) GOTO 500
6040            IF (MU<0 .OR. MU>=NEQ) GOTO 510
6041            LWMDIM = (3*ML+2*MU+2)*NEQ
6042          ELSE IF (MF==-14 .OR. MF==-15) THEN
6043            ML = IUSER(1)
6044            MU = IUSER(2)
6045            IF (ML<0 .OR. ML>=NEQ) GOTO 500
6046            IF (MU<0 .OR. MU>=NEQ) GOTO 510
6047            LWMDIM = (2*ML+MU+1)*NEQ
6048          ELSE IF (MF==16 .OR. MF==17) THEN
6049            LWMDIM = 0
6050          ELSE IF (MF==-16 .OR. MF==-17) THEN
6051            LWMDIM = 0
6052          ELSE IF (MF==20) THEN
6053            LWMDIM = 0
6054          ELSE IF (MF==21 .OR. MF==22) THEN
6055            LWMDIM = 2*NEQ**2
6056          ELSE IF (MF==-21 .OR. MF==-22) THEN
6057            LWMDIM = NEQ**2
6058          ELSE IF (MF==23) THEN
6059            LWMDIM = NEQ
6060          ELSE IF (MF==24 .OR. MF==25) THEN
6061            ML = IUSER(1)
6062            MU = IUSER(2)
6063            IF (ML<0 .OR. ML>=NEQ) GOTO 500
6064            IF (MU<0 .OR. MU>=NEQ) GOTO 510
6065            LWMDIM = (3*ML+2*MU+2)*NEQ
6066          ELSE IF (MF==-24 .OR. MF==-25) THEN
6067            ML = IUSER(1)
6068            MU = IUSER(2)
6069            IF (ML<0 .OR. ML>=NEQ) GOTO 500
6070            IF (MU<0 .OR. MU>=NEQ) GOTO 510
6071            LWMDIM = (2*ML+MU+1)*NEQ
6072          ELSE IF (MF==26 .OR. MF==27) THEN
6073            LWMDIM = 0
6074          ELSE IF (MF==-26 .OR. MF==-27) THEN
6075            LWMDIM = 0
6076          END IF
6077!         LWMDIM = LWMDIM + 2
6078          ALLOCATE (RWORK(LRW),WM(LWMDIM),STAT=JER)
6079          CALL CHECK_STAT(JER,370)
6080          RWORK(1:LRW) = ZERO
6081          WM(1:LWMDIM) = ZERO
6082          IF (.NOT.ALLOCATED(DTEMP)) THEN
6083             ALLOCATE (DTEMP(NEQ),YTEMP(NEQ),STAT=JER)
6084             CALL CHECK_STAT(JER,380)
6085          END IF
6086          ALLOCATE (ACOR(NEQ),SAVF(NEQ),EWT(NEQ),STAT=JER)
6087          CALL CHECK_STAT(JER,390)
6088!         If necessary, reload the saved portion of the Nordsieck
6089!         array and the WM array, saved above.
6090          IF (ISTATE==3) THEN
6091            RWORK(1:LYHTEMP) = YHTEMP(1:LYHTEMP)
6092            I = MIN(LWMTEMP,LWMDIM)
6093!           WM(1:LWMTEMP) = WMTEMP(1:LWMTEMP)
6094            WM(1:I) = WMTEMP(1:I)
6095            DEALLOCATE (YHTEMP,WMTEMP,STAT=JER)
6096            CALL CHECK_STAT(JER,400)
6097          END IF
6098          RWORK(1:LRWUSER) = RUSER(1:LRWUSER)
6099!         IUSER: = LIWUSER if MITER = 0 or 3 (MF = 10, 13, 20, 23)
6100!                = LIWUSER + NEQ otherwise
6101!                  (ABS(MF) = 11,12,14,15,16,17,21,22,24,25,26,27).
6102          LIW = LIWUSER + NEQ
6103          IF (MITER==0 .OR. MITER==3) LIW = LIWUSER
6104          ALLOCATE (IWORK(LIW),STAT=JER)
6105          CALL CHECK_STAT(JER,410)
6106          IWORK(1:LIWUSER) = IUSER(1:LIWUSER)
6107!         Allocate the YMAX vector.
6108          ALLOCATE (YMAX(NEQ),STAT=JER)
6109          CALL CHECK_STAT(JER,420)
6110        END IF
6111!       Allocate the event arrays if they haven't already been allocated
6112!       in a previous call.
6113        IF (ALLOCATED(JROOT)) THEN
6114        ELSE
6115          IF (NG>0) THEN
6116            ALLOCATE (JROOT(NG),G0(NG),G1(NG),GX(NG),STAT=JER)
6117            CALL CHECK_STAT(JER,430)
6118          END IF
6119        END IF
6120
6121! Block A.
6122! This code block is executed on every call. It tests ISTATE and
6123! ITASK for legality and branches appropriately.
6124! If ISTATE > 1 but the flag INIT shows that initialization has
6125! not yet been done, an error return occurs.
6126! If ISTATE = 1 and TOUT = T, return immediately.
6127! The user portion of RWORK and IWORK are reloaded since something
6128! may have changed since the previous visit.
6129
6130        RWORK(1:LRWUSER) = RUSER(1:LRWUSER)
6131        IWORK(1:LIWUSER) = IUSER(1:LIWUSER)
6132        IF (ISTATE<1 .OR. ISTATE>3) GOTO 420
6133        IF (ITASK<1 .OR. ITASK>5) GOTO 430
6134        ITASKC = ITASK
6135        IF (ISTATE==1) GOTO 10
6136        IF (INIT/=1) GOTO 440
6137        IF (ISTATE==2) GOTO 130
6138        GOTO 20
613910      INIT = 0
6140        IF (ABS(TOUT-T)<=ZERO) THEN
6141          RUSER(1:LRWUSER) = RWORK(1:LRWUSER)
6142          IUSER(1:LIWUSER) = IWORK(1:LIWUSER)
6143          RETURN
6144        END IF
6145
6146! Block B.
6147! The next code block is executed for the initial call (ISTATE = 1),
6148! or for a continuation call with parameter changes (ISTATE = 3).
6149! It contains checking of all input and various initializations.
6150
6151!       First check legality of the non-optional input NEQ, ITOL, IOPT,
6152!       MF, ML, and MU.
6153
615420      IF (NEQ<=0) GOTO 450
6155        IF (ISTATE==1) GOTO 30
6156        IF (NEQ>N) GOTO 460
6157        IF (NEQ/=N) GOTO 465
615830      N = NEQ
6159        IF (ITOL<1 .OR. ITOL>4) GOTO 470
6160        IF (IOPT<0 .OR. IOPT>1) GOTO 480
6161        JSV = SIGN(1,MF)
6162        INEWJ = (1-JSV)/2
6163        MFA = ABS(MF)
6164        METH = MFA/10
6165        MITER = MFA - 10*METH
6166        IF (METH<1 .OR. METH>2) GOTO 490
6167        IF (MITER<0 .OR. MITER>7) GOTO 490
6168        IF (MITER<=3) GOTO 40
6169        IF (MITER<=5) THEN
6170          ML = IWORK(1)
6171          MU = IWORK(2)
6172          IF (ML<0 .OR. ML>=N) GOTO 500
6173          IF (MU<0 .OR. MU>=N) GOTO 510
6174        END IF
617540      CONTINUE
6176        IF (NG<0) GOTO 700
6177        IF (ISTATE==1) GOTO 50
6178        IF (IRFND==0 .AND. NG/=NGC) GOTO 710
617950      NGC = NG
6180!       Next process and check the optional input.
6181        IF (IOPT==1) GOTO 60
6182        MAXORD = MORD(METH)
6183        MXSTEP = MXSTP0
6184        MXHNIL = MXHNL0
6185        IF (ISTATE==1) H0 = ZERO
6186        HMXI = ZERO
6187        HMIN = ZERO
6188        GOTO 80
618960      MAXORD = IWORK(5)
6190        IF (MAXORD<0) GOTO 520
6191        IF (MAXORD==0) MAXORD = 100
6192        MAXORD = MIN(MAXORD,MORD(METH))
6193        MXSTEP = IWORK(6)
6194        IF (MXSTEP<0) GOTO 530
6195        IF (MXSTEP==0) MXSTEP = MXSTP0
6196        MXHNIL = IWORK(7)
6197        IF (MXHNIL<0) GOTO 540
6198        IF (MXHNIL==0) MXHNIL = MXHNL0
6199        IF (ISTATE/=1) GOTO 70
6200        H0 = RWORK(5)
6201        IF ((TOUT-T)*H0<ZERO) GOTO 550
620270      HMAX = RWORK(6)
6203        IF (HMAX<ZERO) GOTO 560
6204        HMXI = ZERO
6205        IF (HMAX>ZERO) HMXI = ONE/HMAX
6206        HMIN = RWORK(7)
6207        IF (HMIN<ZERO) GOTO 570
6208        SETH = RWORK(8)
6209        IF (SETH<ZERO) GOTO 690
6210!       Check the nonnegativity information.
6211        IF (BOUNDS) THEN
6212          IF (NDX<1 .OR. NDX>NEQ) THEN
6213            MSG = 'The size of the CONSTRAINED vector'
6214            CALL XERRDV(MSG,900,1,0,0,0,0,ZERO,ZERO)
6215            MSG = 'must be between 1 and NEQ.'
6216            CALL XERRDV(MSG,900,2,0,0,0,0,ZERO,ZERO)
6217          END IF
6218          DO I = 1, NDX
6219            IF (IDX(I)<1 .OR. IDX(I)>N) THEN
6220              MSG = 'Each component of THE CONSTRAINED'
6221              CALL XERRDV(MSG,910,1,0,0,0,0,ZERO,ZERO)
6222              MSG = 'vector must be between 1 and N.'
6223              CALL XERRDV(MSG,910,2,0,0,0,0,ZERO,ZERO)
6224            END IF
6225          END DO
6226        END IF
6227!       Check the sub diagonal and super diagonal arrays.
6228        IF (MITER==4 .OR. MITER==5) THEN
6229           IF (SUBS) THEN
6230              DO I = 1, NSUBS
6231                 IF (SUBDS(I) < 2 .OR. SUBDS(I) > ML+1) THEN
6232                    MSG = 'Each element of SUB_DIAGONALS'
6233                    CALL XERRDV(MSG,920,1,0,0,0,0,ZERO,ZERO)
6234                    MSG = 'must be between 2 and ML + 1.'
6235                    CALL XERRDV(MSG,920,2,0,0,0,0,ZERO,ZERO)
6236                 END IF
6237              END DO
6238           END IF
6239           IF (SUPS) THEN
6240              DO I = 1, NSUPS
6241                 IF (SUPDS(I) < 2 .OR. SUPDS(I) > MU + 1) THEN
6242                    MSG = 'Each element of SUP_DIAGONALS'
6243                    CALL XERRDV(MSG,930,1,0,0,0,0,ZERO,ZERO)
6244                    MSG = 'must be between 2 and MU + 1.'
6245                    CALL XERRDV(MSG,930,2,0,0,0,0,ZERO,ZERO)
6246                 END IF
6247              END DO
6248           END IF
6249!          Compute the banded column grouping.
6250           IF (SUBS .OR. SUPS) THEN
6251             CALL BGROUP(N,EWT,ACOR,YMAX,ML,MU)
6252             BUILD_IAJA = .FALSE.
6253             BUILD_IAJA = .TRUE.
6254             IF (BUILD_IAJA) THEN
6255                CALL BANDED_IAJA(N,ML,MU)
6256                NZB = IAB(N+1) - 1
6257             END IF
6258           END IF
6259        END IF
6260
6261        IF ((MITER==2 .OR. MITER==5) .AND. USE_JACSP) THEN
6262!         Allocate the arrays needed by DVJAC/JACSPD.
6263          IF (ALLOCATED(INDROWDS)) THEN
6264             DEALLOCATE (INDROWDS, INDCOLDS, NGRPDS, IPNTRDS, JPNTRDS, &
6265               IWADS, IWKDS, IOPTDS, YSCALEDS, WKDS, FACDS)
6266             CALL CHECK_STAT(IER,440)
6267          END IF
6268          ALLOCATE (INDROWDS(1), INDCOLDS(1), NGRPDS(1), IPNTRDS(1),   &
6269            JPNTRDS(1), IWADS(1), IWKDS(50+N), IOPTDS(5), YSCALEDS(N), &
6270            WKDS(3*N), FACDS(N), STAT=IER)
6271          CALL CHECK_STAT(IER,450)
6272!         For use in DVJAC:
6273          IOPTDS(4) = 0
6274        END IF
6275
6276! Set work array pointers and check lengths LRW and LIW. Pointers
6277! to segments of RWORK and IWORK are named by prefixing L to the
6278! name of the segment. e.g., the segment YH starts at RWORK(LYH).
6279! Within WM, LOCJS is the location of the saved Jacobian (JSV > 0).
6280
628180      LYH = 21
6282        IF (ISTATE==1) NYH = N
6283        LENRW = LYH + (MAXORD+1)*NYH - 1
6284        IWORK(17) = LENRW
6285        IF (LENRW>LRW) GOTO 580
6286        IF (LENRW/=LRW) GOTO 580
6287        LWM = 1
6288!       Save MAXORD in case the calling program calls with ISTATE=3.
6289        PREVIOUS_MAXORD = MAXORD
6290        JCO = MAX(0,JSV)
6291!       IF (MITER==0) LENWM = 2
6292        IF (MITER==0) LENWM = 0
6293        IF (MITER==1 .OR. MITER==2) THEN
6294!         LENWM = 2 + (1+JCO)*N*N
6295!         LOCJS = N*N + 3
6296          LENWM = (1+JCO)*N*N
6297          LOCJS = N*N + 1
6298        END IF
6299!       IF (MITER==3) LENWM = N + 2
6300        IF (MITER==3) LENWM = N
6301        IF (MITER==4 .OR. MITER==5) THEN
6302          MBAND = ML + MU + 1
6303          LENP = (MBAND+ML)*N
6304          LENJ = MBAND*N
6305!         LENWM = 2 + LENP + JCO*LENJ
6306!         LOCJS = LENP + 3
6307          LENWM = LENP + JCO*LENJ
6308          LOCJS = LENP + 1
6309        END IF
6310        IF (MITER==6 .OR. MITER==7) THEN
6311!         LENWM = 2
6312          LENWM = 0
6313        END IF
6314        IF (LENWM>LWMDIM) GOTO 730
6315        IF (LENWM/=LWMDIM) GOTO 730
6316        LIWM = 1
6317        LENIW = 30 + N
6318        IF (MITER==0 .OR. MITER==3) LENIW = 30
6319        IWORK(18) = LENIW
6320        IF (LENIW>LIW) GOTO 590
6321!       Check RTOL and ATOL for legality.
6322        RTOLI = OPTS%RTOL(1)
6323        ATOLI = OPTS%ATOL(1)
6324        DO I = 1, N
6325          IF (ITOL>=3) RTOLI = OPTS%RTOL(I)
6326          IF (ITOL==2 .OR. ITOL==4) ATOLI = OPTS%ATOL(I)
6327          IF (RTOLI<ZERO) GOTO 600
6328          IF (ATOLI<ZERO) GOTO 610
6329        END DO
6330        IF (ISTATE==1) GOTO 100
6331!       If ISTATE = 3, set flag to signal parameter changes to DVSTEP.
6332        JSTART = -1
6333        IF (NQ<=MAXORD) GOTO 90
6334!       MAXORD was reduced below NQ. Copy YH(*,MAXORD+2) into SAVF.
6335!       YH(*,MAXORD+2) was copied to the YHNQP2 array at the
6336!       beginning of DVODE when the ISTATE=3 call was made.
6337        CALL DCOPY_F90(N,YHNQP2,1,SAVF,1)
6338!       Reload WM1 since LWM may have changed.
633990      IF (MITER>0) WM1 = SQRT(UROUND)
6340!       ISTATC controls the determination of the sparsity arrays
6341!       if the sparse solution option is used.
6342        ISTATC = ISTATE
6343        GOTO 130
6344
6345! Block C.
6346! The next block is for the initial call only (ISTATE = 1).
6347! It contains all remaining initializations, the initial call to F,
6348! and the calculation of the initial step size.
6349! The error weights in EWT are inverted after being loaded.
6350
6351100     UROUND = EPSILON(ONE)
6352        U125 = UROUND ** 0.125_dp
6353        U325 = UROUND ** 0.325_dp
6354!       ISTATC controls the determination of the sparsity arrays if
6355!       the sparse solution option is used.
6356        ISTATC = ISTATE
6357        TN = T
6358        IF (ITASK/=4 .AND. ITASK/=5) GOTO 110
6359        TCRIT = RWORK(1)
6360        IF ((TCRIT-TOUT)*(TOUT-T)<ZERO) GOTO 660
6361        IF (ABS(H0)>ZERO .AND. (T+H0-TCRIT)*H0>ZERO) H0 = TCRIT - T
6362110     JSTART = 0
6363        IF (MITER>0) WM1 = SQRT(UROUND)
6364        CCMXJ = PT2
6365        MSBJ = 50
6366        MSBG = 75
6367        NHNIL = 0
6368        NST = 0
6369        NJE = 0
6370        NNI = 0
6371        NCFN = 0
6372        NETF = 0
6373        NLU = 0
6374        NSLJ = 0
6375        NSLAST = 0
6376        HU = ZERO
6377        NQU = 0
6378        MB28 = 0
6379!_______________________________________________________________________
6380! *****MA48 build change point. Insert this statement.
6381!       MB48 = 0
6382!_______________________________________________________________________
6383        NSLG = 0
6384        NGE = 0
6385!       Initial call to F. (LF0 points to YH(*,2).)
6386        LF0 = LYH + NYH
6387        CALL F(N,T,Y,RWORK(LF0))
6388        NFE = 1
6389!       Load the initial value vector in YH.
6390        CALL DCOPY_F90(N,Y,1,RWORK(LYH),1)
6391!       Load and invert the EWT array. (H is temporarily set to 1.0.)
6392        NQ = 1
6393        H = ONE
6394        CALL DEWSET(N,ITOL,OPTS%RTOL,OPTS%ATOL,RWORK(LYH),EWT)
6395        DO I = 1, N
6396          IF (EWT(I)<=ZERO) GOTO 620
6397          EWT(I) = ONE/EWT(I)
6398        END DO
6399        NNZ = 0
6400        NGP = 0
6401        IF (OPTS%SPARSE) THEN
6402          ISTATC = ISTATE
6403        END IF
6404        IF (ABS(H0)>ZERO) GOTO 120
6405!       Call DVHIN to set initial step size H0 to be attempted.
6406        CALL DVHIN(N,T,RWORK(LYH),RWORK(LF0),F,TOUT,EWT,ITOL,OPTS%ATOL,Y,ACOR, &
6407          H0,NITER,IER)
6408        NFE = NFE + NITER
6409        IF (IER/=0) GOTO 630
6410!       Adjust H0 if necessary to meet HMAX bound.
6411120     RH = ABS(H0)*HMXI
6412        IF (RH>ONE) H0 = H0/RH
6413!       Load H with H0 and scale YH(*,2) by H0.
6414        H = H0
6415        CALL DSCAL_F90(N,H0,RWORK(LF0),1)
6416!       GOTO 270
6417!       Check for a zero of g at T.
6418        IRFND = 0
6419        TOUTC = TOUT
6420        IF (NGC==0) GOTO 210
6421        CALL DVCHECK(1,GFUN,NEQ,Y,RWORK(LYH),NYH,G0,G1,GX,IRT)
6422        IF (IRT==0) GOTO 210
6423        GOTO 720
6424
6425! Block D.
6426! The next code block is for continuation calls only (ISTATE = 2 or 3)
6427! and is to check stop conditions before taking a step.
6428
6429130     NSLAST = NST
6430        IRFP = IRFND
6431        IF (NGC==0) GOTO 140
6432        IF (ITASK==1 .OR. ITASK==4) TOUTC = TOUT
6433        CALL DVCHECK(2,GFUN,NEQ,Y,RWORK(LYH),NYH,G0,G1,GX,IRT)
6434        IF (IRT/=1) GOTO 140
6435        IRFND = 1
6436        ISTATE = 3
6437        T = T0ST
6438        GOTO 330
6439140     CONTINUE
6440        IRFND = 0
6441        IF (IRFP==1 .AND. (ABS(TLAST-TN)>ZERO) .AND. ITASK==2) GOTO 310
6442        KUTH = 0
6443        GOTO (150,200,160,170,180) ITASK
6444150     IF ((TN-TOUT)*H<ZERO) GOTO 200
6445        CALL DVINDY_CORE(TOUT,0,RWORK(LYH),NYH,Y,IFLAG)
6446        IF (IFLAG/=0) GOTO 680
6447        IF (BOUNDS) THEN
6448          DO I = 1, NDX
6449            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
6450            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
6451          END DO
6452        END IF
6453        T = TOUT
6454        GOTO 320
6455160     TP = TN - HU*(ONE+HUN*UROUND)
6456        IF ((TP-TOUT)*H>ZERO) GOTO 640
6457        IF ((TN-TOUT)*H<ZERO) GOTO 200
6458        GOTO 310
6459170     TCRIT = RWORK(1)
6460        IF ((TN-TCRIT)*H>ZERO) GOTO 650
6461        IF ((TCRIT-TOUT)*H<ZERO) GOTO 660
6462        IF ((TN-TOUT)*H<ZERO) GOTO 190
6463        CALL DVINDY_CORE(TOUT,0,RWORK(LYH),NYH,Y,IFLAG)
6464        IF (IFLAG/=0) GOTO 680
6465        IF (BOUNDS) THEN
6466          DO I = 1, NDX
6467            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
6468            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
6469          END DO
6470        END IF
6471        T = TOUT
6472        GOTO 320
6473180     TCRIT = RWORK(1)
6474        IF ((TN-TCRIT)*H>ZERO) GOTO 650
6475190     HMX = ABS(TN) + ABS(H)
6476        IHIT = ABS(TN-TCRIT) <= HUN*UROUND*HMX
6477        IF (IHIT) GOTO 310
6478        TNEXT = TN + HNEW*(ONE+FOUR*UROUND)
6479        IF ((TNEXT-TCRIT)*H<=ZERO) GOTO 200
6480        H = (TCRIT-TN)*(ONE-FOUR*UROUND)
6481        KUTH = 1
6482
6483! Block E.
6484! The next block is normally executed for all calls and contains
6485! the call to the one-step core integrator DVSTEP. This is a
6486! looping point for the integration steps.
6487! First check for too many steps being taken, update EWT(if not
6488! at start of problem), check for too much accuracy being
6489! requested, and check for H below the roundoff level in T.
6490
6491200     CONTINUE
6492        IF ((NST-NSLAST)>=MXSTEP) GOTO 340
6493        CALL DEWSET(N,ITOL,OPTS%RTOL,OPTS%ATOL,RWORK(LYH),EWT)
6494        DO I = 1, N
6495          IF (EWT(I)<=ZERO) GOTO 350
6496          EWT(I) = ONE/EWT(I)
6497        END DO
6498210     TOLSF = UROUND*DVNORM(N,RWORK(LYH),EWT)
6499        IPCUTH = -1
6500        IF (TOLSF<=ONE) GOTO 220
6501        TOLSF = TOLSF*TWO
6502        IF (NST==0) GOTO 670
6503        GOTO 360
6504220     CONTINUE
6505        IPCUTH = IPCUTH + 1
6506        IF (IPCUTH>=IPCUTH_MAX) THEN
6507          MSG = 'Too many step reductions to prevent'
6508          CALL XERRDV(MSG,940,1,0,0,0,0,ZERO,ZERO)
6509          MSG = 'an infeasible prediction.'
6510          CALL XERRDV(MSG,940,1,0,0,0,0,ZERO,ZERO)
6511!         Retract the solution to TN:
6512          CALL DVNRDN(RWORK(LYH),NYH,N,NQ)
6513          ACOR(1:N) = ZERO
6514          ISTATE = -7
6515          GOTO 410
6516        END IF
6517        IF (ABS((TN+H)-TN)>ZERO) GOTO 230
6518        NHNIL = NHNIL + 1
6519        IF (NHNIL>MXHNIL) GOTO 230
6520        MSG = 'Warning: internal T(=R1) and H(=R2) are such that'
6521        CALL XERRDV(MSG,950,1,0,0,0,0,ZERO,ZERO)
6522        MSG = 'in the machine, T + H = T on the next step.'
6523        CALL XERRDV(MSG,950,1,0,0,0,0,ZERO,ZERO)
6524        MSG = '(H = step size). The solver will continue anyway.'
6525        CALL XERRDV(MSG,950,1,0,0,0,2,TN,H)
6526        IF (NHNIL<MXHNIL) GOTO 230
6527        MSG = 'The above warning has been issued I1 times.'
6528        CALL XERRDV(MSG,950,1,0,0,0,0,ZERO,ZERO)
6529        MSG = 'It will not be issued again for this problem.'
6530        CALL XERRDV(MSG,950,1,1,MXHNIL,0,0,ZERO,ZERO)
6531230     CONTINUE
6532        IF (BOUNDS) THEN
6533!         Check positive components for infeasible prediction; reduce
6534!         step size if infeasible prediction will occur in DVNLSD.
6535          ACOR(1:N) = RWORK(LYH:LYH+N-1)
6536!         Predict:
6537          CALL DVNRDP(RWORK(LYH:LRW),NYH,N,NQ)
6538          DO I = 1, NDX
6539            IF ((ACOR(IDX(I))>LB(I) .AND. RWORK(LYH+ &
6540                IDX(I)-1)<LB(I)) .OR. (ACOR(IDX(I))<UB(I) .AND. RWORK(LYH+ &
6541                IDX(I)-1)>UB(I))) THEN
6542!              Retract:
6543              CALL DVNRDN(RWORK(LYH),NYH,N,NQ)
6544              H = HALF*H
6545              ETA = HALF
6546!              Rescale:
6547              CALL DVNRDS(RWORK(LYH),NYH,N,L,ETA)
6548              GOTO 220
6549            END IF
6550          END DO
6551!         Retract:
6552          CALL DVNRDN(RWORK(LYH),NYH,N,NQ)
6553          ACOR(1:N) = ZERO
6554        END IF
6555
6556!       CALL DVSTEP(Y,YH,LDYH,YH1,EWT,SAVF,ACOR,WM,IWM,F,JAC, &
6557!         VNLS,OPTS%ATOL,ITOL)
6558!_______________________________________________________________________
6559
6560        IF (MITER/=6 .AND. MITER/=7) THEN
6561          CALL DVSTEP(Y,RWORK(LYH),NYH,RWORK(LYH),EWT,SAVF,ACOR,WM, &
6562            IWORK(LIWM),F,JAC,DVNLSD,OPTS%ATOL,ITOL)
6563        ELSE
6564          CALL DVSTEP(Y,RWORK(LYH),NYH,RWORK(LYH),EWT,SAVF,ACOR,WM, &
6565            IWORK(LIWM),F,JAC,DVNLSS28,OPTS%ATOL,ITOL)
6566        END IF
6567! *****MA48 build change point. Replace above with these statements.
6568!     IF (MITER /= 6 .AND. MITER /= 7) THEN
6569!        CALL DVSTEP(Y,RWORK(LYH),NYH,RWORK(LYH),EWT,SAVF,ACOR,WM, &
6570!          IWORK(LIWM),F,JAC,DVNLSD,OPTS%ATOL,ITOL)
6571!     ELSE
6572!        IF (USE_MA48_FOR_SPARSE) THEN
6573!           CALL DVSTEP(Y,RWORK(LYH),NYH,RWORK(LYH),EWT,SAVF,ACOR,WM, &
6574!             IWORK(LIWM), F, JAC, DVNLSS48,OPTS%ATOL,ITOL)
6575!        ELSE
6576!           CALL DVSTEP(Y,RWORK(LYH),NYH,RWORK(LYH),EWT,SAVF,ACOR,WM, &
6577!           IWORK(LIWM),F,JAC,DVNLSS28,OPTS%ATOL,ITOL)
6578!        END IF
6579!     END IF
6580!_______________________________________________________________________
6581
6582        KGO = 1 - KFLAG
6583!       Branch on KFLAG. Note: In this version, KFLAG can not be set to
6584!                            -3; KFLAG = 0, -1, -2.
6585        GOTO (240,370,380) KGO
6586
6587! Block F.
6588! The following block handles the case of a successful return from the
6589! core integrator (KFLAG = 0). Test for stop conditions.
6590
6591240     INIT = 1
6592        KUTH = 0
6593        GOTO (250,310,270,280,300) ITASK
6594!       ITASK = 1. If TOUT has been reached, interpolate.
6595250     CONTINUE
6596        IF (NGC==0) GOTO 260
6597        CALL DVCHECK(3,GFUN,NEQ,Y,RWORK(LYH),NYH,G0,G1,GX,IRT)
6598        IF (IRT/=1) GOTO 260
6599        IRFND = 1
6600        ISTATE = 3
6601        T = T0ST
6602        GOTO 330
6603260     CONTINUE
6604        IF ((TN-TOUT)*H<ZERO) GOTO 200
6605        CALL DVINDY_CORE(TOUT,0,RWORK(LYH),NYH,Y,IFLAG)
6606        IF (BOUNDS) THEN
6607          DO I = 1, NDX
6608            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
6609            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
6610          END DO
6611        END IF
6612        T = TOUT
6613        GOTO 320
6614!       ITASK = 3. Jump to exit if TOUT was reached.
6615270     IF ((TN-TOUT)*H>=ZERO) GOTO 310
6616        GOTO 200
6617!       ITASK = 4. See if TOUT or TCRIT was reached. Adjust H if necessary.
6618280     IF ((TN-TOUT)*H<ZERO) GOTO 290
6619        CALL DVINDY_CORE(TOUT,0,RWORK(LYH),NYH,Y,IFLAG)
6620        IF (BOUNDS) THEN
6621          DO I = 1, NDX
6622            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
6623            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
6624          END DO
6625        END IF
6626        T = TOUT
6627        GOTO 320
6628290     HMX = ABS(TN) + ABS(H)
6629        IHIT = ABS(TN-TCRIT) <= HUN*UROUND*HMX
6630        IF (IHIT) GOTO 310
6631        TNEXT = TN + HNEW*(ONE+FOUR*UROUND)
6632        IF ((TNEXT-TCRIT)*H<=ZERO) GOTO 200
6633        H = (TCRIT-TN)*(ONE-FOUR*UROUND)
6634        KUTH = 1
6635        GOTO 200
6636!       ITASK = 5. See if TCRIT was reached and jump to exit.
6637300     HMX = ABS(TN) + ABS(H)
6638        IHIT = ABS(TN-TCRIT) <= HUN*UROUND*HMX
6639
6640! Block G.
6641! The following block handles all successful returns from DVODE.
6642! If ITASK /= 1, Y is loaded from YH and T is set accordingly.
6643! ISTATE is set to 2, and the optional output is loaded into the
6644! work arrays before returning.
6645
6646310     CONTINUE
6647        CALL DCOPY_F90(N,RWORK(LYH),1,Y,1)
6648        T = TN
6649        IF (ITASK/=4 .AND. ITASK/=5) GOTO 320
6650        IF (IHIT) T = TCRIT
6651320     ISTATE = 2
6652330     CONTINUE
6653        RWORK(11) = HU
6654        RWORK(12) = HNEW
6655        RWORK(13) = TN
6656        IWORK(10) = NGE
6657        IWORK(11) = NST
6658        IWORK(12) = NFE
6659        IWORK(13) = NJE
6660        IWORK(14) = NQU
6661        IWORK(15) = NEWQ
6662        IWORK(19) = NLU
6663        IWORK(20) = NNI
6664        IWORK(21) = NCFN
6665        IWORK(22) = NETF
6666        TLAST = T
6667        RUSER(1:LRWUSER) = RWORK(1:LRWUSER)
6668        IUSER(1:LIWUSER) = IWORK(1:LIWUSER)
6669!       Warn the user if |y(t)| < ATOL:
6670        IF (ISTATE==2 .OR. ISTATE==3) THEN
6671          IF (YMAXWARN) THEN
6672            ATOLI = OPTS%ATOL(1)
6673            DO I = 1, N
6674              IF (ITOL==2 .OR. ITOL==4) ATOLI = OPTS%ATOL(I)
6675              IF (ABS(Y(I))<ATOLI) THEN
6676                MSG = 'Warning: Component I1 of the solution is'
6677                CALL XERRDV(MSG,960,1,0,0,0,0,ZERO,ZERO)
6678                MSG = 'smaller in magnitude than component I1'
6679                CALL XERRDV(MSG,960,1,0,0,0,0,ZERO,ZERO)
6680                MSG = 'of the absolute error tolerance vector.'
6681                CALL XERRDV(MSG,960,1,1,I,0,0,ZERO,ZERO)
6682              END IF
6683            END DO
6684          END IF
6685        END IF
6686        RETURN
6687
6688! Block H.
6689! The following block handles all unsuccessful returns other than
6690! those for illegal input. First the error message routine is called.
6691! if there was an error test or convergence test failure, IMXER is set.
6692! Then Y is loaded from YH, and T is set to TN. The optional output
6693! is loaded into the work arrays before returning.
6694
6695!       The maximum number of steps was taken before reaching TOUT.
6696340     MSG = 'At current T(=R1), MXSTEP(=I1) steps'
6697        CALL XERRDV(MSG,970,1,0,0,0,0,ZERO,ZERO)
6698        MSG = 'taken on this call before reaching TOUT.'
6699        CALL XERRDV(MSG,970,1,1,MXSTEP,0,1,TN,ZERO)
6700        ISTATE = -1
6701        GOTO 410
6702!       EWT(i) <= 0.0 for some i (not at start of problem).
6703350     EWTI = EWT(I)
6704        MSG = 'At T(=R1), EWT(I1) has become R2 <= 0.'
6705        CALL XERRDV(MSG,980,1,1,I,0,2,TN,EWTI)
6706        ISTATE = -6
6707        GOTO 410
6708!       Too much accuracy requested for machine precision.
6709360     MSG = 'At T(=R1), too much accuracy was requested'
6710        CALL XERRDV(MSG,990,1,0,0,0,0,ZERO,ZERO)
6711        MSG = 'for precision of machine:   see TOLSF(=R2).'
6712        CALL XERRDV(MSG,990,1,0,0,0,2,TN,TOLSF)
6713        RWORK(14) = TOLSF
6714        ISTATE = -2
6715        GOTO 410
6716!       KFLAG = -1. Error test failed repeatedly or with ABS(H) = HMIN.
6717370     MSG = 'At T(=R1) and step size H(=R2), the error'
6718        CALL XERRDV(MSG,1000,1,0,0,0,0,ZERO,ZERO)
6719        MSG = 'test failed repeatedly or with ABS(H) = HMIN.'
6720        CALL XERRDV(MSG,1000,1,0,0,0,2,TN,H)
6721        ISTATE = -4
6722        GOTO 390
6723!       KFLAG = -2. Convergence failed repeatedly or with ABS(H) = HMIN.
6724380     MSG = 'At T(=R1) and step size H(=R2), the'
6725        CALL XERRDV(MSG,1010,1,0,0,0,0,ZERO,ZERO)
6726        MSG = 'corrector convergence failed repeatedly'
6727        CALL XERRDV(MSG,1010,1,0,0,0,0,ZERO,ZERO)
6728        MSG = 'or with ABS(H) = HMIN.'
6729        CALL XERRDV(MSG,1010,1,0,0,0,2,TN,H)
6730        ISTATE = -5
6731!       Compute IMXER if relevant.
6732390     BIG = ZERO
6733        IMXER = 1
6734        DO 400 I = 1, N
6735          SIZEST = ABS(ACOR(I)*EWT(I))
6736          IF (BIG>=SIZEST) GOTO 400
6737          BIG = SIZEST
6738          IMXER = I
6739400     END DO
6740        IWORK(16) = IMXER
6741!       Set Y vector, T, and optional output.
6742410     CONTINUE
6743        CALL DCOPY_F90(N,RWORK(LYH),1,Y,1)
6744        T = TN
6745        RWORK(11) = HU
6746        RWORK(12) = H
6747        RWORK(13) = TN
6748        IWORK(10) = NGE
6749        IWORK(11) = NST
6750        IWORK(12) = NFE
6751        IWORK(13) = NJE
6752        IWORK(14) = NQU
6753        IWORK(15) = NQ
6754        IWORK(19) = NLU
6755        IWORK(20) = NNI
6756        IWORK(21) = NCFN
6757        IWORK(22) = NETF
6758        TLAST = T
6759        RUSER(1:LRWUSER) = RWORK(1:LRWUSER)
6760        IUSER(1:LIWUSER) = IWORK(1:LIWUSER)
6761        RETURN
6762
6763! Block I.
6764! The following block handles all error returns due to illegal input
6765! (ISTATE = -3), as detected before calling the core integrator.
6766! First the error message routine is called. If the illegal input
6767! is a negative ISTATE, the run is aborted (apparent infinite loop).
6768
6769420     MSG = 'ISTATE(=I1) is illegal.'
6770        CALL XERRDV(MSG,1020,1,1,ISTATE,0,0,ZERO,ZERO)
6771        IF (ISTATE<0) GOTO 750
6772        GOTO 740
6773430     MSG = 'ITASK(=I1) is illegal.'
6774        CALL XERRDV(MSG,1030,1,1,ITASK,0,0,ZERO,ZERO)
6775        GOTO 740
6776440     MSG = 'ISTATE(=I1) > 1 but DVODE is not initialized.'
6777        CALL XERRDV(MSG,1040,1,1,ISTATE,0,0,ZERO,ZERO)
6778        GOTO 740
6779450     MSG = 'NEQ (=I1) < 1.'
6780        CALL XERRDV(MSG,1050,1,1,NEQ,0,0,ZERO,ZERO)
6781        GOTO 740
6782460     MSG = 'ISTATE = 3 and NEQ increased (I1 to I2).'
6783        CALL XERRDV(MSG,1060,1,2,N,NEQ,0,ZERO,ZERO)
6784        GOTO 740
6785465     MSG = 'This version of DVODE requires does not allow NEQ to be reduced.'
6786        CALL XERRDV(MSG,1070,2,0,0,0,0,ZERO,ZERO)
6787        GOTO 740
6788470     MSG = 'ITOL(=I1) is illegal.'
6789        CALL XERRDV(MSG,1080,1,1,ITOL,0,0,ZERO,ZERO)
6790        GOTO 740
6791480     MSG = 'IOPT(=I1) is illegal.'
6792        CALL XERRDV(MSG,1090,1,1,IOPT,0,0,ZERO,ZERO)
6793        GOTO 740
6794490     MSG = 'MF(=I1) is illegal.'
6795        CALL XERRDV(MSG,1100,1,1,MF,0,0,ZERO,ZERO)
6796        GOTO 740
6797500     MSG = 'ML(=I1) illegal: < 0 or >= NEQ (=I2)'
6798        CALL XERRDV(MSG,1110,1,2,ML,NEQ,0,ZERO,ZERO)
6799        GOTO 740
6800510     MSG = 'MU(=I1) illegal: < 0 or >= NEQ (=I2)'
6801        CALL XERRDV(MSG,1120,1,2,MU,NEQ,0,ZERO,ZERO)
6802        GOTO 740
6803520     MSG = 'MAXORD(=I1) < 0.'
6804        CALL XERRDV(MSG,1130,1,1,MAXORD,0,0,ZERO,ZERO)
6805        GOTO 740
6806530     MSG = 'MXSTEP(=I1) < 0.'
6807        CALL XERRDV(MSG,1140,1,1,MXSTEP,0,0,ZERO,ZERO)
6808        GOTO 740
6809540     MSG = 'MXHNIL(=I1) < 0.'
6810        CALL XERRDV(MSG,1150,1,1,MXHNIL,0,0,ZERO,ZERO)
6811        GOTO 740
6812550     MSG = 'TOUT(=R1) is behind T(=R2).'
6813        CALL XERRDV(MSG,1160,1,0,0,0,2,TOUT,T)
6814        MSG = 'The integration direction is given by H0 (=R1).'
6815        CALL XERRDV(MSG,1160,1,0,0,0,1,H0,ZERO)
6816        GOTO 740
6817560     MSG = 'HMAX(=R1) < 0.'
6818        CALL XERRDV(MSG,1170,1,0,0,0,1,HMAX,ZERO)
6819        GOTO 740
6820570     MSG = 'HMIN(=R1) < 0.'
6821        CALL XERRDV(MSG,1180,1,0,0,0,1,HMIN,ZERO)
6822        GOTO 740
6823580     CONTINUE
6824        MSG = 'RWORK length needed, LENRW(=I1) > LRW(=I2)'
6825        CALL XERRDV(MSG,1190,1,2,LENRW,LRW,0,ZERO,ZERO)
6826        GOTO 740
6827590     CONTINUE
6828        MSG = 'IWORK length needed, LENIW(=I1) > LIW(=I2)'
6829        CALL XERRDV(MSG,1200,1,2,LENIW,LIW,0,ZERO,ZERO)
6830        GOTO 740
6831600     MSG = 'RTOL(I1) is R1 < 0.'
6832        CALL XERRDV(MSG,1210,1,1,I,0,1,RTOLI,ZERO)
6833        GOTO 740
6834610     MSG = 'ATOL(I1) is R1 < 0.'
6835        CALL XERRDV(MSG,1220,1,1,I,0,1,ATOLI,ZERO)
6836        GOTO 740
6837620     EWTI = EWT(I)
6838        MSG = 'EWT(I1) is R1 <= 0.'
6839        CALL XERRDV(MSG,1230,1,1,I,0,1,EWTI,ZERO)
6840        GOTO 740
6841630     CONTINUE
6842        MSG = 'TOUT(=R1) too close to T(=R2) to start.'
6843        CALL XERRDV(MSG,1240,1,0,0,0,2,TOUT,T)
6844        GOTO 740
6845640     CONTINUE
6846        MSG = 'ITASK = I1 and TOUT(=R1) < TCUR - HU(=R2).'
6847        CALL XERRDV(MSG,1250,1,1,ITASK,0,2,TOUT,TP)
6848        GOTO 740
6849650     CONTINUE
6850        MSG = 'ITASK = 4 or 5 and TCRIT(=R1) < TCUR(=R2).'
6851        CALL XERRDV(MSG,1260,1,0,0,0,2,TCRIT,TN)
6852        GOTO 740
6853660     CONTINUE
6854        MSG = 'ITASK = 4 or 5 and TCRIT(=R1) < TOUT(=R2).'
6855        CALL XERRDV(MSG,1270,1,0,0,0,2,TCRIT,TOUT)
6856        GOTO 740
6857670     MSG = 'At the start of the problem, too much'
6858        CALL XERRDV(MSG,1280,1,0,0,0,0,ZERO,ZERO)
6859        MSG = 'accuracy was requested for precision'
6860        CALL XERRDV(MSG,1280,1,0,0,0,1,TOLSF,ZERO)
6861        MSG = 'of machine: see TOLSF(=R1).'
6862        CALL XERRDV(MSG,1280,1,0,0,0,1,TOLSF,ZERO)
6863        RWORK(14) = TOLSF
6864        GOTO 740
6865680     MSG = 'Trouble from DVINDY. ITASK = I1, TOUT = R1.'
6866        CALL XERRDV(MSG,1290,1,1,ITASK,0,1,TOUT,ZERO)
6867        GOTO 740
6868690     MSG = 'SETH must be nonnegative.'
6869        CALL XERRDV(MSG,1300,1,0,0,0,0,ZERO,ZERO)
6870        GOTO 740
6871700     MSG = 'NG(=I1) < 0.'
6872        CALL XERRDV(MSG,1310,0,1,NG,0,0,ZERO,ZERO)
6873        GOTO 740
6874710     MSG = 'NG changed (from I1 to I2) illegally, i.e.,'
6875        CALL XERRDV(MSG,1320,1,0,0,0,0,ZERO,ZERO)
6876        MSG = 'not immediately after a root was found.'
6877        CALL XERRDV(MSG,1320,1,2,NGC,NG,0,ZERO,ZERO)
6878        GOTO 740
6879720     MSG = 'One or more components of g has a root'
6880        CALL XERRDV(MSG,1330,1,0,0,0,0,ZERO,ZERO)
6881        MSG = 'too near to the initial point.'
6882        CALL XERRDV(MSG,1330,1,0,0,0,0,ZERO,ZERO)
6883        GOTO 740
6884730     CONTINUE
6885        MSG = 'WM length needed, LENWM(=I1) > LWMDIM(=I2)'
6886        CALL XERRDV(MSG,1340,1,2,LENWM,LWMDIM,0,ZERO,ZERO)
6887
6888740     CONTINUE
6889        ISTATE = -3
6890        RUSER(1:LRWUSER) = RWORK(1:LRWUSER)
6891        IUSER(1:LIWUSER) = IWORK(1:LIWUSER)
6892        RETURN
6893
6894750     MSG = 'Run aborted:  apparent infinite loop.'
6895        CALL XERRDV(MSG,1350,2,0,0,0,0,ZERO,ZERO)
6896        RUSER(1:LRWUSER) = RWORK(1:LRWUSER)
6897        IUSER(1:LIWUSER) = IWORK(1:LIWUSER)
6898        RETURN
6899
6900      END SUBROUTINE DVODE
6901!_______________________________________________________________________
6902
6903      SUBROUTINE DVHIN(N,T0,Y0,YDOT,F,TOUT,EWT,ITOL,ATOL,Y,TEMP,H0, &
6904        NITER,IER)
6905! ..
6906! Calculate the initial step size.
6907! ..
6908! This routine computes the step size, H0, to be attempted on the
6909! first step, when the user has not supplied a value for this.
6910! First we check that TOUT - T0 differs significantly from zero. Then
6911! an iteration is done to approximate the initial second derivative
6912! and this is used to define h from w.r.m.s.norm(h**2 * yddot / 2) = 1.
6913! A bias factor of 1/2 is applied to the resulting h.
6914! The sign of H0 is inferred from the initial values of TOUT and T0.
6915! Communication with DVHIN is done with the following variables:
6916! N      = Size of ODE system, input.
6917! T0     = Initial value of independent variable, input.
6918! Y0     = Vector of initial conditions, input.
6919! YDOT   = Vector of initial first derivatives, input.
6920! F      = Name of subroutine for right-hand side f(t,y), input.
6921! TOUT   = First output value of independent variable
6922! UROUND = Machine unit roundoff
6923! EWT, ITOL, ATOL = Error weights and tolerance parameters
6924!                   as described in the driver routine, input.
6925! Y, TEMP = Work arrays of length N.
6926! H0     = Step size to be attempted, output.
6927! NITER  = Number of iterations (and of f evaluations) to compute H0,
6928!          output.
6929! IER    = The error flag, returned with the value
6930!          IER = 0  if no trouble occurred, or
6931!          IER = -1 if TOUT and T0 are considered too close to proceed.
6932! ..
6933     IMPLICIT NONE
6934! ..
6935! .. Scalar Arguments ..
6936        KPP_REAL, INTENT (INOUT) :: H0
6937        KPP_REAL, INTENT (IN) :: T0, TOUT
6938        INTEGER :: IER
6939        INTEGER, INTENT (IN) :: ITOL, N
6940        INTEGER, INTENT (INOUT) :: NITER
6941! ..
6942! .. Array Arguments ..
6943        KPP_REAL, INTENT (IN) :: ATOL(*), EWT(*), Y0(*)
6944        KPP_REAL, INTENT (INOUT) :: TEMP(*), Y(*), YDOT(*)
6945! ..
6946! .. Subroutine Arguments ..
6947        EXTERNAL F
6948! ..
6949! .. Local Scalars ..
6950        KPP_REAL :: AFI, ATOLI, DELYI, H, HG, HLB, HNEW, HRAT, HUB, T1, &
6951          TDIST, TROUND, YDDNRM
6952        INTEGER :: I, ITER
6953! ..
6954! .. Intrinsic Functions ..
6955        INTRINSIC ABS, MAX, SIGN, SQRT
6956! ..
6957! .. FIRST EXECUTABLE STATEMENT DVHIN
6958! ..
6959        NITER = 0
6960        TDIST = ABS(TOUT-T0)
6961        TROUND = UROUND*MAX(ABS(T0),ABS(TOUT))
6962        IF (TDIST<TWO*TROUND) GOTO 40
6963
6964!       Set a lower bound on H based on the roundoff level in T0
6965!       and TOUT.
6966        HLB = HUN*TROUND
6967!       Set an upper bound on H based on TOUT-T0 and the initial
6968!       Y and YDOT.
6969        HUB = PT1*TDIST
6970        ATOLI = ATOL(1)
6971        DO I = 1, N
6972          IF (ITOL==2 .OR. ITOL==4) ATOLI = ATOL(I)
6973          DELYI = PT1*ABS(Y0(I)) + ATOLI
6974          AFI = ABS(YDOT(I))
6975          IF (AFI*HUB>DELYI) HUB = DELYI/AFI
6976        END DO
6977!       Set initial guess for H as geometric mean of upper and
6978!       lower bounds.
6979        ITER = 0
6980        HG = SQRT(HLB*HUB)
6981!       If the bounds have crossed, exit with the mean value.
6982        IF (HUB<HLB) THEN
6983          H0 = HG
6984          GOTO 30
6985        END IF
6986
6987!       Looping point for iteration.
698810      CONTINUE
6989!       Estimate the second derivative as a difference quotient in f.
6990        H = SIGN(HG,TOUT-T0)
6991        T1 = T0 + H
6992        Y(1:N) = Y0(1:N) + H*YDOT(1:N)
6993        CALL F(N,T1,Y,TEMP)
6994        NFE = NFE + 1
6995        TEMP(1:N) = (TEMP(1:N)-YDOT(1:N))/H
6996        YDDNRM = DVNORM(N,TEMP,EWT)
6997!       Get the corresponding new value of h.
6998        IF (YDDNRM*HUB*HUB>TWO) THEN
6999          HNEW = SQRT(TWO/YDDNRM)
7000        ELSE
7001          HNEW = SQRT(HG*HUB)
7002        END IF
7003        ITER = ITER + 1
7004
7005! Test the stopping conditions.
7006! Stop if the new and previous h values differ by a factor of < 2.
7007! Stop if four iterations have been done. Also, stop with previous h
7008! if HNEW/HG > 2 after first iteration, as this probably means that
7009! the second derivative value is bad because of cancellation error.
7010
7011        IF (ITER>=4) GOTO 20
7012        HRAT = HNEW/HG
7013        IF ((HRAT>HALF) .AND. (HRAT<TWO)) GOTO 20
7014        IF ((ITER>=2) .AND. (HNEW>TWO*HG)) THEN
7015          HNEW = HG
7016          GOTO 20
7017        END IF
7018        HG = HNEW
7019        GOTO 10
7020
7021!       Iteration done. Apply bounds, bias factor, and sign. Then exit.
702220      H0 = HNEW*HALF
7023        IF (H0<HLB) H0 = HLB
7024        IF (H0>HUB) H0 = HUB
702530      H0 = SIGN(H0,TOUT-T0)
7026        NITER = ITER
7027        IER = 0
7028        RETURN
7029!       Error return for TOUT - T0 too small.
703040      IER = -1
7031        RETURN
7032
7033      END SUBROUTINE DVHIN
7034!_______________________________________________________________________
7035
7036      SUBROUTINE DVINDY_CORE(T,K,YH,LDYH,DKY,IFLAG)
7037! ..
7038! Interpolate the solution and derivative.
7039! ..
7040! DVINDY_CORE computes interpolated values of the K-th derivative
7041! of the dependent variable vector y, and stores it in DKY. This
7042! routine is called within the package with K = 0 and T = TOUT,
7043! but may also be called by the user for any K up to the current
7044! order. (See detailed instructions in the usage documentation.)
7045! The computed values in DKY are gotten by interpolation using the
7046! Nordsieck history array YH. This array corresponds uniquely to a
7047! vector-valued polynomial of degree NQCUR or less, and DKY is set
7048! to the K-th derivative of this polynomial at T.
7049! The formula for DKY is:
7050!              q
7051!  DKY(i)  =  sum  c(j,K) * (T - TN)**(j-K) * H**(-j) * YH(i,j+1)
7052!             j=K
7053! where  c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, TN = TCUR, H = HCUR.
7054! The quantities  NQ = NQCUR, L = NQ+1, N, TN, and H are
7055! communicated by PRIVATE variables. The above sum is done in reverse
7056! order.
7057! IFLAG is returned negative if either K or T is out of bounds.
7058! Discussion above and comments in driver explain all variables.
7059! ..
7060     IMPLICIT NONE
7061! ..
7062! .. Scalar Arguments ..
7063        KPP_REAL, INTENT (IN) :: T
7064        INTEGER, INTENT (INOUT) :: IFLAG
7065        INTEGER, INTENT (IN) :: K, LDYH
7066! ..
7067! .. Array Arguments ..
7068        KPP_REAL, INTENT (INOUT) :: DKY(*), YH(LDYH,*)
7069! ..
7070! .. Local Scalars ..
7071        KPP_REAL :: C, R, S, TFUZZ, TN1, TP
7072        INTEGER :: IC, J, JB, JB2, JJ, JJ1, JP1
7073        CHARACTER (80) :: MSG
7074! ..
7075! .. Intrinsic Functions ..
7076        INTRINSIC ABS, REAL, SIGN
7077! ..
7078! .. FIRST EXECUTABLE STATEMENT DVINDY_CORE
7079! ..
7080        IFLAG = 0
7081        IF (K<0 .OR. K>NQ) GOTO 40
7082!       TFUZZ = HUN * UROUND * (TN + HU)
7083        TFUZZ = HUN*UROUND*SIGN(ABS(TN)+ABS(HU),HU)
7084        TP = TN - HU - TFUZZ
7085        TN1 = TN + TFUZZ
7086        IF ((T-TP)*(T-TN1)>ZERO) GOTO 50
7087        S = (T-TN)/H
7088        IC = 1
7089        IF (K==0) GOTO 10
7090        JJ1 = L - K
7091        DO JJ = JJ1, NQ
7092          IC = IC*JJ
7093        END DO
709410      C = REAL(IC)
7095        DKY(1:N) = C*YH(1:N,L)
7096        IF (K==NQ) GOTO 30
7097        JB2 = NQ - K
7098        DO JB = 1, JB2
7099          J = NQ - JB
7100          JP1 = J + 1
7101          IC = 1
7102          IF (K==0) GOTO 20
7103          JJ1 = JP1 - K
7104          DO JJ = JJ1, J
7105            IC = IC*JJ
7106          END DO
710720        C = REAL(IC)
7108          DKY(1:N) = C*YH(1:N,JP1) + S*DKY(1:N)
7109        END DO
711030      R = H**(-K)
7111        CALL DSCAL_F90(N,R,DKY,1)
7112        RETURN
711340      MSG = 'Error in DVINDY, K(=I1) is illegal.'
7114        CALL XERRDV(MSG,1360,1,1,K,0,0,ZERO,ZERO)
7115        IFLAG = -1
7116        RETURN
711750      MSG = 'Error in DVINDY, T(=R1) is illegal. T is not'
7118        CALL XERRDV(MSG,1370,1,0,0,0,1,T,ZERO)
7119        MSG = 'in interval TCUR - HU(= R1) to TCUR(=R2)'
7120        CALL XERRDV(MSG,1370,1,0,0,0,2,TP,TN)
7121        IFLAG = -2
7122        RETURN
7123
7124      END SUBROUTINE DVINDY_CORE
7125!_______________________________________________________________________
7126
7127      SUBROUTINE DVINDY_BNDS(T,K,YH,LDYH,DKY,IFLAG)
7128! ..
7129! Interpolate the solution and derivative and enforce nonnegativity
7130! (used only if user calls DVINDY and the BOUNDS option is in
7131! use).
7132! ..
7133! This version of DVINDY_CORE enforces nonnegativity and is called
7134! only by DVINDY (which is called only by the user). It uses the
7135! private YNNEG array produced by a call to DVINDY_CORE from DVINDY
7136! to enforce nonnegativity.
7137! DVINDY_BNDS computes interpolated values of the K-th derivative
7138! of the dependent variable vector y, and stores it in DKY. This
7139! routine is called within the package with K = 0 and T = TOUT,
7140! but may also be called by the user for any K up to the current
7141! order. (See detailed instructions in the usage documentation.)
7142! The computed values in DKY are gotten by interpolation using the
7143! Nordsieck history array YH. This array corresponds uniquely to a
7144! vector-valued polynomial of degree NQCUR or less, and DKY is set
7145! to the K-th derivative of this polynomial at T.
7146! The formula for DKY is:
7147!              q
7148!  DKY(i)  =  sum  c(j,K) * (T - TN)**(j-K) * H**(-j) * YH(i,j+1)
7149!             j=K
7150! where  c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, TN = TCUR, H = HCUR.
7151! The quantities  NQ = NQCUR, L = NQ+1, N, TN, and H are
7152! communicated by PRIVATE variables. The above sum is done in reverse
7153! order.
7154! IFLAG is returned negative if either K or T is out of bounds.
7155! Discussion above and comments in driver explain all variables.
7156! ..
7157     IMPLICIT NONE
7158! ..
7159! .. Scalar Arguments ..
7160        KPP_REAL, INTENT (IN) :: T
7161        INTEGER, INTENT (INOUT) :: IFLAG
7162        INTEGER, INTENT (IN) :: K, LDYH
7163! ..
7164! .. Array Arguments ..
7165        KPP_REAL, INTENT (INOUT) :: DKY(*), YH(LDYH,*)
7166! ..
7167! .. Local Scalars ..
7168        KPP_REAL :: C, R, S, TFUZZ, TN1, TP
7169        INTEGER :: I, IC, J, JB, JB2, JJ, JJ1, JP1
7170        CHARACTER (80) :: MSG
7171! ..
7172! .. Intrinsic Functions ..
7173        INTRINSIC ABS, REAL, SIGN
7174! ..
7175! .. FIRST EXECUTABLE STATEMENT DVINDY_BNDS
7176! ..
7177        IFLAG = 0
7178        IF (K==0) GOTO 50
7179        IF (K<0 .OR. K>NQ) GOTO 40
7180!       TFUZZ = HUN * UROUND * (TN + HU)
7181        TFUZZ = HUN*UROUND*SIGN(ABS(TN)+ABS(HU),HU)
7182        TP = TN - HU - TFUZZ
7183        TN1 = TN + TFUZZ
7184        IF ((T-TP)*(T-TN1)>ZERO) GOTO 60
7185        S = (T-TN)/H
7186        IC = 1
7187        IF (K==0) GOTO 10
7188        JJ1 = L - K
7189        DO JJ = JJ1, NQ
7190          IC = IC*JJ
7191        END DO
719210      C = REAL(IC)
7193        DKY(1:N) = C*YH(1:N,L)
7194        IF (BOUNDS) THEN
7195          DO I = 1, NDX
7196            IF (YNNEG(IDX(I))<LB(I) .OR. YNNEG(IDX(I))>UB(I)) DKY(IDX(I)) &
7197              = ZERO
7198          END DO
7199        END IF
7200        IF (K==NQ) GOTO 30
7201        JB2 = NQ - K
7202        DO JB = 1, JB2
7203          J = NQ - JB
7204          JP1 = J + 1
7205          IC = 1
7206          IF (K==0) GOTO 20
7207          JJ1 = JP1 - K
7208          DO JJ = JJ1, J
7209            IC = IC*JJ
7210          END DO
721120        C = REAL(IC)
7212          DKY(1:N) = C*YH(1:N,JP1) + S*DKY(1:N)
7213          IF (BOUNDS) THEN
7214            DO I = 1, NDX
7215              IF (YNNEG(IDX(I))<LB(I) .OR. YNNEG(IDX(I))>UB(I)) DKY(IDX(I)) &
7216                = ZERO
7217            END DO
7218          END IF
7219        END DO
722030      R = H**(-K)
7221        CALL DSCAL_F90(N,R,DKY,1)
7222        RETURN
722340      MSG = 'Error in DVINDY, K(=I1) is illegal.'
7224        CALL XERRDV(MSG,1380,1,1,K,0,0,ZERO,ZERO)
7225        IFLAG = -1
7226        RETURN
722750      MSG = 'DVINDY_BNDS cannot be called with k = 0.'
7228        CALL XERRDV(MSG,1390,1,0,0,0,0,ZERO,ZERO)
7229        IFLAG = -1
7230        RETURN
723160      MSG = 'Error in DVINDY, T(=R1) is illegal. T is not'
7232        CALL XERRDV(MSG,1400,1,0,0,0,1,T,ZERO)
7233        MSG = 'not in interval TCUR - HU(= R1) to TCUR(=R2)'
7234        CALL XERRDV(MSG,1400,1,0,0,0,2,TP,TN)
7235        IFLAG = -2
7236        RETURN
7237
7238      END SUBROUTINE DVINDY_BNDS
7239!_______________________________________________________________________
7240
7241      SUBROUTINE DVINDY(T,K,DKY,IFLAG)
7242! ..
7243! This is a dummy interface to allow the user to interpolate the
7244! solution and the derivative (not called by DVODE_F90).
7245! ..
7246! May be used if the user wishes to interpolate solution or
7247! derivative following a successful return from DVODE_F90
7248! DVINDY computes interpolated values of the K-th derivative of
7249! the dependent variable vector y, and stores it in DKY. This
7250! routine is called within the package with K = 0 and T = TOUT,
7251! but may also be called by the user for any K up to the current
7252! order. (See detailed instructions in the usage documentation.)
7253! The computed values in DKY are gotten by interpolation using the
7254! Nordsieck history array YH. This array corresponds uniquely to a
7255! vector-valued polynomial of degree NQCUR or less, and DKY is set
7256! to the K-th derivative of this polynomial at T.
7257! IFLAG is returned negative if either K or T is out of bounds.
7258! ..
7259     IMPLICIT NONE
7260! ..
7261! .. Scalar Arguments ..
7262        KPP_REAL, INTENT (IN) :: T
7263        INTEGER, INTENT (INOUT) :: IFLAG
7264        INTEGER, INTENT (IN) :: K
7265! ..
7266! .. Array Arguments ..
7267        KPP_REAL, INTENT (INOUT) :: DKY(*)
7268! ..
7269! .. Local Scalars ..
7270        INTEGER :: I, IER
7271! ..
7272! .. Intrinsic Functions ..
7273        INTRINSIC ALLOCATED, SIZE
7274! ..
7275! .. FIRST EXECUTABLE STATEMENT DVINDY
7276! ..
7277        CALL DVINDY_CORE(T,K,RWORK(LYH),N,DKY,IFLAG)
7278        IF (.NOT.BOUNDS) RETURN
7279
7280        IF (K==0) THEN
7281!         Interpolate only the solution.
7282          CALL DVINDY_CORE(T,K,RWORK(LYH),N,DKY,IFLAG)
7283!         Enforce bounds.
7284          DO I = 1, NDX
7285            IF (DKY(IDX(I))<LB(I)) DKY(IDX(I)) = LB(I)
7286            IF (DKY(IDX(I))>UB(I)) DKY(IDX(I)) = UB(I)
7287          END DO
7288          RETURN
7289        END IF
7290
7291!       k > 0 - derivatives requested.
7292
7293!       Make sure space is available for the interpolated solution.
7294        IF (ALLOCATED(YNNEG)) THEN
7295          IF (SIZE(YNNEG)<N) THEN
7296            DEALLOCATE (YNNEG,STAT=IER)
7297            CALL CHECK_STAT(IER,460)
7298            ALLOCATE (YNNEG(N),STAT=IER)
7299            CALL CHECK_STAT(IER,470)
7300          END IF
7301        ELSE
7302          ALLOCATE (YNNEG(N),STAT=IER)
7303          CALL CHECK_STAT(IER,480)
7304        END IF
7305!       Interpolate the solution; do not enforce bounds.
7306        CALL DVINDY_CORE(T,0,RWORK(LYH),N,YNNEG,IFLAG)
7307!       Now interpolate the derivative using YNNEG to enforce
7308!       nonnegativity.
7309        CALL DVINDY_BNDS(T,K,RWORK(LYH),N,DKY,IFLAG)
7310        RETURN
7311
7312      END SUBROUTINE DVINDY
7313!_______________________________________________________________________
7314
7315      SUBROUTINE DVSTEP(Y,YH,LDYH,YH1,EWT,SAVF,ACOR,WM,IWM,F,JAC, &
7316        VNLS,ATOL,ITOL)
7317! ..
7318! This is the core step integrator for nonstiff and for dense, banded,
7319! and sparse solutions.
7320! ..
7321! DVSTEP performs one step of the integration of an initial value
7322! problem for a system of ordinary differential equations. It
7323! calls subroutine DVNLSD for the solution of the nonlinear system
7324! arising in the time step. Thus it is independent of the problem
7325! Jacobian structure and the type of nonlinear system solution method.
7326! DVSTEP returns a completion flag KFLAG (in PRIVATE variables block).
7327! A return with KFLAG = -1 or -2 means either ABS(H) = HMIN or 10
7328! consecutive failures occurred. On a return with KFLAG negative,
7329! the values of TN and the YH array are as of the beginning of the last
7330! step, and H is the last step size attempted.
7331! Communication with DVSTEP is done with the following variables:
7332! Y      = An array of length N used for the dependent variable vector.
7333! YH     = An LDYH by LMAX array containing the dependent variables
7334!          and their approximate scaled derivatives, where
7335!          LMAX = MAXORD + 1. YH(i,j+1) contains the approximate
7336!          j-th derivative of y(i), scaled by H**j/factorial(j)
7337!          (j = 0,1,...,NQ). On entry for the first step, the first
7338!          two columns of YH must be set from the initial values.
7339! LDYH   = A constant integer >= N, the first dimension of YH.
7340!          N is the number of ODEs in the system.
7341! YH1    = A one-dimensional array occupying the same space as YH.
7342! EWT    = An array of length N containing multiplicative weights
7343!          for local error measurements. Local errors in y(i) are
7344!          compared to 1.0/EWT(i) in various error tests.
7345! SAVF   = An array of working storage, of length N.
7346!          also used for input of YH(*,MAXORD+2) when JSTART = -1
7347!          and MAXORD < the current order NQ.
7348! ACOR   = A work array of length N, used for the accumulated
7349!          corrections. On a successful return, ACOR(i) contains
7350!          the estimated one-step local error in y(i).
7351! WM,IWM = Real and integer work arrays associated with matrix
7352!          operations in DVNLSD.
7353! F      = Dummy name for the user supplied subroutine for f.
7354! JAC    = Dummy name for the user supplied Jacobian subroutine.
7355! DVNLSD = Dummy name for the nonlinear system solving subroutine,
7356!          whose real name is dependent on the method used.
7357! ..
7358     IMPLICIT NONE
7359! ..
7360! .. Scalar Arguments ..
7361        INTEGER, INTENT (IN) :: LDYH, ITOL
7362! ..
7363! .. Array Arguments ..
7364        KPP_REAL, INTENT (INOUT) :: ACOR(*), EWT(*), SAVF(*), &
7365          WM(*), Y(*), YH(LDYH,*), YH1(*)
7366        KPP_REAL, INTENT (IN) :: ATOL(*)
7367        INTEGER, INTENT (INOUT) :: IWM(*)
7368! ..
7369! .. Subroutine Arguments ..
7370        EXTERNAL F, JAC, VNLS
7371! ..
7372! .. Local Scalars ..
7373        KPP_REAL :: CNQUOT, DDN, DSM, DUP, ETAQ, ETAQM1, ETAQP1, FLOTL, R, &
7374          TOLD
7375        INTEGER :: I, I1, I2, IBACK, J, JB, NCF, NFLAG
7376! ..
7377! .. Intrinsic Functions ..
7378        INTRINSIC ABS, MAX, MIN, REAL
7379! ..
7380! .. FIRST EXECUTABLE STATEMENT DVSTEP
7381! ..
7382        KFLAG = 0
7383        TOLD = TN
7384        NCF = 0
7385        JCUR = 0
7386        NFLAG = 0
7387        IF (JSTART>0) GOTO 10
7388        IF (JSTART==-1) GOTO 30
7389
7390! On the first call, the order is set to 1, and other variables are
7391! initialized. ETAMAX is the maximum ratio by which H can be increased
7392! in a single step. It is normally 10, but is larger during the first
7393! step to compensate for the small initial H. If a failure occurs
7394! (in corrector convergence or error test), ETAMAX is set to 1 for
7395! the next increase.
7396
7397        LMAX = MAXORD + 1
7398        NQ = 1
7399        L = 2
7400        NQNYH = NQ*LDYH
7401        TAU(1) = H
7402        PRL1 = ONE
7403        RC = ZERO
7404        ETAMAX = ETAMX1
7405        NQWAIT = 2
7406        HSCAL = H
7407        GOTO 70
7408
7409! Take preliminary actions on a normal continuation step (JSTART > 0).
7410! If the driver changed H, then ETA must be reset and NEWH set to 1.
7411! If a change of order was dictated on the previous step, then it is
7412! done here and appropriate adjustments in the history are made.
7413! On an order decrease, the history array is adjusted by DVJUST.
7414! On an order increase, the history array is augmented by a column.
7415! On a change of step size H, the history array YH is rescaled.
7416
741710      CONTINUE
7418        IF (KUTH==1) THEN
7419          ETA = MIN(ETA,H/HSCAL)
7420          NEWH = 1
7421        END IF
742220      IF (NEWH==0) GOTO 70
7423        IF (NEWQ==NQ) GOTO 60
7424        IF (NEWQ<NQ) THEN
7425          CALL DVJUST(YH,LDYH,-1)
7426          NQ = NEWQ
7427          L = NQ + 1
7428          NQWAIT = L
7429          GOTO 60
7430        END IF
7431        IF (NEWQ>NQ) THEN
7432          CALL DVJUST(YH,LDYH,1)
7433          NQ = NEWQ
7434          L = NQ + 1
7435          NQWAIT = L
7436          GOTO 60
7437        END IF
7438
7439! The following block handles preliminaries needed when JSTART = -1.
7440! If N was reduced, zero out part of YH to avoid undefined references.
7441! If MAXORD was reduced to a value less than the tentative order NEWQ,
7442! then NQ is set to MAXORD, and a new H ratio ETA is chosen.
7443! Otherwise, we take the same preliminary actions as for JSTART > 0.
7444! In any case, NQWAIT is reset to L = NQ + 1 to prevent further
7445! changes in order for that many steps. The new H ratio ETA is
7446! limited by the input H if KUTH = 1, by HMIN if KUTH = 0, and by
7447! HMXI in any case. Finally, the history array YH is rescaled.
7448
744930      CONTINUE
7450        LMAX = MAXORD + 1
7451        IF (N==LDYH) GOTO 40
7452        I1 = 1 + (NEWQ+1)*LDYH
7453        I2 = (MAXORD+1)*LDYH
7454        IF (I1>I2) GOTO 40
7455        YH1(I1:I2) = ZERO
745640      IF (NEWQ<=MAXORD) GOTO 50
7457        FLOTL = REAL(LMAX)
7458        IF (MAXORD<NQ-1) THEN
7459          DDN = DVNORM(N,SAVF,EWT)/TQ(1)
7460          ETA = ONE/((BIAS1*DDN)**(ONE/FLOTL)+ADDON)
7461        END IF
7462        IF (MAXORD==NQ .AND. NEWQ==NQ+1) ETA = ETAQ
7463        IF (MAXORD==NQ-1 .AND. NEWQ==NQ+1) THEN
7464          ETA = ETAQM1
7465          CALL DVJUST(YH,LDYH,-1)
7466        END IF
7467        IF (MAXORD==NQ-1 .AND. NEWQ==NQ) THEN
7468          DDN = DVNORM(N,SAVF,EWT)/TQ(1)
7469          ETA = ONE/((BIAS1*DDN)**(ONE/FLOTL)+ADDON)
7470          CALL DVJUST(YH,LDYH,-1)
7471        END IF
7472        ETA = MIN(ETA,ONE)
7473        NQ = MAXORD
7474        L = LMAX
747550      IF (KUTH==1) ETA = MIN(ETA,ABS(H/HSCAL))
7476        IF (KUTH==0) ETA = MAX(ETA,HMIN/ABS(HSCAL))
7477        ETA = ETA/MAX(ONE,ABS(HSCAL)*HMXI*ETA)
7478        NEWH = 1
7479        NQWAIT = L
7480        IF (NEWQ<=MAXORD) GOTO 20
7481!       Rescale the history array for a change in H by a factor of ETA.
748260      R = ONE
7483        DO J = 2, L
7484          R = R*ETA
7485! Original:
7486!         CALL DSCAL_F90(N,R,YH(1,J),1)
7487          CALL DSCAL_F90(N,R,YH(1:N,J),1)
7488        END DO
7489        H = HSCAL*ETA
7490        HSCAL = H
7491        RC = RC*ETA
7492        NQNYH = NQ*LDYH
7493
7494! This section computes the predicted values by effectively
7495! multiplying the YH array by the Pascal triangle matrix.
7496! DVSET is called to calculate all integration coefficients.
7497! RC is the ratio of new to old values of the coefficient
7498! H/EL(2)=h/l1.
7499
750070      TN = TN + H
7501        I1 = NQNYH + 1
7502        DO JB = 1, NQ
7503          I1 = I1 - LDYH
7504          DO I = I1, NQNYH
7505            YH1(I) = YH1(I) + YH1(I+LDYH)
7506          END DO
7507        END DO
7508        CALL DVSET
7509        RL1 = ONE/EL(2)
7510        RC = RC*(RL1/PRL1)
7511        PRL1 = RL1
7512
7513!       Call the nonlinear system solver.
7514
7515        CALL VNLS(Y,YH,LDYH,SAVF,EWT,ACOR,IWM,WM,F,JAC,NFLAG, &
7516          ATOL,ITOL)
7517
7518        IF (NFLAG==0) GOTO 80
7519
7520! The DVNLSD routine failed to achieve convergence (NFLAG /= 0).
7521! The YH array is retracted to its values before prediction.
7522! The step size H is reduced and the step is retried, if possible.
7523! Otherwise, an error exit is taken.
7524
7525        NCF = NCF + 1
7526        NCFN = NCFN + 1
7527        ETAMAX = ONE
7528        TN = TOLD
7529        I1 = NQNYH + 1
7530        DO JB = 1, NQ
7531          I1 = I1 - LDYH
7532          DO I = I1, NQNYH
7533            YH1(I) = YH1(I) - YH1(I+LDYH)
7534          END DO
7535        END DO
7536        IF (NFLAG<-1) GOTO 240
7537        IF (ABS(H)<=HMIN*ONEPSM) GOTO 230
7538!       IF (NCF==MXNCF) GOTO 230
7539        IF (NCF==CONSECUTIVE_CFAILS) GOTO 230
7540        ETA = ETACF
7541        ETA = MAX(ETA,HMIN/ABS(H))
7542        NFLAG = -1
7543        GOTO 60
7544
7545! The corrector has converged (NFLAG = 0). The local error test is
7546! made and control passes to statement 500 if it fails.
7547
754880      CONTINUE
7549        DSM = ACNRM/TQ(2)
7550        IF (DSM>ONE) GOTO 100
7551
7552! After a successful step, update the YH and TAU arrays and decrement
7553! NQWAIT. If NQWAIT is then 1 and NQ < MAXORD, then ACOR is saved
7554! for use in a possible order increase on the next step.
7555! If ETAMAX = 1 (a failure occurred this step), keep NQWAIT >= 2.
7556
7557        KFLAG = 0
7558        NST = NST + 1
7559        HU = H
7560        NQU = NQ
7561        DO IBACK = 1, NQ
7562          I = L - IBACK
7563          TAU(I+1) = TAU(I)
7564        END DO
7565        TAU(1) = H
7566
7567        IF (BOUNDS) THEN
7568! Original:
7569!         CALL DAXPY_F90(N,EL(1),ACOR,1,YH(1,1),1)
7570!         CALL DAXPY_F90(N,EL(2),ACOR,1,YH(1,2),1)
7571          CALL DAXPY_F90(N,EL(1),ACOR,1,YH(1:N,1),1)
7572          CALL DAXPY_F90(N,EL(2),ACOR,1,YH(1:N,2),1)
7573!         Take care of roundoff causing y(t) to be slightly unequal
7574!         to the constraint bound.
7575          DO J = 1, NDX
7576            YH(IDX(J),1) = MAX(YH(IDX(J),1),LB(J))
7577            Y(IDX(J)) = MAX(Y(IDX(J)),LB(J))
7578            YH(IDX(J),1) = MIN(YH(IDX(J),1),UB(J))
7579            Y(IDX(J)) = MIN(Y(IDX(J)),UB(J))
7580          END DO
7581!         Update the higher derivatives and project to zero if necessary.
7582          IF (L>2) THEN
7583            DO J = 3, L
7584! Original:
7585!             CALL DAXPY_F90(N,EL(J),ACOR,1,YH(1,J),1)
7586              CALL DAXPY_F90(N,EL(J),ACOR,1,YH(1:N,J),1)
7587            END DO
7588          END IF
7589        ELSE
7590!         Proceed as usual.
7591          DO J = 1, L
7592! Original:
7593!           CALL DAXPY_F90(N,EL(J),ACOR,1,YH(1,J),1)
7594            CALL DAXPY_F90(N,EL(J),ACOR,1,YH(1:N,J),1)
7595          END DO
7596        END IF
7597
7598        NQWAIT = NQWAIT - 1
7599        IF ((L==LMAX) .OR. (NQWAIT/=1)) GOTO 90
7600! Original:
7601!       CALL DCOPY_F90(N,ACOR,1,YH(1,LMAX),1)
7602        CALL DCOPY_F90(N,ACOR,1,YH(1:N,LMAX),1)
7603        CONP = TQ(5)
760490      IF (ABS(ETAMAX-ONE)>0) GOTO 130
7605        IF (NQWAIT<2) NQWAIT = 2
7606        NEWQ = NQ
7607        NEWH = 0
7608        ETA = ONE
7609        HNEW = H
7610        GOTO 250
7611
7612! The error test failed. KFLAG keeps track of multiple failures.
7613! Restore TN and the YH array to their previous values, and prepare
7614! to try the step again. Compute the optimum step size for the
7615! same order. After repeated failures, H is forced to decrease
7616! more rapidly.
7617
7618100     KFLAG = KFLAG - 1
7619        NETF = NETF + 1
7620        NFLAG = -2
7621        TN = TOLD
7622        I1 = NQNYH + 1
7623        DO JB = 1, NQ
7624          I1 = I1 - LDYH
7625          DO I = I1, NQNYH
7626            YH1(I) = YH1(I) - YH1(I+LDYH)
7627          END DO
7628        END DO
7629        IF (ABS(H)<=HMIN*ONEPSM) GOTO 220
7630        ETAMAX = ONE
7631        IF (KFLAG<=KFC) GOTO 110
7632!       Compute ratio of new H to current H at the current order.
7633        FLOTL = REAL(L)
7634        ETA = ONE/((BIAS2*DSM)**(ONE/FLOTL)+ADDON)
7635        ETA = MAX(ETA,HMIN/ABS(H),ETAMIN)
7636        IF ((KFLAG<=-2) .AND. (ETA>ETAMXF)) ETA = ETAMXF
7637        GOTO 60
7638
7639! Control reaches this section if 3 or more consecutive failures
7640! have occurred. It is assumed that the elements of the YH array
7641! have accumulated errors of the wrong order. The order is reduced
7642! by one, if possible. Then H is reduced by a factor of 0.1 and
7643! the step is retried. After a total of 7 consecutive failures,
7644! an exit is taken with KFLAG = -1.
7645
7646!110     IF (KFLAG==KFH) GOTO 220
7647110     IF (KFLAG==CONSECUTIVE_EFAILS) GOTO 220
7648        IF (NQ==1) GOTO 120
7649        ETA = MAX(ETAMIN,HMIN/ABS(H))
7650        CALL DVJUST(YH,LDYH,-1)
7651        L = NQ
7652        NQ = NQ - 1
7653        NQWAIT = L
7654        GOTO 60
7655120     ETA = MAX(ETAMIN,HMIN/ABS(H))
7656        H = H*ETA
7657        HSCAL = H
7658        TAU(1) = H
7659        CALL F(N,TN,Y,SAVF)
7660        NFE = NFE + 1
7661        IF (BOUNDS) THEN
7662          DO I = 1, NDX
7663            IF (ABS(YH(IDX(I),1)-LB(I))<=ZERO) SAVF(IDX(I)) = &
7664              MAX(SAVF(IDX(I)),ZERO)
7665            IF (ABS(YH(IDX(I),1)-UB(I))<=ZERO) SAVF(IDX(I)) = &
7666              MIN(SAVF(IDX(I)),ZERO)
7667          END DO
7668        END IF
7669        YH(1:N,2) = H*SAVF(1:N)
7670        NQWAIT = 10
7671        GOTO 70
7672
7673! If NQWAIT = 0, an increase or decrease in order by one is considered.
7674! Factors ETAQ, ETAQM1, ETAQP1 are computed by which H could be
7675! multiplied at order q, q-1, or q+1, respectively. The largest of
7676! these is determined, and the new order and step size set accordingly.
7677! A change of H or NQ is made only if H increases by at least a factor
7678! of THRESH. If an order change is considered and rejected, then NQWAIT
7679! is set to 2 (reconsider it after 2 steps).
7680
7681!       Compute ratio of new H to current H at the current order.
7682130     FLOTL = REAL(L)
7683        ETAQ = ONE/((BIAS2*DSM)**(ONE/FLOTL)+ADDON)
7684        IF (NQWAIT/=0) GOTO 170
7685        NQWAIT = 2
7686        ETAQM1 = ZERO
7687        IF (NQ==1) GOTO 140
7688!       Compute ratio of new H to current H at the current order
7689!       less one.
7690! Original:
7691!       DDN = DVNORM(N,YH(1,L),EWT)/TQ(1)
7692        DDN = DVNORM(N,YH(1:N,L),EWT)/TQ(1)
7693        ETAQM1 = ONE/((BIAS1*DDN)**(ONE/(FLOTL-ONE))+ADDON)
7694140     ETAQP1 = ZERO
7695        IF (L==LMAX) GOTO 150
7696!       Compute ratio of new H to current H at current order plus one.
7697        CNQUOT = (TQ(5)/CONP)*(H/TAU(2))**L
7698        SAVF(1:N) = ACOR(1:N) - CNQUOT*YH(1:N,LMAX)
7699        DUP = DVNORM(N,SAVF,EWT)/TQ(3)
7700        ETAQP1 = ONE/((BIAS3*DUP)**(ONE/(FLOTL+ONE))+ADDON)
7701150     IF (ETAQ>=ETAQP1) GOTO 160
7702        IF (ETAQP1>ETAQM1) GOTO 190
7703        GOTO 180
7704160     IF (ETAQ<ETAQM1) GOTO 180
7705170     ETA = ETAQ
7706        NEWQ = NQ
7707        GOTO 200
7708180     ETA = ETAQM1
7709        NEWQ = NQ - 1
7710        GOTO 200
7711190     ETA = ETAQP1
7712        NEWQ = NQ + 1
7713! Original:
7714!       CALL DCOPY_F90(N,ACOR,1,YH(1,LMAX),1)
7715        CALL DCOPY_F90(N,ACOR,1,YH(1:N,LMAX),1)
7716!       Test tentative new H against THRESH, ETAMAX, and HMXI and
7717!       then exit.
7718200     IF (ETA<THRESH .OR. ABS(ETAMAX-ONE)<=ZERO) GOTO 210
7719        ETA = MIN(ETA,ETAMAX)
7720        ETA = ETA/MAX(ONE,ABS(H)*HMXI*ETA)
7721        NEWH = 1
7722        HNEW = H*ETA
7723        GOTO 250
7724210     NEWQ = NQ
7725        NEWH = 0
7726        ETA = ONE
7727        HNEW = H
7728        GOTO 250
7729
7730! All returns are made through this section.
7731! On a successful return, ETAMAX is reset and ACOR is scaled.
7732
7733220     KFLAG = -1
7734        GOTO 260
7735230     KFLAG = -2
7736        GOTO 260
7737240     IF (NFLAG==-2) KFLAG = -3
7738        IF (NFLAG==-3) KFLAG = -4
7739        GOTO 260
7740250     ETAMAX = ETAMX3
7741        IF (NST<=10) ETAMAX = ETAMX2
7742        R = ONE/TQ(2)
7743
7744        CALL DSCAL_F90(N,R,ACOR,1)
7745260     JSTART = 1
7746        RETURN
7747
7748      END SUBROUTINE DVSTEP
7749!_______________________________________________________________________
7750
7751      SUBROUTINE DVSET
7752! ..
7753! Set the integration coefficients for DVSTEP.
7754! ..
7755! For each order NQ, the coefficients in EL are calculated by use
7756! of the generating polynomial lambda(x), with coefficients EL(i).
7757!      lambda(x) = EL(1) + EL(2)*x + ... + EL(NQ+1)*(x**NQ).
7758! For the backward differentiation formulas,
7759!                                     NQ-1
7760!      lambda(x) = (1 + x/xi*(NQ)) * product (1 + x/xi(i)) .
7761!                                     i = 1
7762! For the Adams formulas,
7763!                              NQ-1
7764!      (d/dx) lambda(x) = c * product (1 + x/xi(i)),
7765!                              i = 1
7766!      lambda(-1) = 0,    lambda(0) = 1,
7767! where c is a normalization constant.
7768! In both cases, xi(i) is defined by
7769!      H*xi(i) = t sub n - t sub (n-i)
7770!              = H + TAU(1) + TAU(2) + ... TAU(i-1).
7771! In addition to variables described previously, communication
7772! with DVSET uses the following:
7773!   TAU    = A vector of length 13 containing the past NQ values
7774!            of H.
7775!   EL     = A vector of length 13 in which vset stores the
7776!            coefficients for the corrector formula.
7777!   TQ     = A vector of length 5 in which vset stores constants
7778!            used for the convergence test, the error test, and the
7779!            selection of H at a new order.
7780!   METH   = The basic method indicator.
7781!   NQ     = The current order.
7782!   L      = NQ + 1, the length of the vector stored in EL, and
7783!            the number of columns of the YH array being used.
7784!   NQWAIT = A counter controlling the frequency of order changes.
7785!            An order change is about to be considered if NQWAIT = 1.
7786! ..
7787     IMPLICIT NONE
7788! ..
7789! .. Local Scalars ..
7790        KPP_REAL :: AHATN0, ALPH0, CNQM1, CSUM, ELP, EM0, FLOTI, FLOTL, &
7791          FLOTNQ, HSUM, RXI, RXIS, S, T1, T2, T3, T4, T5, T6, XI
7792        INTEGER :: I, IBACK, J, JP1, NQM1, NQM2
7793! ..
7794! .. Local Arrays ..
7795        KPP_REAL :: EM(13)
7796! ..
7797! .. Intrinsic Functions ..
7798        INTRINSIC ABS, REAL
7799! ..
7800! .. FIRST EXECUTABLE STATEMENT DVSET
7801! ..
7802        FLOTL = REAL(L)
7803        NQM1 = NQ - 1
7804        NQM2 = NQ - 2
7805        GOTO (10,40) METH
7806
7807!       Set coefficients for Adams methods.
780810      IF (NQ/=1) GOTO 20
7809        EL(1) = ONE
7810        EL(2) = ONE
7811        TQ(1) = ONE
7812        TQ(2) = TWO
7813        TQ(3) = SIX*TQ(2)
7814        TQ(5) = ONE
7815        GOTO 60
781620      HSUM = H
7817        EM(1) = ONE
7818        FLOTNQ = FLOTL - ONE
7819        EM(2:L) = ZERO
7820        DO J = 1, NQM1
7821          IF ((J/=NQM1) .OR. (NQWAIT/=1)) GOTO 30
7822          S = ONE
7823          CSUM = ZERO
7824          DO I = 1, NQM1
7825            CSUM = CSUM + S*EM(I)/REAL(I+1)
7826            S = -S
7827          END DO
7828          TQ(1) = EM(NQM1)/(FLOTNQ*CSUM)
782930        RXI = H/HSUM
7830          DO IBACK = 1, J
7831            I = (J+2) - IBACK
7832            EM(I) = EM(I) + EM(I-1)*RXI
7833          END DO
7834          HSUM = HSUM + TAU(J)
7835        END DO
7836!       Compute integral from -1 to 0 of polynomial and of x times it.
7837        S = ONE
7838        EM0 = ZERO
7839        CSUM = ZERO
7840        DO I = 1, NQ
7841          FLOTI = REAL(I)
7842          EM0 = EM0 + S*EM(I)/FLOTI
7843          CSUM = CSUM + S*EM(I)/(FLOTI+ONE)
7844          S = -S
7845        END DO
7846!       In EL, form coefficients of normalized integrated polynomial.
7847        S = ONE/EM0
7848        EL(1) = ONE
7849        DO I = 1, NQ
7850          EL(I+1) = S*EM(I)/REAL(I)
7851        END DO
7852        XI = HSUM/H
7853        TQ(2) = XI*EM0/CSUM
7854        TQ(5) = XI/EL(L)
7855        IF (NQWAIT/=1) GOTO 60
7856!       For higher order control constant, multiply polynomial by
7857!       1+x/xi(q).
7858        RXI = ONE/XI
7859        DO IBACK = 1, NQ
7860          I = (L+1) - IBACK
7861          EM(I) = EM(I) + EM(I-1)*RXI
7862        END DO
7863!       Compute integral of polynomial.
7864        S = ONE
7865        CSUM = ZERO
7866        DO I = 1, L
7867          CSUM = CSUM + S*EM(I)/REAL(I+1)
7868          S = -S
7869        END DO
7870        TQ(3) = FLOTL*EM0/CSUM
7871        GOTO 60
7872
7873!       Set coefficients for BDF methods.
787440      EL(3:L) = ZERO
7875        EL(1) = ONE
7876        EL(2) = ONE
7877        ALPH0 = -ONE
7878        AHATN0 = -ONE
7879        HSUM = H
7880        RXI = ONE
7881        RXIS = ONE
7882        IF (NQ==1) GOTO 50
7883        DO J = 1, NQM2
7884!       In EL, construct coefficients of (1+x/xi(1))*...*(1+x/xi(j+1)).
7885          HSUM = HSUM + TAU(J)
7886          RXI = H/HSUM
7887          JP1 = J + 1
7888          ALPH0 = ALPH0 - ONE/REAL(JP1)
7889          DO IBACK = 1, JP1
7890            I = (J+3) - IBACK
7891            EL(I) = EL(I) + EL(I-1)*RXI
7892          END DO
7893        END DO
7894        ALPH0 = ALPH0 - ONE/REAL(NQ)
7895        RXIS = -EL(2) - ALPH0
7896        HSUM = HSUM + TAU(NQM1)
7897        RXI = H/HSUM
7898        AHATN0 = -EL(2) - RXI
7899        DO IBACK = 1, NQ
7900          I = (NQ+2) - IBACK
7901          EL(I) = EL(I) + EL(I-1)*RXIS
7902        END DO
790350      T1 = ONE - AHATN0 + ALPH0
7904        T2 = ONE + REAL(NQ)*T1
7905        TQ(2) = ABS(ALPH0*T2/T1)
7906        TQ(5) = ABS(T2/(EL(L)*RXI/RXIS))
7907        IF (NQWAIT/=1) GOTO 60
7908        CNQM1 = RXIS/EL(L)
7909        T3 = ALPH0 + ONE/REAL(NQ)
7910        T4 = AHATN0 + RXI
7911        ELP = T3/(ONE-T4+T3)
7912        TQ(1) = ABS(ELP/CNQM1)
7913        HSUM = HSUM + TAU(NQ)
7914        RXI = H/HSUM
7915        T5 = ALPH0 - ONE/REAL(NQ+1)
7916        T6 = AHATN0 - RXI
7917        ELP = T2/(ONE-T6+T5)
7918        TQ(3) = ABS(ELP*RXI*(FLOTL+ONE)*T5)
791960      TQ(4) = CORTES*TQ(2)
7920        RETURN
7921
7922      END SUBROUTINE DVSET
7923!_______________________________________________________________________
7924
7925      SUBROUTINE DVJUST(YH,LDYH,IORD)
7926! ..
7927! Adjust the Nordsieck array.
7928! ..
7929! This subroutine adjusts the YH array on reduction of order, and
7930! also when the order is increased for the stiff option (METH = 2).
7931! Communication with DVJUST uses the following:
7932! IORD  = An integer flag used when METH = 2 to indicate an order
7933!         increase (IORD = +1) or an order decrease (IORD = -1).
7934! HSCAL = Step size H used in scaling of Nordsieck array YH.
7935!         (If IORD = +1, DVJUST assumes that HSCAL = TAU(1).)
7936! See References 1 and 2 for details.
7937! ..
7938     IMPLICIT NONE
7939! ..
7940! .. Scalar Arguments ..
7941        INTEGER, INTENT (IN) :: IORD, LDYH
7942! ..
7943! .. Array Arguments ..
7944        KPP_REAL, INTENT (INOUT) :: YH(LDYH,*)
7945! ..
7946! .. Local Scalars ..
7947        KPP_REAL :: ALPH0, ALPH1, HSUM, PROD, T1, XI, XIOLD
7948        INTEGER :: I, IBACK, J, JP1, LP1, NQM1, NQM2, NQP1
7949! ..
7950! .. Intrinsic Functions ..
7951        INTRINSIC REAL
7952! ..
7953! .. FIRST EXECUTABLE STATEMENT DVJUST
7954! ..
7955        IF ((NQ==2) .AND. (IORD/=1)) RETURN
7956        NQM1 = NQ - 1
7957        NQM2 = NQ - 2
7958        GOTO (10,30) METH
7959
7960!       Nonstiff option.
7961
7962!       Check to see if the order is being increased or decreased.
796310      CONTINUE
7964        IF (IORD==1) GOTO 20
7965!       Order decrease.
7966        EL(1:LMAX) = ZERO
7967        EL(2) = ONE
7968        HSUM = ZERO
7969        DO J = 1, NQM2
7970!         Construct coefficients of x*(x+xi(1))*...*(x+xi(j)).
7971          HSUM = HSUM + TAU(J)
7972          XI = HSUM/HSCAL
7973          JP1 = J + 1
7974          DO IBACK = 1, JP1
7975            I = (J+3) - IBACK
7976            EL(I) = EL(I)*XI + EL(I-1)
7977          END DO
7978        END DO
7979!       Construct coefficients of integrated polynomial.
7980        DO J = 2, NQM1
7981          EL(J+1) = REAL(NQ)*EL(J)/REAL(J)
7982        END DO
7983!       Subtract correction terms from YH array.
7984        DO J = 3, NQ
7985          DO I = 1, N
7986            YH(I,J) = YH(I,J) - YH(I,L)*EL(J)
7987          END DO
7988        END DO
7989        RETURN
7990!       Order increase.
7991!       Zero out next column in YH array.
799220      CONTINUE
7993        LP1 = L + 1
7994        YH(1:N,LP1) = ZERO
7995        RETURN
7996
7997!       Stiff option.
7998
7999!       Check to see if the order is being increased or decreased.
800030      CONTINUE
8001        IF (IORD==1) GOTO 40
8002!       Order decrease.
8003        EL(1:LMAX) = ZERO
8004        EL(3) = ONE
8005        HSUM = ZERO
8006        DO J = 1, NQM2
8007!     Construct coefficients of x*x*(x+xi(1))*...*(x+xi(j)).
8008          HSUM = HSUM + TAU(J)
8009          XI = HSUM/HSCAL
8010          JP1 = J + 1
8011          DO IBACK = 1, JP1
8012            I = (J+4) - IBACK
8013            EL(I) = EL(I)*XI + EL(I-1)
8014          END DO
8015        END DO
8016!       Subtract correction terms from YH array.
8017        DO J = 3, NQ
8018          YH(1:N,J) = YH(1:N,J) - YH(1:N,L)*EL(J)
8019        END DO
8020        RETURN
8021!       Order increase.
802240      EL(1:LMAX) = ZERO
8023        EL(3) = ONE
8024        ALPH0 = -ONE
8025        ALPH1 = ONE
8026        PROD = ONE
8027        XIOLD = ONE
8028        HSUM = HSCAL
8029        IF (NQ==1) GOTO 50
8030        DO J = 1, NQM1
8031!       Construct coefficients of x*x*(x+xi(1))*...*(x+xi(j)).
8032          JP1 = J + 1
8033          HSUM = HSUM + TAU(JP1)
8034          XI = HSUM/HSCAL
8035          PROD = PROD*XI
8036          ALPH0 = ALPH0 - ONE/REAL(JP1)
8037          ALPH1 = ALPH1 + ONE/XI
8038          DO IBACK = 1, JP1
8039            I = (J+4) - IBACK
8040            EL(I) = EL(I)*XIOLD + EL(I-1)
8041          END DO
8042          XIOLD = XI
8043        END DO
804450      CONTINUE
8045        T1 = (-ALPH0-ALPH1)/PROD
8046!       Load column L+1 in YH array.
8047        LP1 = L + 1
8048        YH(1:N,LP1) = T1*YH(1:N,LMAX)
8049!       Add correction terms to YH array.
8050        NQP1 = NQ + 1
8051        DO J = 3, NQP1
8052! Original:
8053!         CALL DAXPY_F90(N,EL(J),YH(1,LP1),1,YH(1,J),1)
8054          CALL DAXPY_F90(N,EL(J),YH(1:N,LP1),1,YH(1:N,J),1)
8055        END DO
8056        RETURN
8057
8058      END SUBROUTINE DVJUST
8059!_______________________________________________________________________
8060
8061      SUBROUTINE DVNLSD(Y,YH,LDYH,SAVF,EWT,ACOR,IWM,WM,F,JAC,NFLAG,&
8062        ATOL,ITOL)
8063! ..
8064! This is the nonlinear system solver for dense and banded solutions.
8065! ..
8066! Subroutine DVNLSD is a nonlinear system solver which uses functional
8067! iteration or a chord (modified Newton) method. For the chord method
8068! direct linear algebraic system solvers are used. Subroutine DVNLSD
8069! then handles the corrector phase of this integration package.
8070! Communication with DVNLSD is done with the following variables. (For
8071! more details, please see the comments in the driver subroutine.)
8072! Y          = The dependent variable, a vector of length N, input.
8073! YH         = The Nordsieck (Taylor) array, LDYH by LMAX, input
8074!              and output. On input, it contains predicted values.
8075! LDYH       = A constant >= N, the first dimension of YH, input.
8076! SAVF       = A work array of length N.
8077! EWT        = An error weight vector of length N, input.
8078! ACOR       = A work array of length N, used for the accumulated
8079!              corrections to the predicted y vector.
8080! WM,IWM     = Real and integer work arrays associated with matrix
8081!              operations in chord iteration (MITER /= 0).
8082! F          = Dummy name for user supplied routine for f.
8083! JAC        = Dummy name for user supplied Jacobian routine.
8084! NFLAG      = Input/output flag, with values and meanings as follows:
8085!              INPUT
8086!                  0 first call for this time step.
8087!                 -1 convergence failure in previous call to DVNLSD.
8088!                 -2 error test failure in DVSTEP.
8089!              OUTPUT
8090!                  0 successful completion of nonlinear solver.
8091!                 -1 convergence failure or singular matrix.
8092!                 -2 unrecoverable error in matrix preprocessing
8093!                    (cannot occur here).
8094!                 -3 unrecoverable error in solution (cannot occur
8095!                    here).
8096! IPUP       = Own variable flag with values and meanings as follows:
8097!              0,          do not update the Newton matrix.
8098!              MITER /= 0  update Newton matrix, because it is the
8099!                          initial step, order was changed, the error
8100!                          test failed, or an update is indicated by
8101!                          the scalar RC or step counter NST.
8102! For more details, see comments in driver subroutine.
8103! ..
8104     IMPLICIT NONE
8105! ..
8106! .. Scalar Arguments ..
8107        INTEGER, INTENT (IN) :: ITOL, LDYH
8108        INTEGER, INTENT (INOUT) :: NFLAG
8109! ..
8110! .. Array Arguments ..
8111        KPP_REAL, INTENT (INOUT) :: ACOR(*), EWT(*), SAVF(*), &
8112          WM(*), Y(*), YH(LDYH,*)
8113        KPP_REAL, INTENT (IN) :: ATOL(*)
8114        INTEGER, INTENT (INOUT) :: IWM(*)
8115! ..
8116! .. Subroutine Arguments ..
8117        EXTERNAL F, JAC
8118! ..
8119! .. Local Scalars ..
8120        KPP_REAL :: ACNRMNEW, CSCALE, DCON, DEL, DELP
8121        INTEGER :: I, IERPJ, IERSL, M
8122! ..
8123! .. Intrinsic Functions ..
8124        INTRINSIC ABS, MAX, MIN
8125! ..
8126! .. FIRST EXECUTABLE STATEMENT DVNLSD
8127! ..
8128! On the first step, on a change of method order, or after a
8129! nonlinear convergence failure with NFLAG = -2, set IPUP = MITER
8130! to force a Jacobian update when MITER /= 0.
8131        IF (JSTART==0) NSLP = 0
8132        IF (NFLAG==0) ICF = 0
8133        IF (NFLAG==-2) IPUP = MITER
8134        IF ((JSTART==0) .OR. (JSTART==-1)) IPUP = MITER
8135!     If this is functional iteration, set CRATE = 1 and drop to 220
8136        IF (MITER==0) THEN
8137          CRATE = ONE
8138          GOTO 10
8139        END IF
8140
8141! RC is the ratio of new to old values of the coefficient H/EL(2)=h/l1.
8142! When RC differs from 1 by more than CCMAX, IPUP is set to MITER to
8143! force DVJAC to be called, if a Jacobian is involved. In any case,
8144! DVJAC is called at least every MSBP steps.
8145
8146        DRC = ABS(RC-ONE)
8147        IF (DRC>CCMAX .OR. NST>=NSLP+MSBP) IPUP = MITER
8148
8149! Up to MAXCOR corrector iterations are taken. A convergence test is
8150! made on the r.m.s. norm of each correction, weighted by the error
8151! weight vector EWT. The sum of the corrections is accumulated in the
8152! vector ACOR(i). The YH array is not altered in the corrector loop.
8153
815410      M = 0
8155        DELP = ZERO
8156! Original:
8157!       CALL DCOPY_F90(N,YH(1,1),1,Y,1)
8158        CALL DCOPY_F90(N,YH(1:N,1),1,Y(1:N),1)
8159        CALL F(N,TN,Y,SAVF)
8160        NFE = NFE + 1
8161        IF (BOUNDS) THEN
8162          DO I = 1, NDX
8163            IF (ABS(YH(IDX(I),1)-LB(I))<=ZERO) SAVF(IDX(I)) = &
8164               MAX(SAVF(IDX(I)),ZERO)
8165            IF (ABS(YH(IDX(I),1)-UB(I))<=ZERO) SAVF(IDX(I)) = &
8166               MIN(SAVF(IDX(I)),ZERO)
8167          END DO
8168        END IF
8169        IF (IPUP<=0) GOTO 20
8170
8171! If indicated, the matrix P = I - h*rl1*J is reevaluated and
8172! preprocessed before starting the corrector iteration. IPUP
8173! is set to 0 as an indicator that this has been done.
8174
8175        CALL DVJAC(Y,YH,LDYH,EWT,ACOR,SAVF,WM,IWM,F,JAC,IERPJ, &
8176          ATOL,ITOL)
8177        IPUP = 0
8178        RC = ONE
8179        DRC = ZERO
8180        CRATE = ONE
8181        NSLP = NST
8182!       If matrix is singular, take error return to force cut in
8183!       step size.
8184        IF (IERPJ/=0) GOTO 70
818520      ACOR(1:N) = ZERO
8186!       This is a looping point for the corrector iteration.
818730      IF (MITER/=0) GOTO 40
8188
8189! In the case of functional iteration, update Y directly from
8190! the result of the last function evaluation.
8191
8192        SAVF(1:N) = RL1*(H*SAVF(1:N)-YH(1:N,2))
8193        Y(1:N) = SAVF(1:N) - ACOR(1:N)
8194        DEL = DVNORM(N,Y,EWT)
8195        Y(1:N) = YH(1:N,1) + SAVF(1:N)
8196        CALL DCOPY_F90(N,SAVF,1,ACOR,1)
8197        GOTO 50
8198
8199! In the case of the chord method, compute the corrector error, and
8200! solve the linear system with that as right-hand side and P as
8201! coefficient matrix. The correction is scaled by the factor
8202! 2/(1+RC) to account for changes in h*rl1 since the last DVJAC call.
8203
820440      Y(1:N) = (RL1*H)*SAVF(1:N) - (RL1*YH(1:N,2)+ACOR(1:N))
8205        CALL DVSOL(WM,IWM,Y,IERSL)
8206        NNI = NNI + 1
8207        IF (IERSL>0) GOTO 60
8208        IF (METH==2 .AND. ABS(RC-ONE)>ZERO) THEN
8209          CSCALE = TWO/(ONE+RC)
8210          CALL DSCAL_F90(N,CSCALE,Y,1)
8211        END IF
8212        DEL = DVNORM(N,Y,EWT)
8213        CALL DAXPY_F90(N,ONE,Y,1,ACOR,1)
8214        Y(1:N) = YH(1:N,1) + ACOR(1:N)
8215
8216! Test for convergence. If M > 0, an estimate of the convergence
8217! rate constant is stored in CRATE, and this is used in the test.
8218
821950      IF (M/=0) CRATE = MAX(CRDOWN*CRATE,DEL/DELP)
8220        DCON = DEL*MIN(ONE,CRATE)/TQ(4)
8221        IF (DCON<=ONE) GOTO 80
8222        M = M + 1
8223        IF (M==MAXCOR) GOTO 60
8224        IF (M>=2 .AND. DEL>RDIV*DELP) GOTO 60
8225        DELP = DEL
8226        CALL F(N,TN,Y,SAVF)
8227        NFE = NFE + 1
8228        IF (BOUNDS) THEN
8229          DO I = 1, NDX
8230            IF (ABS(YH(IDX(I),1)-LB(I))<=ZERO) SAVF(IDX(I)) = &
8231               MAX(SAVF(IDX(I)),ZERO)
8232            IF (ABS(YH(IDX(I),1)-UB(I))<=ZERO) SAVF(IDX(I)) = &
8233               MIN(SAVF(IDX(I)),ZERO)
8234          END DO
8235        END IF
8236        GOTO 30
8237
823860      IF (MITER==0 .OR. JCUR==1) GOTO 70
8239        ICF = 1
8240        IPUP = MITER
8241        GOTO 10
8242
824370      CONTINUE
8244        NFLAG = -1
8245        ICF = 2
8246        IPUP = MITER
8247        RETURN
8248
8249!       Return for successful step.
825080      CONTINUE
8251
8252!       Enforce bounds.
8253        IF (BOUNDS) THEN
8254          CHANGED_ACOR = .FALSE.
8255          IF (M==0) THEN
8256            ACNRM = DEL
8257          ELSE
8258            ACNRM = DVNORM(N,ACOR,EWT)
8259          END IF
8260          IF (MITER/=0) THEN
8261!           Since Y(:) = YH(:,1) + ACOR(:) ...
8262            DO I = 1, NDX
8263              IF (Y(IDX(I))<LB(I)) THEN
8264                CHANGED_ACOR = .TRUE.
8265                ACOR(IDX(I)) = LB(I) - YH(IDX(I),1)
8266                SAVF(IDX(I)) = ACOR(IDX(I))
8267              END IF
8268              IF (Y(IDX(I))>UB(I)) THEN
8269                CHANGED_ACOR = .TRUE.
8270                ACOR(IDX(I)) = UB(I) - YH(IDX(I),1)
8271                SAVF(IDX(I)) = ACOR(IDX(I))
8272              END IF
8273            END DO
8274          ELSE
8275!           Since Y(:) = YH(:,1) + SAVF(:) and
8276!           since CALL DCOPY_F90(N,SAVF,1,ACOR,1) ...
8277            DO I = 1, NDX
8278              IF (Y(IDX(I))<LB(IDX(I))) THEN
8279                CHANGED_ACOR = .TRUE.
8280                ACOR(IDX(I)) = LB(I) - YH(IDX(I),1)
8281              END IF
8282              IF (Y(IDX(I))>UB(IDX(I))) THEN
8283                CHANGED_ACOR = .TRUE.
8284                ACOR(IDX(I)) = UB(I) - YH(IDX(I),1)
8285              END IF
8286            END DO
8287          END IF
8288          IF (CHANGED_ACOR) THEN
8289            IF (M==0) THEN
8290              ACNRMNEW = DEL
8291            ELSE
8292              ACNRMNEW = DVNORM(N,ACOR,EWT)
8293            END IF
8294!           ACNRM = ACNRMNEW
8295            ACNRM = MAX(ACNRM,ACNRMNEW)
8296          ELSE
8297          END IF
8298          NFLAG = 0
8299          JCUR = 0
8300          ICF = 0
8301        ELSE
8302!         No projections are required.
8303          NFLAG = 0
8304          JCUR = 0
8305          ICF = 0
8306          IF (M==0) ACNRM = DEL
8307          IF (M>0) ACNRM = DVNORM(N,ACOR,EWT)
8308        END IF
8309        RETURN
8310
8311      END SUBROUTINE DVNLSD
8312!_______________________________________________________________________
8313
8314      SUBROUTINE DVJAC(Y,YH,LDYH,EWT,FTEM,SAVF,WM,IWM,F,JAC,IERPJ, &
8315        ATOL,ITOL)
8316! ..
8317! Compute and process the matrix P = I - h*rl1*J, where J is an
8318! approximation to the Jacobian for dense and banded solutions.
8319! ..
8320! This is a version of DVJAC that allows use of the known nonzero
8321! diagonals if it is available.
8322! DVJAC is called by DVNLSD to compute and process the matrix
8323! P = I - h*rl1*J, where J is an approximation to the Jacobian.
8324! Here J is computed by the user-supplied routine JAC if
8325! MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5.
8326! If MITER = 3, a diagonal approximation to J is used.
8327! If JSV = -1, J is computed from scratch in all cases.
8328! If JSV = 1 and MITER = 1, 2, 4, or 5, and if the saved value of J is
8329! considered acceptable, then P is constructed from the saved J.
8330! J is stored in wm and replaced by P. If MITER /= 3, P is then
8331! subjected to LU decomposition in preparation for later solution
8332! of linear systems with P as coefficient matrix. This is done
8333! by DGEFA_F90 if MITER = 1 or 2, and by DGBFA_F90 if MITER = 4 or 5.
8334! Communication with DVJAC is done with the following variables.
8335! (For more details, please see the comments in the driver subroutine.)
8336! Y          = Vector containing predicted values on entry.
8337! YH         = The Nordsieck array, an LDYH by LMAX array, input.
8338! LDYH       = A constant >= N, the first dimension of YH, input.
8339! EWT        = An error weight vector of length N.
8340! SAVF       = Array containing f evaluated at predicted y, input.
8341! WM         = Real work space for matrices. In the output, it contains
8342!              the inverse diagonal matrix if MITER = 3 and the LU
8343!              decomposition of P if MITER is 1, 2, 4, or 5.
8344!              Storage of matrix elements starts at WM(1).
8345!              Storage of the saved Jacobian starts at WM(LOCJS).
8346! IWM        = Integer work space containing pivot information,
8347!              starting at IWM(31), if MITER is 1, 2, 4, or 5.
8348!              IWM also contains band parameters ML = IWM(1) and
8349!              MU = IWM(2) if MITER is 4 or 5.
8350! F          = Dummy name for the user supplied subroutine for f.
8351! JAC        = Dummy name for the user supplied Jacobian subroutine.
8352! RL1        = 1/EL(2) (input).
8353! IERPJ      = Output error flag, = 0 if no trouble, 1 if the P
8354!              matrix is found to be singular.
8355! JCUR       = Output flag to indicate whether the Jacobian matrix
8356!              (or approximation) is now current.
8357!              JCUR = 0 means J is not current.
8358!              JCUR = 1 means J is current.
8359! ..
8360     IMPLICIT NONE
8361! ..
8362! .. Scalar Arguments ..
8363        INTEGER, INTENT (INOUT) :: IERPJ
8364        INTEGER, INTENT (IN) :: LDYH, ITOL
8365! ..
8366! .. Array Arguments ..
8367        KPP_REAL, INTENT (INOUT) :: EWT(*), FTEM(*), SAVF(*), WM(*), &
8368          Y(*),YH(LDYH,*)
8369        KPP_REAL, INTENT (IN) :: ATOL(*)
8370        INTEGER, INTENT (INOUT) :: IWM(*)
8371! ..
8372! .. Subroutine Arguments ..
8373        EXTERNAL F, JAC
8374! ..
8375! .. Local Scalars ..
8376        KPP_REAL :: CON, DI, FAC, HRL1, R, R0, SRUR, YI, YJ, YJJ
8377        INTEGER :: I, I1, I2, IER, II, J, J1, JJ, JJ1, JJ2, JOK, K,   &
8378          K1, K2, LENP, MBA, MBAND, MEB1, MEBAND, ML, ML1, MU, NG, NP1
8379!         K1, K2, LENP, MBA, MBAND, MEB1, MEBAND, ML, ML3, MU, NG, NP1
8380! ..
8381! .. Intrinsic Functions ..
8382        INTRINSIC ABS, MAX, MIN, REAL
8383! ..
8384! .. FIRST EXECUTABLE STATEMENT DVJAC
8385! ..
8386        IERPJ = 0
8387        HRL1 = H*RL1
8388!       See whether J should be evaluated (JOK = -1) or not (JOK = 1).
8389        JOK = JSV
8390        IF (JSV==1) THEN
8391          IF (NST==0 .OR. NST>NSLJ+MSBJ) JOK = -1
8392          IF (ICF==1 .AND. DRC<CCMXJ) JOK = -1
8393          IF (ICF==2) JOK = -1
8394        END IF
8395        IF (J_IS_CONSTANT .AND. J_HAS_BEEN_COMPUTED) JOK = 1
8396!       End of setting JOK.
8397
8398        IF (JOK==-1 .AND. MITER==1) THEN
8399!         If JOK = -1 and MITER = 1, call JAC to evaluate Jacobian.
8400          NJE = NJE + 1
8401          NSLJ = NST
8402          JCUR = 1
8403          LENP = N*N
8404!         WM(3:LENP+2) = ZERO
8405          WM(1:LENP) = ZERO
8406!         CALL JAC(N,TN,Y,0,0,WM(3),N)
8407          CALL JAC(N,TN,Y,0,0,WM(1),N)
8408          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
8409!         IF (JSV==1) CALL DCOPY_F90(LENP,WM(3),1,WM(LOCJS),1)
8410          IF (JSV==1) CALL DCOPY_F90(LENP,WM(1),1,WM(LOCJS),1)
8411        END IF
8412
8413!       Set flag to indicate how the YSCALE vector will be set for
8414!       JACSP.
8415        LIKE_ORIGINAL_VODE = .FALSE.
8416
8417        IF (JOK==-1 .AND. MITER==2) THEN
8418           IF (USE_JACSP) THEN
8419!             Approximate the Jacobian using Doug Salane's JACSP.
8420              NSLJ = NST
8421              JCUR = 1
8422              IOPTDS(1) = 0
8423              IOPTDS(2) = 0
8424              IOPTDS(3) = 1
8425              IOPTDS(5) = 0
8426!             INFORDS(4) was initialized in DVODE.
8427              LWKDS  = 3 * N
8428              LIWKDS = 50 + N
8429              NRFJACDS = N
8430              NCFJACDS = N
8431              MAXGRPDS = N
8432!             Calculate the YSCALEDS vector for JACSPDV.
8433              IF (LIKE_ORIGINAL_VODE) THEN
8434                 FAC = DVNORM(N,SAVF,EWT)
8435!                JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
8436!                R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
8437                 R0 = THOU*ABS(H)*REAL(N)*FAC
8438                 IF (ABS(R0)<=ZERO) R0 = ONE
8439                 SRUR = WM1
8440                 DO J = 1, N
8441!                   JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
8442!                   R = MAX(ABS(Y(J)),R0/EWT(J))
8443                    R = MAX(ABS(Y(J))/U325,(R0/EWT(J))*U125)
8444                    YSCALEDS(J) = R
8445                 END DO
8446              ELSE
8447                 IF (ITOL == 1 .OR. ITOL == 3) THEN
8448                    DO J = 1, N
8449                       YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(1),UROUND)
8450                    END DO
8451                 ELSE
8452                    DO J = 1, N
8453                       YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(J),UROUND)
8454                    END DO
8455                 END IF
8456              END IF
8457
8458              CALL JACSPDB(F,N,TN,Y,SAVF,WM(1),NRFJACDS, &
8459                YSCALEDS,FACDS,IOPTDS,WKDS,LWKDS,IWKDS,LIWKDS, &
8460                MAXGRPDS,NGRPDS,JPNTRDS,INDROWDS)
8461              NFE = NFE + IWKDS(7)
8462              NJE = NJE + 1
8463           ELSE
8464!             If MITER = 2, make N calls to F to approximate the Jacobian.
8465              NSLJ = NST
8466              JCUR = 1
8467              FAC = DVNORM(N,SAVF,EWT)
8468              R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
8469              IF (ABS(R0)<=ZERO) R0 = ONE
8470              SRUR = WM1
8471!             J1 = 2
8472              J1 = 0
8473              DO J = 1, N
8474                 YJ = Y(J)
8475                 R = MAX(SRUR*ABS(YJ),R0/EWT(J))
8476                 Y(J) = Y(J) + R
8477                 FAC = ONE/R
8478                 CALL F(N,TN,Y,FTEM)
8479                 DO I = 1, N
8480                   WM(I+J1) = (FTEM(I)-SAVF(I))*FAC
8481                 END DO
8482                 Y(J) = YJ
8483                 J1 = J1 + N
8484              END DO
8485              NFE = NFE + N
8486              NJE = NJE + 1
8487           END IF
8488           LENP = N*N
8489!          IF (JSV==1) CALL DCOPY_F90(LENP,WM(3),1,WM(LOCJS),1)
8490           IF (JSV==1) CALL DCOPY_F90(LENP,WM(1),1,WM(LOCJS),1)
8491           IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
8492        END IF
8493
8494        IF (JOK==1 .AND. (MITER==1 .OR. MITER==2)) THEN
8495          JCUR = 0
8496          LENP = N*N
8497!         CALL DCOPY_F90(LENP,WM(LOCJS),1,WM(3),1)
8498          CALL DCOPY_F90(LENP,WM(LOCJS),1,WM(1),1)
8499        END IF
8500
8501        IF (MITER==1 .OR. MITER==2) THEN
8502!         Multiply Jacobian by scalar, add identity, and do LU
8503!         decomposition.
8504          CON = -HRL1
8505!         CALL DSCAL_F90(LENP,CON,WM(3),1)
8506          CALL DSCAL_F90(LENP,CON,WM(1),1)
8507!         J = 3
8508          J = 1
8509          NP1 = N + 1
8510          DO I = 1, N
8511            WM(J) = WM(J) + ONE
8512            J = J + NP1
8513          END DO
8514          NLU = NLU + 1
8515! ______________________________________________________________________
8516
8517!         CALL DGEFA_F90(WM(3),N,N,IWM(31),IER)
8518          CALL DGEFA_F90(WM(1),N,N,IWM(31),IER)
8519          IF (IER/=0) IERPJ = 1
8520! *****LAPACK build change point. Replace above with these statements.
8521!        IF (.NOT.USE_LAPACK) THEN
8522!!         CALL DGEFA_f90(WM(3),N,N,IWM(31),IER)
8523!          CALL DGEFA_f90(WM(1),N,N,IWM(31),IER)
8524!          IF (IER /= 0) IERPJ = 1
8525!        ELSE
8526!!         CALL DGETRF(N,N,WM(3),N,IWM(31),IER)
8527!          CALL DGETRF(N,N,WM(1),N,IWM(31),IER)
8528!          IF (IER /= 0) IERPJ = 1
8529!        END IF
8530! ______________________________________________________________________
8531
8532          RETURN
8533        END IF
8534!       End of code block for MITER = 1 or 2.
8535
8536        IF (MITER==3) THEN
8537!         If MITER = 3, construct a diagonal approximation to
8538!         J and P.
8539          NJE = NJE + 1
8540          JCUR = 1
8541          WM2 = HRL1
8542          R = RL1*PT1
8543          Y(1:N) = Y(1:N) + R*(H*SAVF(1:N)-YH(1:N,2))
8544!         CALL F(N,TN,Y,WM(3))
8545          CALL F(N,TN,Y,WM(1))
8546          NFE = NFE + 1
8547          DO 10 I = 1, N
8548            R0 = H*SAVF(I) - YH(I,2)
8549!           DI = PT1*R0 - H*(WM(I+2)-SAVF(I))
8550            DI = PT1*R0 - H*(WM(I)-SAVF(I))
8551!           WM(I+2) = ONE
8552            WM(I) = ONE
8553            IF (ABS(R0)<UROUND/EWT(I)) GOTO 10
8554            IF (ABS(DI)<=ZERO) GOTO 20
8555!           WM(I+2) = PT1*R0/DI
8556            WM(I) = PT1*R0/DI
855710        END DO
8558          RETURN
855920        IERPJ = 1
8560          RETURN
8561        END IF
8562!       End of code block for MITER = 3.
8563
8564!       Set constants for MITER = 4 or 5.
8565        ML = IWM(1)
8566        MU = IWM(2)
8567!       ML3 = ML + 3
8568        ML1 = ML + 1
8569        MBAND = ML + MU + 1
8570        MEBAND = MBAND + ML
8571        LENP = MEBAND*N
8572
8573        IF (JOK==-1 .AND. MITER==4) THEN
8574!       If JOK = -1 and MITER = 4, call JAC to evaluate Jacobian.
8575          NJE = NJE + 1
8576          NSLJ = NST
8577          JCUR = 1
8578!         WM(3:LENP+2) = ZERO
8579          WM(1:LENP) = ZERO
8580!         CALL JAC(N,TN,Y,ML,MU,WM(ML3),MEBAND)
8581          CALL JAC(N,TN,Y,ML,MU,WM(ML1),MEBAND)
8582          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
8583!         IF (JSV==1) CALL DACOPY(MBAND,N,WM(ML3),MEBAND,WM(LOCJS),MBAND)
8584          IF (JSV==1) CALL DACOPY(MBAND,N,WM(ML1),MEBAND,WM(LOCJS),MBAND)
8585        END IF
8586
8587        IF (JOK==-1 .AND. MITER==5) THEN
8588!       If MITER = 5, make ML+MU+1 calls to F to approximate the Jacobian
8589!       unless the user has specified which sub and super diagonals are
8590!       nonzero. In the latter case NSUBS+NSUPS+1 calls will be made.
8591
8592!         If the subdiagonals are known, use that information to build
8593!         the Jacobian matrix.
8594          IF ((SUBS .OR. SUPS) .OR. BNGRP >= MBAND) GOTO 60
8595
8596!         Otherwise, use the original algorithm.
8597          IF (USE_JACSP) THEN
8598!            Approximate the Jacobian using Doug Salane's JACSP.
8599             NSLJ = NST
8600             JCUR = 1
8601             WM(1:LENP) = ZERO
8602             IOPTDS(1) = 1
8603             IOPTDS(2) = MBAND
8604             IOPTDS(3) = 1
8605             IOPTDS(5) = ML
8606!            INFORDS(4) was initialized in DVODE.
8607             LWKDS  = 3 * N
8608             LIWKDS = 50 + N
8609!            NRFJACDS = MEBAND*N
8610!            NCFJACDS = 1
8611             NRFJACDS = MEBAND
8612             NCFJACDS = N
8613             MBA = MIN(MBAND,N)
8614             MAXGRPDS = MBA
8615!            Calculate the YSCALEDS vector for JACSPDV.
8616             IF (LIKE_ORIGINAL_VODE) THEN
8617                FAC = DVNORM(N,SAVF,EWT)
8618!               JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
8619!               R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
8620                R0 = THOU*ABS(H)*REAL(N)*FAC
8621                IF (ABS(R0)<=ZERO) R0 = ONE
8622                SRUR = WM1
8623                DO J = 1, N
8624!                  JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
8625!                  R = MAX(ABS(Y(J)),R0/EWT(J))
8626                   R = MAX(ABS(Y(J))/U325,(R0/EWT(J))*U125)
8627                   YSCALEDS(J) = R
8628                END DO
8629             ELSE
8630                IF (ITOL == 1 .OR. ITOL == 3) THEN
8631                   DO J = 1, N
8632                      YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(1),UROUND)
8633                   END DO
8634                ELSE
8635                   DO J = 1, N
8636                      YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(J),UROUND)
8637                   END DO
8638                END IF
8639             END IF
8640             CALL JACSPDB(F,N,TN,Y,SAVF,WM(1),NRFJACDS, &
8641               YSCALEDS,FACDS,IOPTDS,WKDS,LWKDS,IWKDS,LIWKDS,  &
8642               MAXGRPDS,NGRPDS,JPNTRDS,INDROWDS)
8643             NFE = NFE + IWKDS(7)
8644             NJE = NJE + 1
8645          ELSE
8646             NSLJ = NST
8647             JCUR = 1
8648             MBA = MIN(MBAND,N)
8649             MEB1 = MEBAND - 1
8650             SRUR = WM1
8651             FAC = DVNORM(N,SAVF,EWT)
8652             R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
8653             IF (ABS(R0)<=ZERO) R0 = ONE
8654             DO J = 1, MBA
8655               DO I = J, N, MBAND
8656                 YI = Y(I)
8657                 R = MAX(SRUR*ABS(YI),R0/EWT(I))
8658                 Y(I) = Y(I) + R
8659               END DO
8660               CALL F(N,TN,Y,FTEM)
8661               DO JJ = J, N, MBAND
8662                 Y(JJ) = YH(JJ,1)
8663                 YJJ = Y(JJ)
8664                 R = MAX(SRUR*ABS(YJJ),R0/EWT(JJ))
8665                 FAC = ONE/R
8666                 I1 = MAX(JJ-MU,1)
8667                 I2 = MIN(JJ+ML,N)
8668!                II = JJ*MEB1 - ML + 2
8669                 II = JJ*MEB1 - ML
8670                 DO I = I1, I2
8671                   WM(II+I) = (FTEM(I)-SAVF(I))*FAC
8672                 END DO
8673               END DO
8674             END DO
8675             NFE = NFE + MBA
8676             NJE = NJE + 1
8677          END IF
8678          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
8679          GOTO 90
8680   60     CONTINUE
8681
8682!         User supplied diagonals information is available.
8683!         WM(3:LENP+2) = ZERO
8684          WM(1:LENP) = ZERO
8685          NJE = NJE + 1
8686          NSLJ = NST
8687          JCUR = 1
8688          MBA = MIN(MBAND,N)
8689          MEB1 = MEBAND - 1
8690          SRUR = WM1
8691          FAC = DVNORM(N,SAVF,EWT)
8692          R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
8693          IF (ABS(R0)<=ZERO) R0 = ONE
8694!         For each group of columns...
8695          DO NG = 1, BNGRP
8696!            Find the first and last columns in the group.
8697             JJ1 = BIGP(NG)
8698             JJ2 = BIGP(NG+1) - 1
8699!            For each column in this group...
8700             DO JJ = JJ1, JJ2
8701                J = BJGP(JJ)
8702                R = MAX(SRUR*ABS(Y(J)),R0/EWT(J))
8703                Y(J) = Y(J) + R
8704             END DO
8705             CALL F(N,TN,Y,FTEM)
8706!            For each column in this group...
8707             DO JJ = JJ1, JJ2
8708                 J = BJGP(JJ)
8709                 Y(J) = YH(J,1)
8710                 R = MAX(SRUR*ABS(Y(J)),R0/EWT(J))
8711                 FAC = ONE/R
8712                 IF (BUILD_IAJA) THEN
8713!                   Use the IAB, JAB sparse structure arrays to
8714!                   determine the first and last nonzeros in
8715!                   column J.
8716                    K1 = IAB(J)
8717                    K2 = IAB(J+1) - 1
8718                 ELSE
8719!                   Extract the positions of the first and
8720!                   last nonzeros in this column directly.
8721                    CALL BANDED_GET_BJNZ(N,ML,MU,J,IWM(31),I)
8722                    DO K = 1, N
8723                       IF (IWM(30+K) /= 0) THEN
8724                          K1 = K
8725                          GOTO 70
8726                       END IF
8727                    END DO
8728   70               CONTINUE
8729                    DO K = N, 1, -1
8730                       IF (IWM(30+K) /= 0) THEN
8731                          K2 = K
8732                          GOTO 80
8733                       END IF
8734                    END DO
8735   80               CONTINUE
8736                 END IF
8737!                Load the nonzeros for column J in the banded matrix.
8738                 IF (BUILD_IAJA) THEN
8739                    DO K = K1, K2
8740                       I = JAB(K)
8741!                      II = J * MEB1 - ML + 2
8742                       II = J * MEB1 - ML
8743                       WM(II+I) = (FTEM(I)-SAVF(I))*FAC
8744                    END DO
8745                 ELSE
8746                    DO K = K1, K2
8747                       I = IWM(30+K)
8748                       IF (I /= 0) THEN
8749!                         II = J * MEB1 - ML + 2
8750                          II = J * MEB1 - ML
8751                          WM(II+I) = (FTEM(I)-SAVF(I))*FAC
8752                       END IF
8753                    END DO
8754                 END IF
8755             END DO
8756          END DO
8757          NFE = NFE + BNGRP
8758          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
8759   90     CONTINUE
8760!         IF (JSV==1) CALL DACOPY(MBAND,N,WM(ML3),MEBAND,WM(LOCJS),MBAND)
8761          IF (JSV==1) CALL DACOPY(MBAND,N,WM(ML1),MEBAND,WM(LOCJS),MBAND)
8762        END IF
8763
8764        IF (JOK==1) THEN
8765          JCUR = 0
8766!         CALL DACOPY(MBAND,N,WM(LOCJS),MBAND,WM(ML3),MEBAND)
8767          CALL DACOPY(MBAND,N,WM(LOCJS),MBAND,WM(ML1),MEBAND)
8768        END IF
8769
8770!       Multiply Jacobian by scalar, add identity, and do LU
8771!       decomposition.
8772        CON = -HRL1
8773!       CALL DSCAL_F90(LENP,CON,WM(3),1)
8774        CALL DSCAL_F90(LENP,CON,WM(1),1)
8775!       II = MBAND + 2
8776        II = MBAND
8777        DO I = 1, N
8778          WM(II) = WM(II) + ONE
8779          II = II + MEBAND
8780        END DO
8781        NLU = NLU + 1
8782! ______________________________________________________________________
8783
8784!       CALL DGBFA_F90(WM(3),MEBAND,N,ML,MU,IWM(31),IER)
8785        CALL DGBFA_F90(WM(1),MEBAND,N,ML,MU,IWM(31),IER)
8786        IF (IER/=0) IERPJ = 1
8787! *****LAPACK build change point. Replace above with these statements.
8788!       IF (.NOT.USE_LAPACK) THEN
8789!!        CALL DGBFA_f90(WM(3),MEBAND,N,ML,MU,IWM(31),IER)
8790!         CALL DGBFA_f90(WM(1),MEBAND,N,ML,MU,IWM(31),IER)
8791!         IF (IER /= 0) IERPJ = 1
8792!       ELSE
8793!!        CALL DGBTRF(N,N,ML,MU,WM(3),MEBAND,IWM(31),IER)
8794!         CALL DGBTRF(N,N,ML,MU,WM(1),MEBAND,IWM(31),IER)
8795!         IF (IER /= 0) IERPJ = 1
8796!       END IF
8797! ______________________________________________________________________
8798       RETURN
8799!      End of code block for MITER = 4 or 5.
8800
8801      END SUBROUTINE DVJAC
8802!_______________________________________________________________________
8803
8804      SUBROUTINE DACOPY(NROW,NCOL,A,NROWA,B,NROWB)
8805! ..
8806! Copy one array to another.
8807! ..
8808     IMPLICIT NONE
8809! ..
8810! .. Scalar Arguments ..
8811        INTEGER, INTENT (IN) :: NCOL, NROW, NROWA, NROWB
8812! ..
8813! .. Array Arguments ..
8814        KPP_REAL, INTENT (IN) :: A(NROWA,NCOL)
8815        KPP_REAL, INTENT (INOUT) :: B(NROWB,NCOL)
8816! ..
8817! .. Local Scalars ..
8818        INTEGER :: IC
8819! ..
8820! .. FIRST EXECUTABLE STATEMENT DACOPY
8821! ..
8822        DO IC = 1, NCOL
8823          CALL DCOPY_F90(NROW,A(1,IC),1,B(1,IC),1)
8824        END DO
8825        RETURN
8826
8827      END SUBROUTINE DACOPY
8828!_______________________________________________________________________
8829
8830      SUBROUTINE DVSOL(WM,IWM,X,IERSL)
8831! ..
8832! Manage the solution of the linear system arising from a chord
8833! iteration for dense and banded solutions.
8834! ..
8835! This routine manages the solution of the linear system arising from
8836! a chord iteration. It is called if MITER /= 0.
8837! If MITER is 1 or 2, it calls DGESL_F90 to accomplish this.
8838! If MITER = 3 it updates the coefficient H*RL1 in the diagonal
8839! matrix, and then computes the solution.
8840! If MITER is 4 or 5, it calls DGBSL_F90.
8841! Communication with DVSOL uses the following variables:
8842! WM    = Real work space containing the inverse diagonal matrix if
8843!         MITER = 3 and the LU decomposition of the matrix otherwise.
8844!         Storage of matrix elements starts at WM(1).
8845!         WM also contains the following matrix-related data:
8846!         WM1 = SQRT(UROUND) (not used here),
8847!         WM2 = HRL1, the previous value of H*RL1, used if MITER = 3.
8848! IWM   = Integer work space containing pivot information, starting at
8849!         IWM(31), if MITER is 1, 2, 4, or 5. IWM also contains band
8850!         parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5.
8851! X     = The right-hand side vector on input, and the solution vector
8852!         on output, of length N.
8853! IERSL = Output flag. IERSL = 0 if no trouble occurred.
8854!         IERSL = 1 if a singular matrix arose with MITER = 3.
8855! ..
8856     IMPLICIT NONE
8857! ..
8858! .. Scalar Arguments ..
8859        INTEGER, INTENT (INOUT) :: IERSL
8860! ..
8861! .. Array Arguments ..
8862        KPP_REAL, INTENT (INOUT) :: WM(*), X(*)
8863        INTEGER, INTENT (INOUT) :: IWM(*)
8864! ..
8865! .. Local Scalars ..
8866        KPP_REAL :: DI, HRL1, PHRL1, R
8867        INTEGER :: I, MEBAND, ML, MU
8868! ..
8869! .. Intrinsic Functions ..
8870        INTRINSIC ABS
8871! ..
8872! ______________________________________________________________________
8873
8874! *****LAPACK build change point. Insert this statement.
8875!       INTEGER INFO
8876!       CHARACTER*1 TRANS
8877! ______________________________________________________________________
8878
8879! .. FIRST EXECUTABLE STATEMENT DVSOL
8880! ..
8881        IERSL = 0
8882        GOTO (10,10,20,50,50) MITER
8883
888410      CONTINUE
8885! ______________________________________________________________________
8886
8887!       CALL DGESL_F90(WM(3),N,N,IWM(31),X,0)
8888        CALL DGESL_F90(WM(1),N,N,IWM(31),X,0)
8889! *****LAPACK build change point. Replace above with these statements.
8890!       IF (.NOT.USE_LAPACK) THEN
8891!!         CALL DGESL_f90(WM(3),N,N,IWM(31),X,0)
8892!          CALL DGESL_f90(WM(1),N,N,IWM(31),X,0)
8893!       ELSE
8894!          TRANS = 'N'
8895!!         CALL DGETRS(TRANS,N,1,WM(3),N,IWM(31),X,N,INFO)
8896!          CALL DGETRS(TRANS,N,1,WM(1),N,IWM(31),X,N,INFO)
8897!          IF (INFO /= 0) THEN
8898!             WRITE(6,*) 'Stopping in DVSOL with INFO = ', INFO
8899!             STOP
8900!          END IF
8901!       END IF
8902! ______________________________________________________________________
8903
8904        RETURN
8905
890620      PHRL1 = WM2
8907        HRL1 = H*RL1
8908        WM2 = HRL1
8909        IF (ABS(HRL1-PHRL1)<=ZERO) GOTO 30
8910        R = HRL1/PHRL1
8911        DO I = 1, N
8912!         DI = ONE - R*(ONE-ONE/WM(I+2))
8913          DI = ONE - R*(ONE-ONE/WM(I))
8914          IF (ABS(DI)<=ZERO) GOTO 40
8915!         WM(I+2) = ONE/DI
8916          WM(I) = ONE/DI
8917        END DO
8918
891930      DO I = 1, N
8920!         X(I) = WM(I+2)*X(I)
8921          X(I) = WM(I)*X(I)
8922        END DO
8923        RETURN
892440      IERSL = 1
8925        RETURN
8926
892750      ML = IWM(1)
8928        MU = IWM(2)
8929        MEBAND = 2*ML + MU + 1
8930! ______________________________________________________________________
8931
8932!       CALL DGBSL_F90(WM(3),MEBAND,N,ML,MU,IWM(31),X,0)
8933        CALL DGBSL_F90(WM(1),MEBAND,N,ML,MU,IWM(31),X,0)
8934! *****LAPACK build change point. Replace above with these statements.
8935!       IF (.NOT.USE_LAPACK) THEN
8936!!        CALL DGBSL_F90(WM(3),MEBAND,N,ML,MU,IWM(31),X,0)
8937!         CALL DGBSL_F90(WM(1),MEBAND,N,ML,MU,IWM(31),X,0)
8938!       ELSE
8939!         TRANS = 'N'
8940!!        CALL DGBTRS(TRANS,N,ML,MU,1,WM(3),MEBAND,IWM(31),X,N,INFO)
8941!         CALL DGBTRS(TRANS,N,ML,MU,1,WM(1),MEBAND,IWM(31),X,N,INFO)
8942!         IF (INFO /= 0) THEN
8943!           WRITE(6,*) 'Stopping in DVSOL with INFO = ', INFO
8944!           STOP
8945!         END IF
8946!       END IF
8947! ______________________________________________________________________
8948
8949      RETURN
8950
8951      END SUBROUTINE DVSOL
8952!_______________________________________________________________________
8953
8954      SUBROUTINE DVSRCO(RSAV,ISAV,JOB)
8955! ..
8956! Save or restore (depending on JOB) the contents of the PRIVATE
8957! variable blocks, which are used internally by DVODE (not called
8958! by DVODE_F90).
8959! ..
8960! RSAV = real array of length 49 or more.
8961! ISAV = integer array of length 41 or more.
8962! JOB  = flag indicating to save or restore the PRIVATE variable
8963!        blocks:
8964!        JOB  = 1 if PRIVATE variables is to be saved
8965!                 (written to RSAV/ISAV).
8966!        JOB  = 2 if PRIVATE variables is to be restored
8967!                 (read from RSAV/ISAV).
8968!        A call with JOB = 2 presumes a prior call with JOB = 1.
8969! ..
8970     IMPLICIT NONE
8971! ..
8972! .. Scalar Arguments ..
8973        INTEGER, INTENT (IN) :: JOB
8974! ..
8975! .. Array Arguments ..
8976        KPP_REAL, INTENT (INOUT) :: RSAV(*)
8977        INTEGER, INTENT (INOUT) :: ISAV(*)
8978! ..
8979! .. FIRST EXECUTABLE STATEMENT DVSRCO
8980! ..
8981        IF (JOB/=2) THEN
8982!         Save the contents of the PRIVATE blocks.
8983          RSAV(1) = ACNRM
8984          RSAV(2) = CCMXJ
8985          RSAV(3) = CONP
8986          RSAV(4) = CRATE
8987          RSAV(5) = DRC
8988          RSAV(6:18) = EL(1:13)
8989          RSAV(19) = ETA
8990          RSAV(20) = ETAMAX
8991          RSAV(21) = H
8992          RSAV(22) = HMIN
8993          RSAV(23) = HMXI
8994          RSAV(24) = HNEW
8995          RSAV(25) = HSCAL
8996          RSAV(26) = PRL1
8997          RSAV(27) = RC
8998          RSAV(28) = RL1
8999          RSAV(29:41) = TAU(1:13)
9000          RSAV(42:46) = TQ(1:5)
9001          RSAV(47) = TN
9002          RSAV(48) = UROUND
9003          RSAV(LENRV1+1) = HU
9004          ISAV(1) = ICF
9005          ISAV(2) = INIT
9006          ISAV(3) = IPUP
9007          ISAV(4) = JCUR
9008          ISAV(5) = JSTART
9009          ISAV(6) = JSV
9010          ISAV(7) = KFLAG
9011          ISAV(8) = KUTH
9012          ISAV(9) = L
9013          ISAV(10) = LMAX
9014          ISAV(11) = LYH
9015          ISAV(12) = 0
9016          ISAV(13) = 0
9017          ISAV(14) = 0
9018          ISAV(15) = LWM
9019          ISAV(16) = LIWM
9020          ISAV(17) = LOCJS
9021          ISAV(18) = MAXORD
9022          ISAV(19) = METH
9023          ISAV(20) = MITER
9024          ISAV(21) = MSBJ
9025          ISAV(22) = MXHNIL
9026          ISAV(23) = MXSTEP
9027          ISAV(24) = N
9028          ISAV(25) = NEWH
9029          ISAV(26) = NEWQ
9030          ISAV(27) = NHNIL
9031          ISAV(28) = NQ
9032          ISAV(29) = NQNYH
9033          ISAV(30) = NQWAIT
9034          ISAV(31) = NSLJ
9035          ISAV(32) = NSLP
9036          ISAV(33) = NYH
9037          ISAV(LENIV1+1) = NCFN
9038          ISAV(LENIV1+2) = NETF
9039          ISAV(LENIV1+3) = NFE
9040          ISAV(LENIV1+4) = NJE
9041          ISAV(LENIV1+5) = NLU
9042          ISAV(LENIV1+6) = NNI
9043          ISAV(LENIV1+7) = NQU
9044          ISAV(LENIV1+8) = NST
9045          RETURN
9046        ELSE
9047!         Replace the contents of the PRIVATE blocks.
9048          ACNRM = RSAV(1)
9049          CCMXJ = RSAV(2)
9050          CONP = RSAV(3)
9051          CRATE = RSAV(4)
9052          DRC = RSAV(5)
9053          EL(1:13) = RSAV(6:18)
9054          ETA = RSAV(19)
9055          ETAMAX = RSAV(20)
9056          H = RSAV(21)
9057          HMIN = RSAV(22)
9058          HMXI = RSAV(23)
9059          HNEW = RSAV(24)
9060          HSCAL = RSAV(25)
9061          PRL1 = RSAV(26)
9062          RC = RSAV(27)
9063          RL1 = RSAV(28)
9064          TAU(1:13) = RSAV(29:41)
9065          TQ(1:5) = RSAV(42:46)
9066          TN = RSAV(47)
9067          UROUND = RSAV(48)
9068          HU = RSAV(LENRV1+1)
9069          ICF = ISAV(1)
9070          INIT = ISAV(2)
9071          IPUP = ISAV(3)
9072          JCUR = ISAV(4)
9073          JSTART = ISAV(5)
9074          JSV = ISAV(6)
9075          KFLAG = ISAV(7)
9076          KUTH = ISAV(8)
9077          L = ISAV(9)
9078          LMAX = ISAV(10)
9079          LYH = ISAV(11)
9080          LWM = ISAV(15)
9081          LIWM = ISAV(16)
9082          LOCJS = ISAV(17)
9083          MAXORD = ISAV(18)
9084          METH = ISAV(19)
9085          MITER = ISAV(20)
9086          MSBJ = ISAV(21)
9087          MXHNIL = ISAV(22)
9088          MXSTEP = ISAV(23)
9089          N = ISAV(24)
9090          NEWH = ISAV(25)
9091          NEWQ = ISAV(26)
9092          NHNIL = ISAV(27)
9093          NQ = ISAV(28)
9094          NQNYH = ISAV(29)
9095          NQWAIT = ISAV(30)
9096          NSLJ = ISAV(31)
9097          NSLP = ISAV(32)
9098          NYH = ISAV(33)
9099          NCFN = ISAV(LENIV1+1)
9100          NETF = ISAV(LENIV1+2)
9101          NFE = ISAV(LENIV1+3)
9102          NJE = ISAV(LENIV1+4)
9103          NLU = ISAV(LENIV1+5)
9104          NNI = ISAV(LENIV1+6)
9105          NQU = ISAV(LENIV1+7)
9106          NST = ISAV(LENIV1+8)
9107          RETURN
9108        END IF
9109
9110      END SUBROUTINE DVSRCO
9111!_______________________________________________________________________
9112
9113      SUBROUTINE DEWSET(N,ITOL,RTOL,ATOL,YCUR,EWT)
9114! ..
9115! Set the error weight vector.
9116! ..
9117! This subroutine sets the error weight vector EWT according to
9118! EWT(i) = RTOL(i)*ABS(YCUR(i)) + ATOL(i), i = 1,...,N,
9119! with the subscript on RTOL and/or ATOL possibly replaced by 1
9120! above, depending on the value of ITOL.
9121! ..
9122     IMPLICIT NONE
9123! ..
9124! .. Scalar Arguments ..
9125        INTEGER, INTENT (IN) :: ITOL, N
9126! ..
9127! .. Array Arguments ..
9128        KPP_REAL, INTENT (IN) :: ATOL(*), RTOL(*), YCUR(N)
9129        KPP_REAL, INTENT (OUT) :: EWT(N)
9130! ..
9131! .. Intrinsic Functions ..
9132        INTRINSIC ABS
9133! ..
9134! .. FIRST EXECUTABLE STATEMENT DEWSET
9135! ..
9136        GOTO (10,20,30,40) ITOL
913710      CONTINUE
9138        EWT(1:N) = RTOL(1)*ABS(YCUR(1:N)) + ATOL(1)
9139        RETURN
914020      CONTINUE
9141        EWT(1:N) = RTOL(1)*ABS(YCUR(1:N)) + ATOL(1:N)
9142        RETURN
914330      CONTINUE
9144        EWT(1:N) = RTOL(1:N)*ABS(YCUR(1:N)) + ATOL(1)
9145        RETURN
914640      CONTINUE
9147        EWT(1:N) = RTOL(1:N)*ABS(YCUR(1:N)) + ATOL(1:N)
9148        RETURN
9149
9150      END SUBROUTINE DEWSET
9151!_______________________________________________________________________
9152
9153      FUNCTION DVNORM(N,V,W)
9154! ..
9155! Calculate weighted root-mean-square (rms) vector norm.
9156! ..
9157! This routine computes the weighted root-mean-square norm
9158! of the vector of length N contained in the array V, with
9159! weights contained in the array W of length N.
9160! DVNORM = SQRT((1/N) * SUM(V(i)*W(i))**2)
9161! ..
9162     IMPLICIT NONE
9163! ..
9164! .. Function Return Value ..
9165        KPP_REAL :: DVNORM
9166! ..
9167! .. Scalar Arguments ..
9168        INTEGER, INTENT (IN) :: N
9169! ..
9170! .. Array Arguments ..
9171        KPP_REAL, INTENT (IN) :: V(N), W(N)
9172! ..
9173! .. Local Scalars ..
9174        KPP_REAL :: SUM
9175        INTEGER :: I
9176! ..
9177! .. Intrinsic Functions ..
9178        INTRINSIC SQRT
9179! ..
9180! .. FIRST EXECUTABLE STATEMENT DVNORM
9181! ..
9182        SUM = ZERO
9183        DO I = 1, N
9184          SUM = SUM + (V(I)*W(I))**2
9185        END DO
9186        DVNORM = SQRT(SUM/N)
9187        RETURN
9188
9189      END FUNCTION DVNORM
9190!_______________________________________________________________________
9191
9192! The modified SLATEC error handling routines begin here.
9193      SUBROUTINE XERRDV(MSG,NERR,LEVEL,NI,I1,I2,NR,R1,R2)
9194! ..
9195! Write error messages with values.
9196! ..
9197! This is an adaptation of subroutine XERRWD (NMES eliminated).
9198! Subroutines XERRDV, XSETF, XSETUN, and Functions IXSAV
9199! as given here, constitute a simplified version of the SLATEC
9200! error handling package.
9201!
9202! All arguments are input arguments.
9203! MSG    = The message (character array).
9204! NERR   = The error number (not used).
9205! LEVEL  = The error level
9206!          0 or 1 means recoverable (control returns to caller).
9207!          2 means fatal (run is aborted--see note below).
9208! NI     = Number of integers (0, 1, or 2) to be printed with message.
9209! I1,I2  = Integers to be printed, depending on NI.
9210! NR     = Number of reals (0, 1, or 2) to be printed with message.
9211! R1,R2  = Reals to be printed, depending on NR.
9212! Note: This routine is machine-dependent and specialized for use
9213! in limited context, in the following ways:
9214!  1. The argument MSG is assumed to be of type CHARACTER, and
9215!     the message is printed with a format of (1X,A).
9216!  2. The message is assumed to take only one line.
9217!     Multi-line messages are generated by repeated calls.
9218!  3. If LEVEL = 2, control passes to the statement: STOP
9219!     to abort the run. This statement may be machine-dependent.
9220!  4. R1 and R2 are assumed to be in real(wp) and are printed
9221!     in D21.13 format.
9222! Internal Notes:
9223! For a different default logical unit number, IXSAV(or a subsidiary
9224! function that it calls) will need to be modified.
9225! For a different run-abort command, change the statement following
9226! statement 100 at the end.
9227! ..
9228     IMPLICIT NONE
9229! ..
9230! .. Scalar Arguments ..
9231        KPP_REAL :: R1, R2
9232        INTEGER :: I1, I2, LEVEL, NERR, NI, NR
9233        CHARACTER (*) :: MSG
9234        LOGICAL PRINT_NERR
9235! ..
9236! .. Local Scalars ..
9237        INTEGER :: LUNIT, MESFLG
9238! ..
9239! .. FIRST EXECUTABLE STATEMENT XERRDV
9240! ..
9241!       Get logical unit number and message print flag.
9242        LUNIT = IXSAV(1,0,.FALSE.)
9243        MESFLG = IXSAV(2,0,.FALSE.)
9244        IF (MESFLG==0) GOTO 10
9245
9246        PRINT_NERR = .FALSE.
9247        IF (PRINT_NERR) PRINT *, MSG, 'Message number = ', NERR
9248
9249!       Write the message.
9250        WRITE (LUNIT,90000) MSG
925190000   FORMAT (1X,A)
9252        IF (NI==1) WRITE (LUNIT,90001) I1
925390001   FORMAT ('In the above message, I1 = ',I10)
9254        IF (NI==2) WRITE (LUNIT,90002) I1, I2
925590002   FORMAT ('In the above message, I1 = ',I10,3X,'I2 = ',I10)
9256        IF (NR==1) WRITE (LUNIT,90003) R1
925790003   FORMAT ('In the above message, R1 = ',D21.13)
9258        IF (NR==2) WRITE (LUNIT,90004) R1, R2
925990004   FORMAT ('In the above message, R1 = ',D21.13,3X,'R2 = ',D21.13)
9260
9261!       Abort the run if LEVEL = 2.
926210      IF (LEVEL/=2) RETURN
9263        WRITE (LUNIT,90005)
926490005   FORMAT ('LEVEL = 2 in XERRDV. Stopping.')
9265        STOP
9266
9267      END SUBROUTINE XERRDV
9268!_______________________________________________________________________
9269
9270      SUBROUTINE XSETF(MFLAG)
9271! ..
9272!     Reset the error print control flag.
9273! ..
9274     IMPLICIT NONE
9275! ..
9276! .. Scalar Arguments ..
9277        INTEGER, INTENT (IN) :: MFLAG
9278! ..
9279! .. Local Scalars ..
9280        INTEGER :: JUNK
9281! ..
9282! .. FIRST EXECUTABLE STATEMENT XSETF
9283! ..
9284        IF (MFLAG==0 .OR. MFLAG==1) JUNK = IXSAV(2,MFLAG,.TRUE.)
9285!       Get rid of a compiler warning message:
9286        IF (JUNK/=JUNK) STOP
9287        RETURN
9288
9289      END SUBROUTINE XSETF
9290!_______________________________________________________________________
9291
9292      SUBROUTINE XSETUN(LUN)
9293! ..
9294!     Reset the logical unit number for error messages.
9295! ..
9296!     XSETUN sets the logical unit number for error messages to LUN.
9297! ..
9298     IMPLICIT NONE
9299! ..
9300! .. Scalar Arguments ..
9301        INTEGER :: LUN
9302! ..
9303! .. Local Scalars ..
9304        INTEGER :: JUNK
9305! ..
9306! .. FIRST EXECUTABLE STATEMENT XSETUN
9307! ..
9308        IF (LUN>0) JUNK = IXSAV(1,LUN,.TRUE.)
9309!       Get rid of a compiler warning message:
9310        IF (JUNK/=JUNK) STOP
9311        RETURN
9312
9313      END SUBROUTINE XSETUN
9314!_______________________________________________________________________
9315
9316      FUNCTION IXSAV(IPAR,IVALUE,ISET)
9317! ..
9318! Save and recall error message control parameters.
9319! ..
9320! IXSAV saves and recalls one of two error message parameters:
9321!  LUNIT, the logical unit number to which messages are printed,
9322!  and MESFLG, the message print flag.
9323! This is a modification of the SLATEC library routine J4SAVE.
9324! Saved local variables:
9325!  LUNIT  = Logical unit number for messages. The default is
9326!           obtained by a call to IUMACH(may be machine-dependent).
9327!  MESFLG = Print control flag:
9328!           1 means print all messages (the default).
9329!           0 means no printing.
9330! On input:
9331!  IPAR   = Parameter indicator (1 for LUNIT, 2 for MESFLG).
9332!  IVALUE = The value to be set for the parameter, if ISET = .TRUE.
9333!  ISET   = Logical flag to indicate whether to read or write.
9334!           If ISET = .TRUE., the parameter will be given
9335!           the value IVALUE. If ISET = .FALSE., the parameter
9336!           will be unchanged, and IVALUE is a dummy argument.
9337! On return:
9338!   IXSAV = The (old) value of the parameter.
9339! ..
9340     IMPLICIT NONE
9341! ..
9342! .. Function Return Value ..
9343        INTEGER :: IXSAV
9344! ..
9345! .. Scalar Arguments ..
9346        INTEGER, INTENT (IN) :: IPAR, IVALUE
9347        LOGICAL, INTENT (IN) :: ISET
9348! ..
9349! .. Local Scalars ..
9350        INTEGER, SAVE :: LUNIT, MESFLG
9351! ..
9352! .. Data Statements ..
9353        DATA LUNIT/ -1/, MESFLG/1/
9354! ..
9355! .. FIRST EXECUTABLE STATEMENT IXSAV
9356! ..
9357        IF (IPAR==1) THEN
9358          IF (LUNIT==-1) LUNIT = IUMACH()
9359!  i       Get rid of a compiler warning message:
9360          IF (LUNIT/=LUNIT) STOP
9361          IXSAV = LUNIT
9362          IF (ISET) LUNIT = IVALUE
9363        END IF
9364
9365        IF (IPAR==2) THEN
9366          IXSAV = MESFLG
9367          IF (ISET) MESFLG = IVALUE
9368        END IF
9369        RETURN
9370
9371      END FUNCTION IXSAV
9372!_______________________________________________________________________
9373
9374      FUNCTION IUMACH()
9375! ..
9376!     Provide the standard output unit number.
9377! ..
9378!     INTEGER LOUT, IUMACH
9379!     LOUT = IUMACH()
9380!     Function Return Values:
9381!     LOUT: the standard logical unit for Fortran output.
9382!     Internal Notes:
9383!     The built-in value of 6 is standard on a wide range
9384!     of Fortran systems. This may be machine-dependent.
9385! ..
9386! .. Function Return Value ..
9387        INTEGER :: IUMACH
9388! ..
9389! .. FIRST EXECUTABLE STATEMENT IUMACH
9390! ..
9391        IUMACH = 6
9392        RETURN
9393
9394      END FUNCTION IUMACH
9395! The modified error handling routines end here.
9396!_______________________________________________________________________
9397
9398      SUBROUTINE CHECK_STAT(IER,CALLED_FROM_WHERE)
9399! ..
9400! Print an error message if a storage allocation error
9401! occurred.
9402! ..
9403     IMPLICIT NONE
9404! ..
9405! .. Scalar Arguments ..
9406        INTEGER, INTENT (IN) :: CALLED_FROM_WHERE, IER
9407! ..
9408! .. Local Scalars ..
9409        INTEGER :: I1
9410        CHARACTER (80) :: MSG
9411! ..
9412! .. FIRST EXECUTABLE STATEMENT CHECK_STAT
9413! ..
9414        IF (IER/=0) THEN
9415          I1 = CALLED_FROM_WHERE
9416          MSG = 'A storage allocation error occurred.'
9417          CALL XERRDV(MSG,1410,1,0,0,0,0,ZERO,ZERO)
9418          MSG = 'The error occurred at location I1.'
9419          CALL XERRDV(MSG,1410,2,1,I1,0,0,ZERO,ZERO)
9420        END IF
9421        RETURN
9422
9423      END SUBROUTINE CHECK_STAT
9424!_______________________________________________________________________
9425
9426      SUBROUTINE DVPREPS(NEQ,Y,YH,LDYH,SAVF,EWT,F,JAC)
9427! ..
9428! Determine the sparsity structure and allocate the necessary arrays
9429! for MA28 based sparse solutions.
9430! ..
9431     IMPLICIT NONE
9432! ..
9433! .. Scalar Arguments ..
9434        INTEGER, INTENT (IN) :: LDYH, NEQ
9435! ..
9436! .. Array Arguments ..
9437        KPP_REAL, INTENT (INOUT) :: EWT(*), Y(*)
9438        KPP_REAL :: SAVF(*)
9439        KPP_REAL, INTENT (IN) :: YH(LDYH,*)
9440! ..
9441! .. Subroutine Arguments ..
9442        EXTERNAL F, JAC
9443! ..
9444! .. Local Scalars ..
9445        KPP_REAL :: DQ, DYJ, ERWT, FAC, YJ
9446        INTEGER :: I, IER, J, JFOUND, K, KMAX, KMIN, KNEW, NP1, NZ
9447        CHARACTER (80) :: MSG
9448! ..
9449! .. Intrinsic Functions ..
9450        INTRINSIC ABS, ALLOCATED, MAX, SIGN
9451! ..
9452! .. FIRST EXECUTABLE STATEMENT DVPREPS
9453! ..
9454        NZ_SWAG = MAX(MAX(1000,NZ_SWAG),10*N)
9455        NP1 = N + 1
9456        NZ_ALL = NZ_SWAG
9457!       ADDTONNZ = MAX(1000,NZ_SWAG)
9458        ADDTONNZ = NZ_SWAG
945910      CONTINUE
9460        IF (ALLOCATED(IAN)) THEN
9461          DEALLOCATE (IAN,JAN,IGP,JGP,FTEMP1,IKEEP28,IW28,ICN,PMAT, &
9462            JVECT,STAT=IER)
9463          CALL CHECK_STAT(IER,490)
9464          IF (ALLOCATED(JMAT)) THEN
9465            DEALLOCATE (JMAT,STAT=IER)
9466            CALL CHECK_STAT(IER,500)
9467          END IF
9468        END IF
9469        NZ_ALL = NZ_ALL + ADDTONNZ
9470        LICN_ALL = ELBOW_ROOM * NZ_ALL
9471        LIRN_ALL = ELBOW_ROOM * NZ_ALL
9472        IF (LICN_ALL>MAX_ARRAY_SIZE .OR. LIRN_ALL>MAX_ARRAY_SIZE) THEN
9473          MSG = 'Maximum array size exceeded. Stopping.'
9474          CALL XERRDV(MSG,1420,2,0,0,0,0,ZERO,ZERO)
9475        END IF
9476!       Note: ICN may need to be reallocated in DVJACS28.
9477        ALLOCATE (IAN(NP1),JAN(LIRN_ALL),IGP(NP1),JGP(N),FTEMP1(N), &
9478          IKEEP28(N,5),IW28(N,8),ICN(LICN_ALL),PMAT(LICN_ALL),      &
9479          JVECT(LIRN_ALL),STAT=IER)
9480        CALL CHECK_STAT(IER,510)
9481        IF (JSV==1) THEN
9482          ALLOCATE (JMAT(NZ_ALL),STAT=IER)
9483          CALL CHECK_STAT(IER,520)
9484          JMAT(1:NZ_ALL) = ZERO
9485        END IF
9486
9487        IF (MOSS==0) GOTO 30
9488        IF (ISTATC==3) GOTO 20
9489
9490!       ISTATE = 1 and MOSS /= 0.
9491
9492!       Perturb Y for structure determination:
9493        DO I = 1, N
9494          ERWT = ONE/EWT(I)
9495          FAC = ONE + ONE/(I+ONE)
9496          Y(I) = Y(I) + FAC*SIGN(ERWT,Y(I))
9497        END DO
9498        GOTO (60,70) MOSS
9499
950020      CONTINUE
9501!       ISTATE = 3 and MOSS /= 0.
9502
9503!       Load Y from YH(*,1):
9504        Y(1:N) = YH(1:N,1)
9505        GOTO (60,70) MOSS
9506
9507!       MOSS = 0
9508
9509!       Process user's IA,JA. Add diagonal entries if necessary:
951030      CONTINUE
9511        IF (IAJA_CALLED) THEN
9512        ELSE
9513          MSG = 'You have indicated that you wish to supply the'
9514          CALL XERRDV(MSG,1430,1,0,0,0,0,ZERO,ZERO)
9515          MSG = 'sparsity arrays IA and JA directly but you did'
9516          CALL XERRDV(MSG,1430,1,0,0,0,0,ZERO,ZERO)
9517          MSG = 'not call SET_IAJA after calling SET_OPTS.'
9518          CALL XERRDV(MSG,1430,2,0,0,0,0,ZERO,ZERO)
9519        END IF
9520        KNEW = 1
9521        KMIN = IA(1)
9522        IAN(1) = 1
9523        DO J = 1, N
9524          JFOUND = 0
9525          KMAX = IA(J+1) - 1
9526          IF (KMIN>KMAX) GOTO 40
9527          DO K = KMIN, KMAX
9528            I = JA(K)
9529            IF (I==J) JFOUND = 1
9530            IF (KNEW>NZ_ALL) THEN
9531               IF (LP /= 0) THEN
9532                  MSG = 'NZ_ALL (=I1) is not large enough.'
9533                  CALL XERRDV(MSG,1440,1,0,0,0,0,ZERO,ZERO)
9534                  MSG = 'Allocating more space for another try.'
9535                  CALL XERRDV(MSG,1440,1,1,NZ_ALL,0,0,ZERO,ZERO)
9536               END IF
9537               GOTO 10
9538            END IF
9539            JAN(KNEW) = I
9540            KNEW = KNEW + 1
9541          END DO
9542          IF (JFOUND==1) GOTO 50
954340        IF (KNEW>NZ_ALL) THEN
9544             IF (LP /= 0) THEN
9545                MSG = 'NZ_ALL (=I1) is not large enough.'
9546                CALL XERRDV(MSG,1450,1,0,0,0,0,ZERO,ZERO)
9547                MSG = 'Allocating more space for another try.'
9548                CALL XERRDV(MSG,1450,1,1,NZ_ALL,0,0,ZERO,ZERO)
9549             END IF
9550             GOTO 10
9551          END IF
9552          JAN(KNEW) = J
9553          KNEW = KNEW + 1
955450        IAN(J+1) = KNEW
9555          KMIN = KMAX + 1
9556        END DO
9557        GOTO 90
9558
955960      CONTINUE
9560
9561!       MOSS = 1.
9562
9563!       Compute structure from user-supplied Jacobian routine JAC.
9564        NZ = 0
9565        CALL JAC(NEQ,TN,Y,IAN,JAN,NZ,PMAT)
9566        IF (NZ<=0) THEN
9567          MSG = 'Illegal value of NZ from JAC in DVPREPS.'
9568          CALL XERRDV(MSG,1460,2,0,0,0,0,ZERO,ZERO)
9569        END IF
9570        IF (NZ>NZ_ALL) THEN
9571           IF (LP /= 0) THEN
9572              MSG = 'NZ_ALL (=I1) is not large enough.'
9573              CALL XERRDV(MSG,1470,1,0,0,0,0,ZERO,ZERO)
9574              MSG = 'Allocating more space for another try.'
9575              CALL XERRDV(MSG,1470,1,1,NZ_ALL,0,0,ZERO,ZERO)
9576           END IF
9577           GOTO 10
9578        END IF
9579        CALL JAC(NEQ,TN,Y,IAN,JAN,NZ,PMAT)
9580        CALL SET_ICN(N,IAN,ICN)
9581        CALL CHECK_DIAG(N,IAN,JAN,ICN)
9582        GOTO 90
9583
9584!       MOSS = 2.
9585
9586!       Compute structure from results of N+1 calls to F.
958770      K = 1
9588        IAN(1) = 1
9589        DO I = 1, N
9590          ERWT = ONE/EWT(I)
9591          FAC = ONE + ONE/(I+ONE)
9592          Y(I) = Y(I) + FAC*SIGN(ERWT,Y(I))
9593        END DO
9594        CALL F(NEQ,TN,Y,SAVF)
9595        NFE = NFE + 1
9596        DO J = 1, N
9597          IF (K>NZ_ALL) THEN
9598             IF (LP /= 0) THEN
9599                MSG = 'NZ_ALL (=I1) is not large enough.'
9600                CALL XERRDV(MSG,1480,1,0,0,0,0,ZERO,ZERO)
9601                MSG = 'Allocating more space for another try.'
9602                CALL XERRDV(MSG,1480,1,1,NZ_ALL,0,0,ZERO,ZERO)
9603
9604             END IF
9605             GOTO 10
9606          END IF
9607          YJ = Y(J)
9608          ERWT = ONE/EWT(J)
9609          DYJ = SIGN(ERWT,YJ)
9610          Y(J) = YJ + DYJ
9611          CALL F(NEQ,TN,Y,FTEMP1)
9612          NFE = NFE + 1
9613          Y(J) = YJ
9614          DO 80 I = 1, N
9615            DQ = (FTEMP1(I)-SAVF(I))/DYJ
9616            IF ((ABS(DQ)<=SETH) .AND. (I/=J)) GOTO 80
9617            JAN(K) = I
9618            K = K + 1
961980        END DO
9620          IAN(J+1) = K
9621        END DO
962290      CONTINUE
9623        IF (MOSS==0 .OR. ISTATC/=1) GOTO 100
9624!       If ISTATE = 1 and MOSS /= 0, restore Y from YH.
9625        Y(1:N) = YH(1:N,1)
9626100     NNZ = IAN(NP1) - 1
9627        LENIGP = 0
9628        MAXG = 0
9629        IF (MITER==7) THEN
9630!         Compute grouping of column indices.
9631          MAXG = NP1
9632          CALL DGROUP(N,IAN,JAN,MAXG,NGP,IGP,JGP,IKEEP28(1,1), &
9633            IKEEP28(1,2),IER)
9634          IF (IER/=0) THEN
9635            MSG = 'An error occurred in DGROUP.'
9636            CALL XERRDV(MSG,1490,2,0,0,0,0,ZERO,ZERO)
9637          END IF
9638          LENIGP = NGP + 1
9639        END IF
9640
9641        IF (USE_JACSP .AND. MITER==7) THEN
9642!         Use Doug Salane's Jacobian routines to determine the column
9643!         grouping; and allocate and initialize the necessary arrays
9644!         for use in DVJACS48.
9645          IF (ALLOCATED(INDROWDS)) THEN
9646             DEALLOCATE (INDROWDS, INDCOLDS, NGRPDS, IPNTRDS, JPNTRDS, IWADS, &
9647               IWKDS, IOPTDS, YSCALEDS, WKDS, FACDS)
9648             CALL CHECK_STAT(IER,530)
9649          END IF
9650!         We could delete IWADS and use IW28 array.
9651          ALLOCATE (INDROWDS(NNZ), INDCOLDS(NNZ), NGRPDS(N+1), IPNTRDS(N+1), &
9652            JPNTRDS(N+1), IWADS(6*N), IWKDS(50+N), IOPTDS(5), YSCALEDS(N),  &
9653            WKDS(3*N), FACDS(N) ,STAT=IER)
9654          CALL CHECK_STAT(IER,540)
9655          INDROWDS(1:NNZ) = JAN(1:NNZ)
9656          CALL SET_ICN(N,IAN,INDCOLDS)
9657          CALL CHECK_DIAG(N,IAN,INDROWDS,INDCOLDS)
9658          LIWADS = 6 * N
9659          CALL DVDSM(N,N,NNZ,INDROWDS,INDCOLDS,NGRPDS,MAXGRPDS,MINGRPDS,      &
9660            INFODS,IPNTRDS,JPNTRDS,IWADS,LIWADS)
9661          IF (INFODS /= 1) THEN
9662             MSG = 'An error occurred in subroutine DSM. INFO = I1.'
9663               CALL XERRDV(MSG,1500,2,1,INFODS,0,0,ZERO,ZERO)
9664          END IF
9665!         For use in DVJACS28:
9666          IOPTDS(4) = 0
9667!         Define the IGP and JGP arrays needed by DVJACS28.
9668          CALL DGROUPDS(N,MAXGRPDS,NGRPDS,IGP,JGP)
9669          NGP = MAXGRPDS
9670          LENIGP = MAXGRPDS + 1
9671        END IF
9672
9673!       Trim the arrays to the final sizes.
9674
9675        IF (NZ_ALL>NNZ) THEN
9676          NZ_ALL = NNZ
9677          MAX_NNZ = MAX(MAX_NNZ,NNZ)
9678          LIRN_ALL = ELBOW_ROOM * NNZ
9679          ICN(1:NNZ) = JAN(1:NNZ)
9680          DEALLOCATE (JAN,STAT=IER)
9681          CALL CHECK_STAT(IER,550)
9682          ALLOCATE (JAN(LIRN_ALL),STAT=IER)
9683          CALL CHECK_STAT(IER,560)
9684          JAN(1:NNZ) = ICN(1:NNZ)
9685          CALL CHECK_STAT(IER,570)
9686          DEALLOCATE (ICN,PMAT,JVECT,STAT=IER)
9687          CALL CHECK_STAT(IER,580)
9688          IF (ALLOCATED(JMAT)) THEN
9689            DEALLOCATE (JMAT,STAT=IER)
9690            CALL CHECK_STAT(IER,590)
9691          END IF
9692          LICN_ALL = ELBOW_ROOM * NNZ
9693          ALLOCATE (ICN(LICN_ALL),PMAT(LICN_ALL),JVECT(LIRN_ALL),STAT=IER)
9694          CALL CHECK_STAT(IER,600)
9695          IF (JSV==1) THEN
9696            ALLOCATE (JMAT(NNZ),STAT=IER)
9697            CALL CHECK_STAT(IER,610)
9698            JMAT(1:NNZ) = ZERO
9699          END IF
9700          IF (MITER==7) THEN
9701            JVECT(1:LENIGP) = IGP(1:LENIGP)
9702            DEALLOCATE (IGP,STAT=IER)
9703            CALL CHECK_STAT(IER,620)
9704            ALLOCATE (IGP(LENIGP),STAT=IER)
9705            CALL CHECK_STAT(IER,630)
9706            IGP(1:LENIGP) = JVECT(1:LENIGP)
9707          END IF
9708        END IF
9709        IF (SCALE_MATRIX) THEN
9710           IF (ALLOCATED(CSCALEX)) THEN
9711              DEALLOCATE (CSCALEX,RSCALEX,WSCALEX,STAT=IER)
9712              CALL CHECK_STAT(IER,640)
9713              ALLOCATE (CSCALEX(N),RSCALEX(N),WSCALEX(N,5),STAT=IER)
9714              CALL CHECK_STAT(IER,650)
9715           ELSE
9716              ALLOCATE (CSCALEX(N),RSCALEX(N),WSCALEX(N,5),STAT=IER)
9717              CALL CHECK_STAT(IER,660)
9718           END IF
9719        END IF
9720        IF (LP /= 0) THEN
9721           MSG = 'The final DVPRPEPS storage allocations are:'
9722           CALL XERRDV(MSG,1510,1,0,0,0,0,ZERO,ZERO)
9723           MSG = '   NZ_ALL (=I1):'
9724           CALL XERRDV(MSG,1510,1,1,NZ_ALL,0,0,ZERO,ZERO)
9725           MSG = '   LIRN_ALL (=I1) and LICN_ALL (=I2):'
9726           CALL XERRDV(MSG,1510,1,2,LIRN_ALL,LICN_ALL,0,ZERO,ZERO)
9727         END IF
9728        RETURN
9729
9730      END SUBROUTINE DVPREPS
9731!_______________________________________________________________________
9732
9733      SUBROUTINE DVRENEW(NEQ,Y,SAVF,EWT,F)
9734! ..
9735! In the event MA28BD encounters a zero pivot in the LU factorization
9736! of the iteration matrix due to an out-of-date MA28AD pivot sequence,
9737! re-calculate the sparsity structure using finite differences.
9738! ..
9739     IMPLICIT NONE
9740! ..
9741! .. Scalar Arguments ..
9742        INTEGER, INTENT (IN) :: NEQ
9743! ..
9744! .. Array Arguments ..
9745        KPP_REAL, INTENT (INOUT) :: EWT(*), SAVF(*), Y(*)
9746! ..
9747! .. Subroutine Arguments ..
9748        EXTERNAL F
9749! ..
9750! .. Local Scalars ..
9751        KPP_REAL :: DQ, DYJ, ERWT, FAC, YJ
9752        INTEGER :: ADDTONZ, I, IER, J, K, KVAL, NP1
9753        CHARACTER (80) :: MSG
9754! ..
9755! .. Intrinsic Functions ..
9756        INTRINSIC ABS, ALLOCATED, MAX, SIGN
9757! ..
9758! .. FIRST EXECUTABLE STATEMENT DVRENEW
9759! ..
9760! .. Caution:
9761!    This routine must not be called before DVPREPS has been called.
9762!
9763!    Note:
9764!    On entry to DVRENEW, the allocated array sizes of arrays that
9765!    may change size are:
9766!      ICN, PMAT  = length LICN_ALL
9767!      JAN, JVECT = length LIRN_ALL
9768!      JMAT       = length NZ_ALL
9769!      IGP        = length LENIGP on first entry; N+1 thereafter
9770
9771!       Check if a numerical Jacobian is being used and stop if
9772!       it is not.
9773        IF (MITER /= 7) THEN
9774          MSG = 'DVRENEW can be used only if MITER = 7.'
9775          CALL XERRDV(MSG,1520,2,0,0,0,0,ZERO,ZERO)
9776        END IF
9777
9778!       Save Y and SAVF.
9779        IF (.NOT.ALLOCATED(YTEMP)) THEN
9780           ALLOCATE (YTEMP(N),DTEMP(N),STAT=IER)
9781           CALL CHECK_STAT(IER,670)
9782        END IF
9783        YTEMP(1:N) = Y(1:N)
9784        DTEMP(1:N) = SAVF(1:N)
9785
9786!       Define the amount to be added to the array lengths
9787!       if necessary.
9788        NP1 = N + 1
9789        NNZ = IAN(NP1) - 1
9790        ADDTONZ = ELBOW_ROOM * NNZ
9791
9792!       Just change the size of IGP to N+1 if have not already
9793!       done so.
9794        IF (SIZE(IGP) /= NP1) THEN
9795           DEALLOCATE (IAN,STAT=IER)
9796           CALL CHECK_STAT(IER,680)
9797           ALLOCATE (IAN(NP1),STAT=IER)
9798           CALL CHECK_STAT(IER,690)
9799        END IF
9800
9801!       Go to the differencing section to determine the new
9802!       sparsity structure.
9803        GOTO 20
9804
980510      CONTINUE
9806
9807!       Reallocate the arrays if necessary.
9808        IF (KVAL > LIRN_ALL) THEN
9809!          Note: JAN and JVECT may need to be reallocated in DVJACS28.
9810           LIRN_ALL = LIRN_ALL + ADDTONZ
9811           IF (LIRN_ALL>MAX_ARRAY_SIZE) THEN
9812              MSG = 'Maximum array size exceeded. Stopping in DVRENEW.'
9813             CALL XERRDV(MSG,1530,2,0,0,0,0,ZERO,ZERO)
9814           END IF
9815           DEALLOCATE (JAN,JVECT,STAT=IER)
9816           CALL CHECK_STAT(IER,700)
9817           ALLOCATE (JAN(LIRN_ALL),JVECT(LIRN_ALL),STAT=IER)
9818           CALL CHECK_STAT(IER,710)
9819        END IF
9820        IF (KVAL > LICN_ALL) THEN
9821!          Note: ICN and PMAT may need to be reallocated in DVJACS28.
9822           LICN_ALL = LICN_ALL + ADDTONZ
9823           IF (LICN_ALL>MAX_ARRAY_SIZE) THEN
9824              MSG = 'Maximum array size exceeded. Stopping in DVRENEW.'
9825             CALL XERRDV(MSG,1540,2,0,0,0,0,ZERO,ZERO)
9826           END IF
9827           DEALLOCATE (ICN,PMAT,STAT=IER)
9828           CALL CHECK_STAT(IER,720)
9829           ALLOCATE (ICN(LICN_ALL),PMAT(LICN_ALL),STAT=IER)
9830           CALL CHECK_STAT(IER,730)
9831        END IF
9832
9833   20   CONTINUE
9834
9835!       Perturb Y for structure determination:
9836        DO I = 1, N
9837          ERWT = ONE/EWT(I)
9838          FAC = ONE + ONE/(I+ONE)
9839          Y(I) = Y(I) + FAC*SIGN(ERWT,Y(I))
9840        END DO
9841
9842!       Compute structure from results of N+1 calls to F.
9843        K = 1
9844        IAN(1) = 1
9845        DO I = 1, N
9846          ERWT = ONE/EWT(I)
9847          FAC = ONE + ONE/(I+ONE)
9848          Y(I) = Y(I) + FAC*SIGN(ERWT,Y(I))
9849        END DO
9850        CALL F(NEQ,TN,Y,SAVF)
9851        NFE = NFE + 1
9852        DO J = 1, N
9853          KVAL = K
9854          IF (KVAL > LIRN_ALL) THEN
9855             IF (LP /= 0) THEN
9856                MSG = 'LIRN_ALL (=I1) is not large enough.'
9857                CALL XERRDV(MSG,1550,1,0,0,0,0,ZERO,ZERO)
9858                MSG = 'Allocating more space for another try.'
9859                CALL XERRDV(MSG,1550,1,1,LIRN_ALL,0,0,ZERO,ZERO)
9860             END IF
9861             GOTO 10
9862          END IF
9863          IF (KVAL > LICN_ALL) THEN
9864             IF (LP /= 0) THEN
9865                MSG = 'LICN_ALL (=I1) is not large enough.'
9866                CALL XERRDV(MSG,1560,1,0,0,0,0,ZERO,ZERO)
9867                MSG = 'Allocating more space for another try.'
9868                CALL XERRDV(MSG,1560,1,1,LICN_ALL,0,0,ZERO,ZERO)
9869             END IF
9870             GOTO 10
9871          END IF
9872          YJ = Y(J)
9873          ERWT = ONE/EWT(J)
9874          DYJ = SIGN(ERWT,YJ)
9875          Y(J) = YJ + DYJ
9876          CALL F(NEQ,TN,Y,FTEMP1)
9877          NFE = NFE + 1
9878          Y(J) = YJ
9879          DO 80 I = 1, N
9880            DQ = (FTEMP1(I)-SAVF(I))/DYJ
9881            IF ((ABS(DQ)<=SETH) .AND. (I/=J)) GOTO 80
9882            JAN(K) = I
9883            K = K + 1
988480        END DO
9885          IAN(J+1) = K
9886        END DO
9887
9888        NNZ = IAN(NP1) - 1
9889        IF (NNZ > NZ_ALL .AND. JSV == 1) THEN
9890!          Increase the size of JMAT if necessary.
9891           NZ_ALL = NNZ
9892           IF (LP /= 0) THEN
9893              MSG = 'NZ_ALL (=I1) is not large enough.'
9894              CALL XERRDV(MSG,1570,1,0,0,0,0,ZERO,ZERO)
9895              MSG = 'Allocating more space for another try.'
9896              CALL XERRDV(MSG,1570,1,1,NZ_ALL,0,0,ZERO,ZERO)
9897           END IF
9898           IF (NZ_ALL>MAX_ARRAY_SIZE) THEN
9899              MSG = 'Maximum array size exceeded. Stopping in DVRENEW.'
9900              CALL XERRDV(MSG,1580,2,0,0,0,0,ZERO,ZERO)
9901           END IF
9902           DEALLOCATE (JMAT,STAT=IER)
9903           CALL CHECK_STAT(IER,740)
9904           ALLOCATE (JMAT(NZ_ALL),STAT=IER)
9905           CALL CHECK_STAT(IER,750)
9906           JMAT(1:NZ_ALL) = ZERO
9907        END IF
9908
9909!       Compute grouping of column indices.
9910
9911        LENIGP = 0
9912        MAXG = 0
9913        MAXG = NP1
9914        CALL DGROUP(N,IAN,JAN,MAXG,NGP,IGP,JGP,IKEEP28(1,1), &
9915          IKEEP28(1,2),IER)
9916        IF (IER/=0) THEN
9917          MSG = 'An error occurred in DGROUP.'
9918          CALL XERRDV(MSG,1590,2,0,0,0,0,ZERO,ZERO)
9919        END IF
9920        LENIGP = NGP + 1
9921
9922!       Restore Y and SAVF.
9923        Y(1:N) = YTEMP(1:N)
9924        SAVF(1:N) = DTEMP(1:N)
9925        RETURN
9926
9927      END SUBROUTINE DVRENEW
9928!_______________________________________________________________________
9929
9930      SUBROUTINE DGROUP(N,IA,JA,MAXG,NGRP,IGP,JGP,INCL,JDONE,IER)
9931! ..
9932! Construct groupings of the column indices of the Jacobian matrix,
9933! used in the numerical evaluation of the Jacobian by finite
9934! differences for sparse solutions.
9935! ..
9936!     Input:
9937!     N      = the order of the matrix
9938!     IA,JA  = sparse structure descriptors of the matrix by rows
9939!     MAXG   = length of available storage in the IGP array
9940!     INCL and JDONE are working arrays of length N.
9941!     Output:
9942!     NGRP   = number of groups
9943!     JGP    = array of length N containing the column indices by
9944!              groups
9945!     IGP    = pointer array of length NGRP + 1 to the locations
9946!              in JGP of the beginning of each group
9947!     IER    = error indicator. IER = 0 if no error occurred, or
9948!              1 if MAXG was insufficient
9949! ..
9950     IMPLICIT NONE
9951! ..
9952! .. Scalar Arguments ..
9953        INTEGER, INTENT (INOUT) :: IER, NGRP
9954        INTEGER, INTENT (IN) :: MAXG, N
9955! ..
9956! .. Array Arguments ..
9957        INTEGER, INTENT (IN) :: IA(*), JA(*)
9958        INTEGER, INTENT (INOUT) :: IGP(*), INCL(*), JDONE(*), JGP(*)
9959! ..
9960! .. Local Scalars ..
9961        INTEGER :: I, J, K, KMAX, KMIN, NCOL, NG
9962! ..
9963! .. FIRST EXECUTABLE STATEMENT DGROUP
9964! ..
9965        IER = 0
9966        JDONE(1:N) = 0
9967        NCOL = 1
9968        DO NG = 1, MAXG
9969          IGP(NG) = NCOL
9970          INCL(1:N) = 0
9971          DO 20 J = 1, N
9972!           Reject column J if it is already in a group.
9973            IF (JDONE(J)==1) GOTO 20
9974            KMIN = IA(J)
9975            KMAX = IA(J+1) - 1
9976            DO 10 K = KMIN, KMAX
9977!           Reject column J if it overlaps any column already
9978!           in this group.
9979              I = JA(K)
9980              IF (INCL(I)==1) GOTO 20
998110          END DO
9982!           Accept column J into group NG.
9983            JGP(NCOL) = J
9984            NCOL = NCOL + 1
9985            JDONE(J) = 1
9986            DO K = KMIN, KMAX
9987              I = JA(K)
9988              INCL(I) = 1
9989            END DO
999020        END DO
9991!         Stop if this group is empty (grouping is complete).
9992          IF (NCOL==IGP(NG)) GOTO 30
9993        END DO
9994!       Error return if not all columns were chosen (MAXG too small).
9995        IF (NCOL<=N) GOTO 40
9996        NG = MAXG
999730      NGRP = NG - 1
9998        RETURN
999940      IER = 1
10000        RETURN
10001
10002      END SUBROUTINE DGROUP
10003!_______________________________________________________________________
10004
10005      SUBROUTINE BGROUP(N,BJA,BINCL,BDONE,ML,MU)
10006! ..
10007! Construct groupings of the column indices of the Jacobian
10008! matrix, used in the numerical evaluation of the Jacobian
10009! by finite differences for banded solutions when the nonzero
10010! sub and super diagonals are known. BGROUP is similar to
10011! DGROUP but it does not require the sparse structure arrays
10012! and it uses real rather than integer work arrays.
10013! ..
10014!     Input:
10015!
10016!       N       = the order of the matrix (number of odes)
10017!       BINCL   = real working array of length N
10018!       BJA     = real working array of length N
10019!       BDONE   = real working array of length N
10020!       ML      = integer lower bandwidth
10021!       MU      = integer upper bandwidth
10022!
10023!     Output: (PRIVATE information used in DVJAC)
10024!
10025!       BNGRP   = integer number of groups
10026!       BJGP    = integer array of length N containing the
10027!                 column indices by groups
10028!       BIGP    = integer pointer array of length BNGRP + 1
10029!                 to the locations in BJGP of the beginning
10030!                 of each group
10031!
10032!       Note:
10033!          On output:
10034!             For I = 1, ..., BNGRP:
10035!                Start of group I:
10036!                  J = BIGP(I)
10037!                Number of columns in group I:
10038!                  K = BIGP(I+1) - BIGP(I)
10039!                Columns in group I:
10040!                  BJGP(J-1+L), L=1, ..., K
10041!
10042!    Note:
10043!    The three arrays BJA, BINCL, and BDONE are REAL to avoid the
10044!    necessity to allocate three new INTEGER arrays. BGROUP can
10045!    be called only at an integration start or restart because
10046!    DVODE_F90 work arrays are used for these arrays.
10047!
10048!    Note:
10049!    The PRIVATE banded information SUBDS, NSUBDS, SUPDS, NSUPS,
10050!    ML, and MU must be defined before calling BGROUP.
10051!       ML        = lower bandwidth
10052!       MU        = upper bandwidth
10053!       NSUBS     = number of strict sub diagonals
10054!       SUBDS(I)  = row in which the Ith sub diagonal
10055!                   begins, I=1, ..., NSUBS
10056!       NSUPS     = number of strict super diagonals
10057!       SUPDS(I)  = column in which the Ith super diagonal
10058!                   begins, I=1, ..., NSUPS
10059! ..
10060        IMPLICIT NONE
10061! ..
10062! .. Scalar Arguments ..
10063        INTEGER, INTENT (IN) :: N, ML, MU
10064! ..
10065! .. Array Arguments ..
10066        KPP_REAL, INTENT (INOUT) :: BINCL(*), BJA(*), BDONE(*)
10067! ..
10068! .. Local Scalars ..
10069        INTEGER :: I, IBDONE, IBINCL, IER, J, K, KBEGIN, KFINI, &
10070          KI, KJ, MAXG, NCOL, NG
10071        KPP_REAL :: FUDGE, ONE_PLUS_FUDGE
10072        CHARACTER (80) :: MSG
10073! ..
10074! .. Intrinsic Functions ..
10075     INTRINSIC INT, MAX, MIN, REAL
10076! ..
10077! .. FIRST EXECUTABLE STATEMENT BGROUP
10078! ..
10079!       Storage for the column grouping information.
10080        IF (ALLOCATED(BIGP)) THEN
10081           DEALLOCATE (BIGP,BJGP,STAT=IER)
10082           CALL CHECK_STAT(IER,760)
10083        END IF
10084        ALLOCATE (BIGP(N+1),BJGP(N),STAT=IER)
10085        CALL CHECK_STAT(IER,770)
10086
10087        FUDGE = 0.4_dp
10088        ONE_PLUS_FUDGE = 1.0_dp + FUDGE
10089        MAXG = N + 1
10090!       BDONE(1:N) = 0 ...
10091        BDONE(1:N) = FUDGE
10092        NCOL = 1
10093        DO NG = 1, MAXG
10094           BIGP(NG) = NCOL
10095!          BINCL(1:N) = 0 ...
10096           BINCL(1:N) = FUDGE
10097           DO 30 J = 1, N
10098!             Reject column J if it is already in a group.
10099!             IF (BDONE(J) == 1) GOTO 30 ...
10100              IBDONE = INT(BDONE(J))
10101              IF (IBDONE == 1) GOTO 30
10102!             Vertical extent of band = KBEGIN to KFINI.
10103!             KJ = number of nonzeros in column J.
10104!             BJA(K) = K implies nonzero at (k,j).
10105              KBEGIN = MAX(J-MU,1)
10106              KFINI = MIN(J+ML,N)
10107              KJ = 0
10108!             BJA(1:N) = 0 ...
10109              BJA(1:N) = FUDGE
10110!             Locate the row positions of the nonzeros in column J.
10111!             Restrict attention to the band:
10112              DO 10 K = KBEGIN, KFINI
10113                 IF (K < J) THEN
10114                    IF (NSUPS > 0) THEN
10115                       DO I = NSUPS, 1, -1
10116!                         KI = SUPDS(I) + J - 1
10117                          KI = J + 1 - SUPDS(I)
10118                          IF (K == KI) THEN
10119                             KJ = KJ + 1
10120!                            BJA(K) = K ...
10121                             BJA(K) = REAL(K) + FUDGE
10122                          END IF
10123                       END DO
10124                    END IF
10125                 ELSEIF (K == J) THEN
10126                    KJ = KJ + 1
10127!                   BJA(K) = K ...
10128                    BJA(K) = REAL(K) + FUDGE
10129                 ELSE
10130                    IF (NSUBS > 0) THEN
10131                       DO I = NSUBS, 1, -1
10132                          KI = SUBDS(I) + J -1
10133                          IF (K == KI) THEN
10134                             KJ = KJ + 1
10135!                            BJA(K) = K ...
10136                             BJA(K) = REAL(K) + FUDGE
10137                          END IF
10138                       END DO
10139                    END IF
10140              END IF
10141 10           CONTINUE
10142!             At this point BJA contains the row numbers for
10143!             the nonzeros in column J.
10144              DO 20 K = KBEGIN, KFINI
10145!                Reject column J if it overlaps any column
10146!                already in this group.
10147!                I = BJA(K)
10148                 I = INT(BJA(K))
10149                 IBINCL = INT(BINCL(I))
10150!                IF (BINCL(I) == 1 .AND. I == K) GOTO 30
10151                 IF (IBINCL == 1 .AND. I == K) GOTO 30
10152 20           END DO
10153!             Accept column J into group NG.
10154              BJGP(NCOL) = J
10155              NCOL = NCOL + 1
10156!             BDONE(J) = 1 ...
10157              BDONE(J) = ONE_PLUS_FUDGE
10158              DO K = 1, N
10159!                IF (I == K) BINCL(I) = 1 ...
10160                 I = INT(BJA(K))
10161                 IF (I == K) BINCL(I) = ONE_PLUS_FUDGE
10162              END DO
10163 30        END DO
10164!          Done if this group is empty (grouping is complete).
10165           IF (NCOL == BIGP(NG)) GOTO 40
10166        END DO
10167
10168!       Should not get here since MAXG = N + 1.
10169!       Terminal error if not all columns were chosen
10170!       because MAXG too small.
10171        IF (NCOL <= N) THEN
10172           MSG = 'An impossible error occurred in subroutine BGROUP.'
10173           CALL XERRDV(MSG,1600,2,0,0,0,0,ZERO,ZERO)
10174        END IF
10175
10176        NG = MAXG
10177 40     BNGRP = NG - 1
10178
10179!       Trim BIGP to it's actual size if necessary.
10180        IF (NG < MAXG) THEN
10181!          BJA(1:NG) = BIGP(1:NG) ...
10182           DO I = 1, NG
10183              BJA(I) = REAL(BIGP(I)) + FUDGE
10184           END DO
10185           DEALLOCATE (BIGP,STAT=IER)
10186           CALL CHECK_STAT(IER,780)
10187           ALLOCATE (BIGP(NG),STAT=IER)
10188           CALL CHECK_STAT(IER,790)
10189!          BIGP(1:NG) = BJA(1:NG) ...
10190           DO I = 1, NG
10191              BIGP(I) = INT(BJA(I))
10192           END DO
10193        END IF
10194        RETURN
10195
10196      END SUBROUTINE BGROUP
10197!_______________________________________________________________________
10198
10199      SUBROUTINE BANDED_IAJA(N,ML,MU)
10200! ..
10201! Build the sparse structure descriptor arrays for a banded
10202! matrix if the nonzero diagonals are known.
10203! ..
10204!     Input:
10205!
10206!       N       = the order of the matrix (number of odes)
10207!       ML      = integer lower bandwidth
10208!       MU      = integer upper bandwidth
10209!
10210!     Output: (PRIVATE information used in DVJAC)
10211!
10212!       IAB     = IA descriptor array
10213!       JAB     = JA descriptor array
10214!
10215!    Note:
10216!    The PRIVATE banded information SUBDS, NSUBS, SUPDS, NSUPS,
10217!    ML, and MU must be defined before calling BANDED_IAJA.
10218!       ML        = lower bandwidth
10219!       MU        = upper bandwidth
10220!       NSUBS     = number of strict sub diagonals
10221!       SUBDS(I)  = row in which the Ith sub diagonal
10222!                   begins, I=1, ..., NSUBS
10223!       NSUPS     = number of strict super diagonals
10224!       SUPDS(I)  = column in which the Ith super diagonal
10225!                   begins, I=1, ..., NSUPS
10226! ..
10227        IMPLICIT NONE
10228! ..
10229! .. Scalar Arguments ..
10230        INTEGER, INTENT (IN) :: N, ML, MU
10231! ..
10232! .. Local Scalars ..
10233        INTEGER :: I, IER, J, K, KBEGIN, KFINI, KI, KJ, &
10234          NP1, NZBB
10235        CHARACTER (80) :: MSG
10236! ..
10237! .. Intrinsic Functions ..
10238     INTRINSIC ALLOCATED, MAX, MIN
10239! ..
10240! .. FIRST EXECUTABLE STATEMENT BANDED_IAJA
10241! ..
10242!    Check for errors.
10243
10244     IF (.NOT.BUILD_IAJA) THEN
10245        MSG = 'BANDED_IAJA cannot be called with BUILD_IAJA = .FALSE.'
10246        CALL XERRDV(MSG,1610,2,0,0,0,0,ZERO,ZERO)
10247     END IF
10248
10249     IF (NSUBS < 0) THEN
10250        MSG = 'NSUBS < 0 in BANDED_IAJA.'
10251        CALL XERRDV(MSG,1620,2,0,0,0,0,ZERO,ZERO)
10252     ELSE
10253        IF (NSUBS > 0) THEN
10254           IF (NSUBS /= SIZE(SUBDS)) THEN
10255              MSG = 'The size of the SUBDS array must'
10256              CALL XERRDV(MSG,1630,1,0,0,0,0,ZERO,ZERO)
10257              MSG = 'equal NSUBS in BANDED_IAJA.'
10258              CALL XERRDV(MSG,1630,2,0,0,0,0,ZERO,ZERO)
10259           END IF
10260        END IF
10261     END IF
10262
10263     IF (NSUPS < 0) THEN
10264        MSG = 'NSUPS < 0 in BANDED_IAJA.'
10265        CALL XERRDV(MSG,1640,2,0,0,0,0,ZERO,ZERO)
10266     ELSE
10267        IF (NSUPS > 0) THEN
10268           IF (NSUPS /= SIZE(SUPDS)) THEN
10269              MSG = 'The size of the SUPDS array must'
10270              CALL XERRDV(MSG,1650,1,0,0,0,0,ZERO,ZERO)
10271              MSG = 'equal NSUPS in BANDED_IAJA.'
10272              CALL XERRDV(MSG,1650,2,0,0,0,0,ZERO,ZERO)
10273           END IF
10274        END IF
10275     END IF
10276
10277!    Allocate the necessary storage for the descriptor arrays.
10278
10279!    Define the total number of elements in all diagonals.
10280     NP1 = N + 1
10281     NZB = (NSUBS + NSUPS + 1) * NP1 - 1
10282     IF (NSUBS /= 0) THEN
10283        DO I = 1, NSUBS
10284           NZB = NZB - SUBDS(I)
10285        END DO
10286     END IF
10287     IF (NSUPS /= 0) THEN
10288        DO I = 1, NSUPS
10289           NZB = NZB - SUPDS(I)
10290        END DO
10291     END IF
10292     IF (ALLOCATED(IAB)) THEN
10293        DEALLOCATE(IAB,JAB,STAT=IER)
10294        CALL CHECK_STAT(IER,800)
10295     END IF
10296     ALLOCATE(IAB(NP1),JAB(NZB),STAT=IER)
10297     CALL CHECK_STAT(IER,810)
10298     IAB(1) = 1
10299     NZBB = 0
10300
10301!    For each column in the matrix...
10302     DO J = 1, N
10303!       Vertical extent of band = KBEGIN to KFINI.
10304!       KJ = number of nonzeros in column J.
10305        KBEGIN = MAX(J-MU,1)
10306        KFINI = MIN(J+ML,N)
10307        KJ = 0
10308!       Locate the row positions of the nonzeros in column J.
10309!       (Restrict attention to the band.)
10310        IAB(J+1) = IAB(J)
10311!       For each row in the intersection of the band with
10312!       this column ...
10313        DO K = KBEGIN, KFINI
10314!          Does column J intersect a super diagonal at (K,J)?
10315           IF (K < J) THEN
10316              DO I = NSUPS, 1, -1
10317                 KI = J + 1 - SUPDS(I)
10318                 IF (K == KI) THEN
10319                    KJ = KJ + 1
10320                    IAB(J+1) = IAB(J+1) + 1
10321                    NZBB = NZBB + 1
10322                    JAB(NZBB) = K
10323                    GOTO 10
10324                 END IF
10325              END DO
10326           ELSEIF (K == J) THEN
10327!             We are on the main diagonal.
10328              KJ = KJ + 1
10329              IAB(J+1) = IAB(J+1) + 1
10330              NZBB = NZBB + 1
10331              JAB(NZBB) = K
10332              GOTO 10
10333           ELSE
10334!             Does column J intersect a sub diagonal at (K,J)?
10335              DO I = NSUBS, 1, -1
10336                 KI = SUBDS(I) + J - 1
10337                 IF (K == KI) THEN
10338                    KJ = KJ + 1
10339                    IAB(J+1) = IAB(J+1) + 1
10340                    NZBB = NZBB + 1
10341                    JAB(NZBB) = K
10342                    GOTO 10
10343                 END IF
10344              END DO
10345           END IF
1034610         CONTINUE
10347        END DO
10348     END DO
10349
10350     IF (NZBB /= NZB) THEN
10351        MSG = 'NZBB (I1) is not equal to NZB (I2)'
10352        CALL XERRDV(MSG,1660,1,0,0,0,0,ZERO,ZERO)
10353        MSG = 'in BANDED_IAJA.'
10354        CALL XERRDV(MSG,1660,2,2,NZBB,NZB,0,ZERO,ZERO)
10355     END IF
10356     RETURN
10357
10358   END SUBROUTINE BANDED_IAJA
10359!_______________________________________________________________________
10360
10361      SUBROUTINE BANDED_GET_BJNZ(N,ML,MU,JCOL,JNZ,NZJ)
10362! ..
10363! Locate the nonzeros in a given column of a sparse banded matrix
10364! with known diagonals. This is a version of BANDED_IAJA modified
10365! to do only one column.
10366! ..
10367!     Input:
10368!
10369!       N       = the order of the matrix (number of odes)
10370!       ML      = integer lower bandwidth
10371!       MU      = integer upper bandwidth
10372!       JCOL    = column number between 1 and N
10373!       JZ      = integer array of length N
10374!
10375!     Output:
10376!
10377!       JNZ    = integer array of length N. If
10378!                 JNZ(K) is not 0, there is a
10379!                 nonzero at position (K,JCOL)
10380!       NZJ     = number of nozeros in column JCOL
10381!
10382!    Caution:
10383!    No parameter checking is done since this subroutine
10384!    will be called many times. Note that a number of
10385!    PRIVATE parameters must be set before calling this
10386!    subroutine.
10387! ..
10388        IMPLICIT NONE
10389! ..
10390! .. Scalar Arguments ..
10391        INTEGER, INTENT (IN) :: N, ML, MU, JCOL
10392        INTEGER, INTENT (OUT) :: NZJ
10393! ..
10394! .. Array Arguments ..
10395        INTEGER, INTENT (OUT) :: JNZ(*)
10396! ..
10397! .. Local Scalars ..
10398        INTEGER :: I, J, K, KBEGIN, KFINI, KI, KJ
10399! ..
10400! .. Intrinsic Functions ..
10401     INTRINSIC MAX, MIN
10402! ..
10403! .. FIRST EXECUTABLE STATEMENT BANDED_GET_BJNZ
10404! ..
10405        JNZ(1:N) = 0
10406        J = JCOL
10407
10408!       Locate the row positions of the nonzeros in column J.
10409
10410!       Vertical extent of band = KBEGIN to KFINI.
10411        KBEGIN = MAX(J-MU,1)
10412        KFINI = MIN(J+ML,N)
10413!       KJ = number of nonzeros in column J.
10414        KJ = 0
10415!       For each row in the intersection of the band with
10416!       this column ...
10417        DO K = KBEGIN, KFINI
10418!          Does column J intersect a super diagonal at (K,J)?
10419           IF (K < J) THEN
10420              DO I = NSUPS, 1, -1
10421                 KI = J + 1 - SUPDS(I)
10422                 IF (K == KI) THEN
10423                    KJ = KJ + 1
10424                    JNZ(KJ) = K
10425                    GOTO 10
10426                 END IF
10427              END DO
10428           ELSEIF (K == J) THEN
10429!             We are on the main diagonal.
10430              KJ = KJ + 1
10431              JNZ(KJ) = K
10432              GOTO 10
10433           ELSE
10434!             Does column J intersect a sub diagonal at (K,J)?
10435              DO I = NSUBS, 1, -1
10436                 KI = SUBDS(I) + J - 1
10437                 IF (K == KI) THEN
10438                    KJ = KJ + 1
10439                    JNZ(KJ) = K
10440                    GOTO 10
10441                 END IF
10442              END DO
10443           END IF
1044410         CONTINUE
10445        END DO
10446        NZJ = KJ
10447     RETURN
10448
10449   END SUBROUTINE BANDED_GET_BJNZ
10450!_______________________________________________________________________
10451
10452! Beginning of Jacobian related routines that use MA28
10453
10454      SUBROUTINE DVNLSS28(Y,YH,LDYH,SAVF,EWT,ACOR,IWM,WM,F,JAC, &
10455        NFLAG,ATOL,ITOL)
10456! ..
10457! This is the nonlinear system solver for MA28 based sparse solutions.
10458! ..
10459! Subroutine DVNLSS28 is a nonlinear system solver, which uses functional
10460! iteration or a chord (modified Newton) method. For the chord method
10461! direct linear algebraic system solvers are used. Subroutine DVNLSS28
10462! then handles the corrector phase of this integration package.
10463! Communication with DVNLSS28 is done with the following variables. (For
10464! more details, please see the comments in the driver subroutine.)
10465! Y          = The dependent variable, a vector of length N, input.
10466! YH         = The Nordsieck (Taylor) array, LDYH by LMAX, input
10467!              and output. On input, it contains predicted values.
10468! LDYH       = A constant >= N, the first dimension of YH, input.
10469! SAVF       = A work array of length N.
10470! EWT        = An error weight vector of length N, input.
10471! ACOR       = A work array of length N, used for the accumulated
10472!              corrections to the predicted y vector.
10473! WM,IWM     = Real and integer work arrays associated with matrix
10474!              operations in chord iteration (MITER /= 0).
10475! F          = Dummy name for user supplied routine for f.
10476! JAC        = Dummy name for user supplied Jacobian routine.
10477! NFLAG      = Input/output flag, with values and meanings as follows:
10478!              INPUT
10479!                  0 first call for this time step.
10480!                 -1 convergence failure in previous call to DVNLSS28.
10481!                 -2 error test failure in DVSTEP.
10482!              OUTPUT
10483!                  0 successful completion of nonlinear solver.
10484!                 -1 convergence failure or singular matrix.
10485!                 -2 unrecoverable error in matrix preprocessing
10486!                    (cannot occur here).
10487!                 -3 unrecoverable error in solution (cannot occur
10488!                    here).
10489! IPUP       = Own variable flag with values and meanings as follows:
10490!              0,          do not update the Newton matrix.
10491!              MITER \= 0  update Newton matrix, because it is the
10492!                          initial step, order was changed, the error
10493!                          test failed, or an update is indicated by
10494!                          the scalar RC or step counter NST.
10495! For more details, see comments in driver subroutine.
10496! ..
10497     IMPLICIT NONE
10498! ..
10499! .. Scalar Arguments ..
10500        INTEGER, INTENT (IN) :: ITOL, LDYH
10501        INTEGER, INTENT (INOUT) :: NFLAG
10502! ..
10503! .. Array Arguments ..
10504        KPP_REAL, INTENT (INOUT) :: ACOR(*), EWT(*), SAVF(*), &
10505          WM(*), Y(*), YH(LDYH,*)
10506        KPP_REAL, INTENT (IN) :: ATOL(*)
10507        INTEGER IWM(*)
10508        LOGICAL DUMMY
10509! ..
10510! .. Subroutine Arguments ..
10511        EXTERNAL F, JAC
10512! ..
10513! .. Local Scalars ..
10514        KPP_REAL :: ACNRMNEW, CSCALE, DCON, DEL, DELP
10515        INTEGER :: I, IERPJ, IERSL, M
10516! ..
10517! .. Intrinsic Functions ..
10518        INTRINSIC ABS, MAX, MIN
10519! ..
10520! .. FIRST EXECUTABLE STATEMENT DVNLSS28
10521! ..
10522! Get rid of a couple of needless compiler warning messages.
10523        DUMMY = .FALSE.
10524        IF (DUMMY) THEN
10525          WM(1) = ZERO
10526          IWM(1) = 0
10527        END IF 
10528! On the first step, on a change of method order, or after a
10529! nonlinear convergence failure with NFLAG = -2, set IPUP = MITER
10530! to force a Jacobian update when MITER /= 0.
10531        IF (JSTART==0) NSLP = 0
10532        IF (NFLAG==0) ICF = 0
10533        IF (NFLAG==-2) IPUP = MITER
10534        IF ((JSTART==0) .OR. (JSTART==-1)) IPUP = MITER
10535!       If this is functional iteration, set CRATE = 1 and drop
10536!       to 220.
10537        IF (MITER==0) THEN
10538          CRATE = ONE
10539          GOTO 10
10540        END IF
10541
10542! RC is the ratio of new to old values of the coefficient H/EL(2)=h/l1.
10543! When RC differs from 1 by more than CCMAX, IPUP is set to MITER
10544! to force DVJACS28 to be called, if a Jacobian is involved. In any
10545! case, DVJACS28 is called at least every MSBP steps.
10546
10547        DRC = ABS(RC-ONE)
10548        IF (DRC>CCMAX .OR. NST>=NSLP+MSBP) IPUP = MITER
10549
10550! Up to MAXCOR corrector iterations are taken. A convergence test is
10551! made on the r.m.s. norm of each correction, weighted by the error
10552! weight vector EWT. The sum of the corrections is accumulated in the
10553! vector ACOR(i). The YH array is not altered in the corrector loop.
10554
1055510      M = 0
10556        DELP = ZERO
10557! Original:
10558!       CALL DCOPY_F90(N,YH(1,1),1,Y,1)
10559        CALL DCOPY_F90(N,YH(1:N,1),1,Y(1:N),1)
10560        CALL F(N,TN,Y,SAVF)
10561        NFE = NFE + 1
10562        IF (BOUNDS) THEN
10563          DO I = 1, NDX
10564            IF (ABS(YH(IDX(I),1)-LB(I))<=ZERO) SAVF(IDX(I)) = &
10565              MAX(SAVF(IDX(I)),ZERO)
10566            IF (ABS(YH(IDX(I),1)-UB(I))<=ZERO) SAVF(IDX(I)) = &
10567              MIN(SAVF(IDX(I)),ZERO)
10568          END DO
10569        END IF
10570        IF (IPUP<=0) GOTO 20
10571
10572! If indicated, the matrix P = I - h*rl1*J is reevaluated and
10573! preprocessed before starting the corrector iteration. IPUP
10574! is set to 0 as an indicator that this has been done.
10575
10576        CALL DVJACS28(Y,YH,LDYH,EWT,ACOR,SAVF,F,JAC,IERPJ,N, &
10577          ATOL,ITOL)
10578        IPUP = 0
10579        RC = ONE
10580        DRC = ZERO
10581        CRATE = ONE
10582        NSLP = NST
10583!     If matrix is singular, take error return to force cut in
10584!     step size.
10585        IF (IERPJ/=0) GOTO 70
1058620      ACOR(1:N) = ZERO
10587!       This is a looping point for the corrector iteration.
1058830      IF (MITER/=0) GOTO 40
10589
10590! In the case of functional iteration, update Y directly from
10591! the result of the last function evaluation.
10592
10593        SAVF(1:N) = RL1*(H*SAVF(1:N)-YH(1:N,2))
10594        Y(1:N) = SAVF(1:N) - ACOR(1:N)
10595        DEL = DVNORM(N,Y,EWT)
10596        Y(1:N) = YH(1:N,1) + SAVF(1:N)
10597        CALL DCOPY_F90(N,SAVF,1,ACOR,1)
10598        GOTO 50
10599
10600! In the case of the chord method, compute the corrector error,
10601! and solve the linear system with that as right-hand side and
10602! P as coefficient matrix. The correction is scaled by the factor
10603! 2/(1+RC) to account for changes in h*rl1 since the last
10604! DVJACS28 call.
10605
1060640      Y(1:N) = (RL1*H)*SAVF(1:N) - (RL1*YH(1:N,2)+ACOR(1:N))
10607        CALL DVSOLS28(Y,SAVF,IERSL)
10608        NNI = NNI + 1
10609        IF (IERSL>0) GOTO 60
10610        IF (METH==2 .AND. ABS(RC-ONE)>ZERO) THEN
10611          CSCALE = TWO/(ONE+RC)
10612          CALL DSCAL_F90(N,CSCALE,Y,1)
10613        END IF
10614        DEL = DVNORM(N,Y,EWT)
10615        CALL DAXPY_F90(N,ONE,Y,1,ACOR,1)
10616        Y(1:N) = YH(1:N,1) + ACOR(1:N)
10617
10618! Test for convergence. If M > 0, an estimate of the convergence
10619! rate constant is stored in CRATE, and this is used in the test.
10620
1062150      IF (M/=0) CRATE = MAX(CRDOWN*CRATE,DEL/DELP)
10622        DCON = DEL*MIN(ONE,CRATE)/TQ(4)
10623        IF (DCON<=ONE) GOTO 80
10624        M = M + 1
10625        IF (M==MAXCOR) GOTO 60
10626        IF (M>=2 .AND. DEL>RDIV*DELP) GOTO 60
10627        DELP = DEL
10628        CALL F(N,TN,Y,SAVF)
10629        NFE = NFE + 1
10630        IF (BOUNDS) THEN
10631          DO I = 1, NDX
10632            IF (ABS(YH(IDX(I),1)-LB(I))<=ZERO) SAVF(IDX(I)) = &
10633              MAX(SAVF(I),ZERO)
10634            IF (ABS(YH(IDX(I),1)-UB(I))<=ZERO) SAVF(IDX(I)) = &
10635              MIN(SAVF(I),ZERO)
10636          END DO
10637        END IF
10638        GOTO 30
10639
1064060      IF (MITER==0 .OR. JCUR==1) GOTO 70
10641        ICF = 1
10642        IPUP = MITER
10643        GOTO 10
10644
1064570      CONTINUE
10646        NFLAG = -1
10647        ICF = 2
10648        IPUP = MITER
10649        RETURN
10650
10651!       Return for successful step.
1065280      NFLAG = 0
10653
10654!       Enforce bounds.
10655        IF (BOUNDS) THEN
10656          CHANGED_ACOR = .FALSE.
10657          IF (M==0) THEN
10658            ACNRM = DEL
10659          ELSE
10660            ACNRM = DVNORM(N,ACOR,EWT)
10661          END IF
10662          IF (MITER/=0) THEN
10663!           Since Y(:) = YH(:,1) + ACOR(:):
10664            DO I = 1, NDX
10665              IF (Y(IDX(I))<LB(I)) THEN
10666                CHANGED_ACOR = .TRUE.
10667                ACOR(IDX(I)) = LB(I) - YH(IDX(I),1)
10668                SAVF(IDX(I)) = ACOR(IDX(I))
10669              END IF
10670              IF (Y(IDX(I))>UB(I)) THEN
10671                CHANGED_ACOR = .TRUE.
10672                ACOR(IDX(I)) = UB(I) - YH(IDX(I),1)
10673                SAVF(IDX(I)) = ACOR(IDX(I))
10674              END IF
10675            END DO
10676          ELSE
10677!           Since Y(:) = YH(:,1) + SAVF(:) and
10678!           since CALL DCOPY_F90(N, SAVF, 1, ACOR, 1) ...
10679            DO I = 1, NDX
10680              IF (Y(IDX(I))<LB(IDX(I))) THEN
10681                CHANGED_ACOR = .TRUE.
10682                ACOR(IDX(I)) = LB(I) - YH(IDX(I),1)
10683              END IF
10684              IF (Y(IDX(I))>UB(IDX(I))) THEN
10685                CHANGED_ACOR = .TRUE.
10686                ACOR(IDX(I)) = UB(I) - YH(IDX(I),1)
10687              END IF
10688            END DO
10689          END IF
10690          IF (CHANGED_ACOR) THEN
10691            IF (M==0) THEN
10692              ACNRMNEW = DEL
10693            ELSE
10694              ACNRMNEW = DVNORM(N,ACOR,EWT)
10695            END IF
10696            ACNRM = MAX(ACNRM,ACNRMNEW)
10697          ELSE
10698          END IF
10699          NFLAG = 0
10700          JCUR = 0
10701          ICF = 0
10702        ELSE
10703!         No projections are required.
10704          NFLAG = 0
10705          JCUR = 0
10706          ICF = 0
10707          IF (M==0) ACNRM = DEL
10708          IF (M>0) ACNRM = DVNORM(N,ACOR,EWT)
10709        END IF
10710        RETURN
10711
10712      END SUBROUTINE DVNLSS28
10713!_______________________________________________________________________
10714
10715      SUBROUTINE DVSOLS28(X,TEM,IERSL)
10716! ..
10717! Manage the solution of the MA28 based sparse linear system arising
10718! from a chord iteration.
10719! ..
10720! This routine solves the sparse linear system arising from a chord
10721! iteration. If MITER is 6 or 7, it calls MA28CD to accomplish this.
10722! Communication with DVSOLS28 uses the following variables:
10723! X = The right-hand side vector on input, and the solution vector
10724!     on output, of length N.
10725! TEM (=SAVF(*))
10726! IERSL = Output flag. IERSL = 0 if no trouble occurred.
10727! ..
10728     IMPLICIT NONE
10729! ..
10730! .. Scalar Arguments ..
10731        INTEGER, INTENT (INOUT) :: IERSL
10732! ..
10733! .. Array Arguments ..
10734        KPP_REAL, INTENT (INOUT) :: TEM(*), X(*)
10735! ..
10736! .. Local Scalars ..
10737        INTEGER :: I
10738! ..
10739! .. FIRST EXECUTABLE STATEMENT DVSOLS28
10740! ..
10741        IF (SCALE_MATRIX) THEN
10742           DO I = 1, N
10743              X(I) = X(I) * RSCALEX(I)
10744           END DO
10745        END IF
10746        IERSL = 0
10747        CALL MA28CD(N,PMAT,LICN_ALL,ICN,IKEEP28,X,TEM,1)
10748        MA28CD_CALLS = MA28CD_CALLS + 1
10749        IF (SCALE_MATRIX) THEN
10750           DO I = 1, N
10751              X(I) = X(I) * CSCALEX(I)
10752           END DO
10753        END IF
10754        RETURN
10755
10756      END SUBROUTINE DVSOLS28
10757!_______________________________________________________________________
10758
10759      SUBROUTINE DVJACS28(Y,YH,LDYH,EWT,FTEMP1,SAVF,F,JAC,IERPJ,N, &
10760        ATOL,ITOL)
10761! ..
10762! Compute and process P = I - H*RL1*J, where J is an approximation to
10763! the MA28 based sparse Jacobian.
10764! ..
10765     IMPLICIT NONE
10766! ..
10767! .. Scalar Arguments ..
10768        INTEGER, INTENT (INOUT) :: IERPJ
10769        INTEGER, INTENT (IN) :: LDYH, N, ITOL
10770! ..
10771! .. Array Arguments ..
10772        KPP_REAL, INTENT (INOUT) :: EWT(*), FTEMP1(*), SAVF(*), Y(*), YH(LDYH,*)
10773        KPP_REAL, INTENT (IN) :: ATOL(*)
10774! ..
10775! .. Subroutine Arguments ..
10776        EXTERNAL F, JAC
10777! ..
10778! .. Local Scalars ..
10779        KPP_REAL :: CON, FAC, HRL1, R, R0, SRUR
10780        INTEGER :: I, IER, J, JER, JJ, JJ1, JJ2, K, K1, K2, MA28,       &
10781          MA28SAVE, MB28SAVE, NG, NZ
10782        CHARACTER (80) :: MSG
10783! ..
10784! .. Intrinsic Functions ..
10785        INTRINSIC ABS, EXP, MAX, REAL
10786! ..
10787! .. FIRST EXECUTABLE STATEMENT DVJACS28
10788! ..
10789        IERPJ = 0
10790
10791!       Structure determination
10792
10793!       Calculate the sparsity structure if this is the first call to
10794!       DVJACS28 with ISTATE = 1 or if it is a continuation call with
10795!       ISTATE = 3.
10796        IF (ISTATC==1 .OR. ISTATC==3) THEN
10797          CALL DVPREPS(N,Y,YH,LDYH,DTEMP,EWT,F,JAC)
10798          ISTATC = 0
10799        END IF
10800        JCUR = 0
10801        HRL1 = H*RL1
10802        CON = -HRL1
10803
10804!       If MA28 = 4 the saved copy of the Jacobian will be used
10805!       to restore PMAT. If MA28 = 1,2,3 the Jacobian will be
10806!       recomputed. If MA28 = 1,2 the JVECT and ICN pointer arrays
10807!       will be defined and MA28AD will be called to decompose
10808!       PMAT. If MA28 = 3 the JVECT pointer array will be defined
10809!       and MA28BD will be called to decompose PMAT using the ICN
10810!       pointer array returned in the last call to MA28AD.
10811
10812        MA28 = 4
10813        IF (INEWJ==1 .OR. MB28==0) MA28 = 3
10814        IF (NST>=NSLJ+MSBJ) MA28 = 3
10815!       IF (ICF==1 .OR. ICF==2) MA28 = 3
10816        IF (ICF==1 .AND. DRC<CCMXJ) MA28 = 3
10817        IF (ICF==2) MA28 = 3
10818        IF (NST>=NSLG+MSBG) MA28 = 2
10819        IF (JSTART==0 .OR. JSTART==-1) MA28 = 1
10820        JSTART = 1
1082110      IF (MA28<=2) NSLG = NST
10822        IF (MA28<=3) NSLJ = NST
10823
10824!       Analytical Sparse Jacobian
10825
10826!       If MITER = 6, call JAC to evaluate J analytically, multiply
10827!       J by CON = -H*EL(1), and add the identity matrix to form P.
10828        IF (MITER==6) THEN
10829          IF (MA28==4) THEN
10830!           Reuse the saved Jacobian.
10831            NZ = IAN(N+1) - 1
10832            PMAT(1:NZ) = CON*JMAT(1:NZ)
10833            DO K = 1, NZ
10834              IF (JAN(K)==JVECT(K)) PMAT(K) = PMAT(K) + ONE
10835            END DO
10836            GOTO 90
10837          END IF
10838          JCUR = 1
10839          NJE = NJE + 1
10840          IF (MA28==1 .OR. MA28==2) THEN
10841            NZ = IAN(N+1) - 1
10842            CALL JAC(N,TN,Y,IAN,JAN,NZ,PMAT)
10843            NZ = IAN(N+1) - 1
10844            IF (NZ>NZ_ALL) THEN
10845              MSG = 'DVODE_F90-- NZ > NZ_ALL in DVJACS28.'
10846              CALL XERRDV(MSG,1670,2,0,0,0,0,ZERO,ZERO)
10847            END IF
10848!           Define column pointers for MA28AD.
10849            CALL SET_ICN(N,IAN,ICN)
10850            CALL CHECK_DIAG(N,IAN,JAN,ICN)
10851            PMAT(1:NZ) = CON*PMAT(1:NZ)
10852            DO K = 1, NZ
10853              IF (JAN(K)==ICN(K)) PMAT(K) = PMAT(K) + ONE
10854            END DO
10855            GOTO 80
10856          ELSE
10857!           MA28 = 3...
10858            NZ = IAN(N+1) - 1
10859            CALL JAC(N,TN,Y,IAN,JAN,NZ,PMAT)
10860            NZ = IAN(N+1) - 1
10861            IF (NZ>NZ_ALL) THEN
10862              MSG = 'DVODE_F90-- NZ > NZ_ALL in DVJACS28.'
10863              CALL XERRDV(MSG,1680,2,0,0,0,0,ZERO,ZERO)
10864            END IF
10865!           Define column pointers for MA28AD.
10866            CALL SET_ICN(N,IAN,JVECT)
10867            CALL CHECK_DIAG(N,IAN,JAN,JVECT)
10868            IF (INEWJ/=1) JMAT(1:NZ) = PMAT(1:NZ)
10869            PMAT(1:NZ) = CON*PMAT(1:NZ)
10870            DO K = 1, NZ
10871              IF (JAN(K)==JVECT(K)) PMAT(K) = PMAT(K) + ONE
10872            END DO
10873            GOTO 90
10874          END IF
10875        END IF
10876
10877!       Finite Difference Sparse Jacobian
10878
10879!       If MITER = 7, evaluate J numerically, multiply J by
10880!       CON, and add the identity matrix to form P.
10881        IF (MITER==7) THEN
10882          IF (MA28==4) THEN
10883!           Reuse the saved constant Jacobian.
10884            NZ = IAN(N+1) - 1
10885            PMAT(1:NZ) = CON*JMAT(1:NZ)
10886            DO J = 1, N
10887              K1 = IAN(J)
10888              K2 = IAN(J+1) - 1
10889              DO K = K1, K2
10890                I = JAN(K)
10891                IF (I==J) PMAT(K) = PMAT(K) + ONE
10892              END DO
10893            END DO
10894            GOTO 90
10895          ELSE
10896            NZ = IAN(N+1) - 1
10897            JCUR = 1
10898            IF (.NOT.(J_IS_CONSTANT.AND.J_HAS_BEEN_COMPUTED)) THEN
10899               IF (USE_JACSP) THEN
10900!                 Approximate the Jacobian using Doug Salane's JACSP.
10901!                 The JPNTRDS and INDROWDS pointer arrays were defined
10902!                 in DVPREPS (and altered in DSM).
10903                  IOPTDS(1) = 2
10904                  IOPTDS(2) = 0
10905                  IOPTDS(3) = 1
10906                  IOPTDS(5) = 0
10907!                 INFORDS(4) was initialized in DVPREPS (and altered in
10908!                 the first call to JACSP).
10909                  LWKDS  = 3 * N
10910                  LIWKDS = 50 + N
10911                  NRFJACDS = NZ
10912                  NCFJACDS = 1
10913
10914!                 Set flag to indicate how the YSCALE vector will be
10915!                 set for JACSP.
10916                  LIKE_ORIGINAL_VODE = .FALSE.
10917!                 Calculate the YSCALEDS vector for JACSPDV.
10918                  IF (LIKE_ORIGINAL_VODE) THEN
10919                     FAC = DVNORM(N,SAVF,EWT)
10920!                    JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
10921!                    R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
10922                     R0 = THOU*ABS(H)*REAL(N)*FAC
10923                     IF (ABS(R0)<=ZERO) R0 = ONE
10924!                    SRUR = WM1
10925                     DO J = 1, N
10926!                       JACSPDB multiplies YSCALEDS(*) BY UROUND**0.825:
10927!                       R = MAX(ABS(Y(J)),R0/EWT(J))
10928                        R = MAX(ABS(Y(J))/U325,(R0/EWT(J))*U125)
10929                        YSCALEDS(J) = R
10930                     END DO
10931                  ELSE
10932                     IF (ITOL == 1 .OR. ITOL == 3) THEN
10933                        DO J = 1, N
10934                           YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(1),UROUND)
10935                        END DO
10936                     ELSE
10937                        DO J = 1, N
10938                          YSCALEDS(J) = MAX(ABS(Y(J)),ATOL(J),UROUND)
10939                        END DO
10940                     END IF
10941                  END IF
10942
10943                  CALL JACSPDB(F,N,TN,Y,SAVF,PMAT(1),NRFJACDS, &
10944                    YSCALEDS,FACDS,IOPTDS,WKDS,LWKDS,IWKDS,LIWKDS, &
10945                    MAXGRPDS,NGRPDS,JPNTRDS,INDROWDS)
10946                  NFE = NFE + IWKDS(7)
10947                  NJE = NJE + 1
10948
10949                  DO NG = 1, MAXGRPDS
10950                    JJ1 = IGP(NG)
10951                    JJ2 = IGP(NG+1) - 1
10952                    DO JJ = JJ1, JJ2
10953                      J = JGP(JJ)
10954                      K1 = IAN(J)
10955                      K2 = IAN(J+1) - 1
10956                      DO K = K1, K2
10957                        I = JAN(K)
10958                        GOTO (17,17,18) MA28
10959!                       Define the row pointers for MA28AD.
1096017                      JVECT(K) = I
10961!                       Define the column pointers for MA28AD.
10962                        ICN(K) = J
10963                        GOTO 19
10964!                       Define the column pointers for MA28AD.
1096518                      JVECT(K) = J
1096619                      CONTINUE
10967                        IF (INEWJ==0) JMAT(K) = PMAT(K)
10968                        PMAT(K) = CON*PMAT(K)
10969                        IF (I==J) PMAT(K) = PMAT(K) + ONE
10970                      END DO
10971                    END DO
10972                  END DO
10973                  NFE = NFE + MAXGRPDS
10974               ELSE
10975                  FAC = DVNORM(N,SAVF,EWT)
10976                  R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC
10977                  IF (ABS(R0)<=ZERO) R0 = ONE
10978                  SRUR = WM1
10979                  DO NG = 1, NGP
10980                    JJ1 = IGP(NG)
10981                    JJ2 = IGP(NG+1) - 1
10982                    DO JJ = JJ1, JJ2
10983                      J = JGP(JJ)
10984                      R = MAX(SRUR*ABS(Y(J)),R0/EWT(J))
10985                      Y(J) = Y(J) + R
10986                    END DO
10987                    CALL F(N,TN,Y,FTEMP1)
10988                    NFE = NFE + 1
10989                    DO JJ = JJ1, JJ2
10990                      J = JGP(JJ)
10991                      Y(J) = YH(J,1)
10992                      R = MAX(SRUR*ABS(Y(J)),R0/EWT(J))
10993                      FAC = ONE / R
10994                      K1 = IAN(J)
10995                      K2 = IAN(J+1) - 1
10996                      DO K = K1, K2
10997                        I = JAN(K)
10998                        GOTO (20,20,30) MA28
10999!                       Define row pointers for MA28AD.
1100020                      JVECT(K) = I
11001!                       Define column pointers for MA28AD.
11002                        ICN(K) = J
11003                        GOTO 40
11004!                       Define column pointers for MA28AD.
1100530                      JVECT(K) = J
1100640                      PMAT(K) = (FTEMP1(I)-SAVF(I)) * FAC
11007                        IF (INEWJ==0) JMAT(K) = PMAT(K)
11008                        PMAT(K) = CON*PMAT(K)
11009                        IF (I==J) PMAT(K) = PMAT(K) + ONE
11010                      END DO
11011                    END DO
11012                  END DO
11013                  NFE = NFE + NGP
11014                  NJE = NJE + 1
11015               END IF
11016               IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .TRUE.
11017            ELSE
11018!              Do not recompute the constant Jacobian.
11019!              Reuse the saved Jacobian.
11020               NZ = IAN(N+1) - 1
11021               PMAT(1:NZ) = CON*JMAT(1:NZ)
11022               DO J = 1, N
11023                 K1 = IAN(J)
11024                 K2 = IAN(J+1) - 1
11025                 DO K = K1, K2
11026                   I = JAN(K)
11027                   IF (I==J) PMAT(K) = PMAT(K) + ONE
11028                   GOTO (50,50,60) MA28
11029!                  Define row pointers for MA28AD.
1103050                 JVECT(K) = I
11031!                  Define column pointers for MA28AD.
11032                   ICN(K) = J
11033                   GOTO 70
11034!                  Define column pointers for MA28AD.
1103560                 JVECT(K) = J
1103670                 CONTINUE
11037                 END DO
11038               END DO
11039            END IF
11040            GOTO (80,80,90) MA28
11041          END IF
11042        END IF
11043
11044!       MA28AD does an LU factorization based on a pivotal strategy
11045!       designed to compromise between maintaining sparsity and
11046!       controlling loss of accuracy due to roundoff error. Unless
11047!       magnitudes of Jacobian elements change so as to invalidate
11048!       choice of pivots, MA28AD need only be called at beginning
11049!       of the integration.
11050
1105180      CONTINUE
11052        IF (SCALE_MATRIX) THEN
11053!          MA19AD computes scaling factors for the iteration matrix.
11054           CALL MC19AD(N,NZ,PMAT,JAN,ICN,RSCALEX,CSCALEX,WSCALEX)
11055           MC19AD_CALLS = MC19AD_CALLS + 1
11056           DO I =1, N
11057              RSCALEX(I) = EXP(RSCALEX(I))
11058              CSCALEX(I) = EXP(CSCALEX(I))
11059           END DO
11060           DO K = 1, NZ
11061              I = JAN(K)
11062              J = ICN(K)
11063              PMAT(K) = PMAT(K) * RSCALEX(I) * CSCALEX(J)
11064           END DO
11065        END IF
11066        OK_TO_CALL_MA28 = .TRUE.
11067        CALL MA28AD(N,NZ,PMAT,LICN_ALL,JAN,LIRN_ALL,ICN,U_PIVOT, &
11068          IKEEP28,IW28,FTEMP1,IER)
11069        OK_TO_CALL_MA28 = .FALSE.
11070        MA28AD_CALLS = MA28AD_CALLS + 1
11071        MA28SAVE = MA28
11072        MB28SAVE = MB28
11073        MB28 = 0
11074        NLU = NLU + 1
11075        MAX_MINIRN = MAX(MAX_MINIRN,MINIRN)
11076        MAX_MINICN = MAX(MAX_MINICN,MINICN)
11077!       IER = -1: Numerically singular Jacobian
11078!       IER = -2: Structurally singular Jacobian
11079        IF (IER==-1 .OR. IER==-2) IERPJ = 1
11080        IF (IER==-3) THEN
11081!         LIRN_ALL is not large enough.
11082          IF (LP /= 0) THEN
11083             MSG = 'LIRN_ALL (=I1) is not large enough.'
11084             CALL XERRDV(MSG,1690,1,0,0,0,0,ZERO,ZERO)
11085             MSG = 'Allocating more space for another try.'
11086             CALL XERRDV(MSG,1690,1,1,LIRN_ALL,0,0,ZERO,ZERO)
11087          END IF
11088!         Allocate more space for JAN and JVECT and try again.
11089          LIRN_ALL = LIRN_ALL + MAX(MAX(1000,ELBOW_ROOM*NZ_SWAG),10*N)
11090          LIRN_ALL = MAX(LIRN_ALL,(11*MINIRN)/10)
11091          IF (LIRN_ALL>MAX_ARRAY_SIZE) THEN
11092            MSG = 'Maximum array size exceeded. Stopping.'
11093            CALL XERRDV(MSG,1700,2,0,0,0,0,ZERO,ZERO)
11094          END IF
11095          DEALLOCATE (JAN,STAT=JER)
11096          CALL CHECK_STAT(JER,820)
11097          ALLOCATE (JAN(LIRN_ALL),STAT=JER)
11098          CALL CHECK_STAT(JER,830)
11099          IF (MITER==7) THEN
11100            JAN(1:NZ) = JVECT(1:NZ)
11101          END IF
11102          DEALLOCATE (JVECT,STAT=JER)
11103          CALL CHECK_STAT(JER,840)
11104          ALLOCATE (JVECT(LIRN_ALL),STAT=JER)
11105          CALL CHECK_STAT(JER,850)
11106          IF (MITER==7) THEN
11107            JVECT(1:NZ) = JAN(1:NZ)
11108          END IF
11109          MA28 = MA28SAVE
11110          MB28 = MB28SAVE
11111          NLU = NLU - 1
11112!         Since PMAT has changed, it must be restored:
11113          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .FALSE.
11114          GOTO 10
11115        END IF
11116        IF (IER==-4 .OR. IER==-5 .OR. IER==-6) THEN
11117!         LICN_ALL is not large enough.
11118          IF (LP /= 0) THEN
11119             MSG = 'LICN_ALL (=I1) is not large enough.'
11120             CALL XERRDV(MSG,1710,1,0,0,0,0,ZERO,ZERO)
11121             MSG = 'Allocating more space for another try.'
11122             CALL XERRDV(MSG,1710,1,1,LICN_ALL,0,0,ZERO,ZERO)
11123          END IF
11124!         Allocate more space for JAN and JVECT and try again.
11125          LICN_ALL = LICN_ALL + MAX(MAX(1000,ELBOW_ROOM*NZ_SWAG),10*N)
11126          LICN_ALL = MAX(LICN_ALL,(11*MINICN)/10)
11127          IF (LICN_ALL>MAX_ARRAY_SIZE) THEN
11128            MSG = 'Maximum array size exceeded. Stopping.'
11129            CALL XERRDV(MSG,1720,2,0,0,0,0,ZERO,ZERO)
11130          END IF
11131          DEALLOCATE (PMAT,ICN,STAT=JER)
11132          CALL CHECK_STAT(JER,860)
11133          ALLOCATE (PMAT(LICN_ALL),ICN(LICN_ALL),STAT=JER)
11134          PMAT(1:LICN_ALL) = ZERO
11135          CALL CHECK_STAT(JER,870)
11136          IF (MITER==7) THEN
11137            JAN(1:NZ) = JVECT(1:NZ)
11138          END IF
11139          MA28 = MA28SAVE
11140          MB28 = MB28SAVE
11141          NLU = NLU - 1
11142          IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .FALSE.
11143          GOTO 10
11144        END IF
11145        IF (MITER/=7) RETURN
11146        JAN(1:NZ) = JVECT(1:NZ)
11147        RETURN
11148
11149!       MA28BD uses the pivot sequence generated by an earlier call
11150!       to MA28AD to factor a new matrix of the same structure.
11151
1115290      CONTINUE
11153
11154        IF (SCALE_MATRIX) THEN
11155           DO K =1, NZ
11156              I = JAN(K)
11157              J = JVECT(K)
11158              PMAT(K) = PMAT(K) * RSCALEX(I) * CSCALEX(J)
11159           END DO
11160        END IF
11161        CALL MA28BD(N,NZ,PMAT,LICN_ALL,JAN,JVECT,ICN,IKEEP28,IW28, &
11162          FTEMP1,IER)
11163        MA28BD_CALLS = MA28BD_CALLS + 1
11164        MB28 = 1
11165        NLU = NLU + 1
11166!       IER = -2 : The matrix is numerically singular. The MA28AD
11167!                  pivot sequence leads to a zero pivot, that is,
11168!                  to one for which the ratio of it to the smallest
11169!                  element in the row is less than EPS.
11170!       IER = -13: The matrix is structurally singular.
11171
11172        IF (REDO_PIVOT_SEQUENCE) THEN
11173!          Force MA28AD to calculate a new pivot sequence.
11174           IF (IER/=-13 .AND. IER/=-2 .AND. IER<=0) RETURN
11175           IF (IER==-2) MA28 = 1
11176           IF (IER==-13) MA28 = 1
11177           IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .FALSE.
11178        ELSE
11179           IF (IER==-2) IERPJ = 1
11180           IF (IER/=-13 .AND. IER<=0) RETURN
11181           IF (IER==-13) MA28 = 1
11182           IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .FALSE.
11183        END IF
11184        IF (IER>0) MA28 = 2
11185        IF (IER==-13 .AND. MITER==7 .AND. MOSS==2) THEN
11186!          Recompute the sparsity structure.
11187           CALL DVRENEW(N,Y,SAVF,EWT,F)
11188           IF (J_IS_CONSTANT) J_HAS_BEEN_COMPUTED = .FALSE.
11189        END IF
11190        GOTO 10
11191
11192      END SUBROUTINE DVJACS28
11193! End of Jacobian related routines that use MA28
11194!_______________________________________________________________________
11195
11196      SUBROUTINE SET_ICN(N,IA,ICN)
11197! ..
11198! Define the column locations of nonzero elements for a sparse
11199! matrix.
11200! ..
11201     IMPLICIT NONE
11202! ..
11203! .. Scalar Arguments ..
11204        INTEGER, INTENT (IN) :: N
11205! ..
11206! .. Array Arguments ..
11207        INTEGER, INTENT (IN) :: IA(*)
11208        INTEGER, INTENT (INOUT) :: ICN(*)
11209! ..
11210! .. Local Scalars ..
11211        INTEGER :: J, KMAX, KMIN
11212! ..
11213! .. FIRST EXECUTABLE STATEMENT SET_ICN
11214! ..
11215        KMIN = 1
11216        DO J = 1, N
11217          KMAX = IA(J+1) - 1
11218          ICN(KMIN:KMAX) = J
11219          KMIN = KMAX + 1
11220        END DO
11221
11222      END SUBROUTINE SET_ICN
11223!_______________________________________________________________________
11224
11225      SUBROUTINE CHECK_DIAG(N,IA,JA,ICN)
11226! ..
11227! Check that the diagonal is included in the sparse matrix
11228! description arrays.
11229! ..
11230     IMPLICIT NONE
11231! ..
11232! .. Scalar Arguments ..
11233        INTEGER, INTENT (IN) :: N
11234! ..
11235! .. Array Arguments ..
11236        INTEGER, INTENT (IN) :: IA(*), ICN(*), JA(*)
11237! ..
11238! .. Local Scalars ..
11239        INTEGER :: J, K, KMAX, KMIN
11240        CHARACTER (80) :: MSG
11241! ..
11242! .. FIRST EXECUTABLE STATEMENT CHECK_DIAG
11243! ..
11244        KMIN = 1
11245        DO J = 1, N
11246          KMAX = IA(J+1) - 1
11247          DO K = KMIN, KMAX
11248            IF (JA(K)==ICN(K)) GOTO 10
11249          END DO
11250          MSG = 'In CHECK_DIAG, the diagonal is not present.'
11251          CALL XERRDV(MSG,1730,2,0,0,0,0,ZERO,ZERO)
1125210        CONTINUE
11253          KMIN = KMAX + 1
11254        END DO
11255
11256      END SUBROUTINE CHECK_DIAG
11257!_______________________________________________________________________
11258
11259      SUBROUTINE DVCHECK(JOB,G,NEQ,Y,YH,NYH,G0,G1,GX,IRT)
11260! ..
11261! Check for the presence of a root in the vicinity of the current T,
11262! in a manner depending on the input flag JOB, and call DVROOTS to
11263! locate the root as precisely as possible.
11264! ..
11265! This subroutine is essentially DRCHEK from LSODAR.
11266! ..
11267     IMPLICIT NONE
11268! ..
11269! .. Scalar Arguments ..
11270        INTEGER, INTENT (INOUT) :: IRT
11271        INTEGER, INTENT (IN) :: JOB, NEQ, NYH
11272! ..
11273! .. Array Arguments ..
11274        KPP_REAL, INTENT (INOUT) :: G0(*), G1(*), GX(*), Y(*), YH(NYH,*)
11275! ..
11276! .. Subroutine Arguments ..
11277        EXTERNAL G
11278! ..
11279! .. Local Scalars ..
11280        KPP_REAL :: HMING, T1, TEMP1, TEMP2, X
11281        INTEGER :: I, IFLAG, JFLAG
11282        LOGICAL :: ZROOT
11283! ..
11284! .. Intrinsic Functions ..
11285        INTRINSIC ABS, MAX, MIN, SIGN
11286! ..
11287! In addition to variables described previously, DVCHECK
11288! uses the following for communication:
11289! JOB    = integer flag indicating type of call:
11290!          JOB = 1 means the problem is being initialized, and DVCHECK
11291!                  is to look for a root at or very near the initial T.
11292!          JOB = 2 means a continuation call to the solver was just
11293!                  made, and DVCHECK is to check for a root in the
11294!                  relevant part of the step last taken.
11295!          JOB = 3 means a successful step was just taken, and DVCHECK
11296!                  is to look for a root in the interval of the step.
11297! G0     = array of length NG, containing the value of g at T = T0ST.
11298!          G0 is input for JOB >= 2, and output in all cases.
11299! G1,GX  = arrays of length NG for work space.
11300! IRT    = completion flag:
11301!          IRT = 0  means no root was found.
11302!          IRT = -1 means JOB = 1 and a root was found too near to T.
11303!          IRT = 1  means a legitimate root was found (JOB = 2 or 3).
11304!                   On return, T0ST is the root location, and Y is the
11305!                   corresponding solution vector.
11306! T0ST   = value of T at one endpoint of interval of interest. Only
11307!          roots beyond T0ST in the direction of integration are sought.
11308!          T0ST is input if JOB >= 2, and output in all cases.
11309!          T0ST is updated by DVCHECK, whether a root is found or not.
11310! TLAST  = last value of T returned by the solver (input only).
11311! TOUTC  = copy of TOUT(input only).
11312! IRFND  = input flag showing whether the last step taken had a root.
11313!          IRFND = 1 if it did, = 0 if not.
11314! ITASKC = copy of ITASK (input only).
11315! NGC    = copy of NG (input only).
11316! ..
11317! .. FIRST EXECUTABLE STATEMENT DVCHECK
11318! ..
11319        IRT = 0
11320        JROOT(1:NGC) = 0
11321        HMING = (ABS(TN)+ABS(H))*UROUND*HUN
11322
11323        GOTO (10,30,80) JOB
11324
11325!       Evaluate g at initial T, and check for zero values.
1132610      CONTINUE
11327        T0ST = TN
11328        CALL G(NEQ,T0ST,Y,NGC,G0)
11329        NGE = 1
11330        ZROOT = .FALSE.
11331        DO I = 1, NGC
11332          IF (ABS(G0(I))<=ZERO) ZROOT = .TRUE.
11333        END DO
11334        IF (.NOT.ZROOT) GOTO 20
11335!       g has a zero at T. Look at g at T + (small increment).
11336!       TEMP1 = SIGN(HMING, H)
11337!       T0ST = T0ST + TEMP1
11338!       TEMP2 = TEMP1 / H
11339        TEMP2 = MAX(HMING/ABS(H),TENTH)
11340        TEMP1 = TEMP2*H
11341        T0ST = T0ST + TEMP1
11342        Y(1:N) = Y(1:N) + TEMP2*YH(1:N,2)
11343        CALL G(NEQ,T0ST,Y,NGC,G0)
11344        NGE = NGE + 1
11345        ZROOT = .FALSE.
11346        DO I = 1, NGC
11347          IF (ABS(G0(I))<=ZERO) ZROOT = .TRUE.
11348        END DO
11349        IF (.NOT.ZROOT) GOTO 20
11350!       g has a zero at T and also close to T. Take error return.
11351        IRT = -1
11352        RETURN
11353
1135420      CONTINUE
11355        RETURN
11356
1135730      CONTINUE
11358        IF (IRFND==0) GOTO 70
11359!       If a root was found on the previous step, evaluate G0 = g(T0ST).
11360        CALL DVINDY_CORE(T0ST,0,YH,NYH,Y,IFLAG)
11361        IF (BOUNDS) THEN
11362          DO I = 1, NDX
11363            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
11364            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
11365          END DO
11366        END IF
11367        CALL G(NEQ,T0ST,Y,NGC,G0)
11368        NGE = NGE + 1
11369        ZROOT = .FALSE.
11370        DO I = 1, NGC
11371          IF (ABS(G0(I))<=ZERO) ZROOT = .TRUE.
11372        END DO
11373        IF (.NOT.ZROOT) GOTO 70
11374!       g has a zero at T0ST. Look at g at T + (small increment).
11375        TEMP1 = SIGN(HMING,H)
11376        T0ST = T0ST + TEMP1
11377        IF ((T0ST-TN)*H<ZERO) GOTO 40
11378        TEMP2 = TEMP1/H
11379        Y(1:N) = Y(1:N) + TEMP2*YH(1:N,2)
11380        GOTO 50
1138140      CALL DVINDY_CORE(T0ST,0,YH,NYH,Y,IFLAG)
11382        IF (BOUNDS) THEN
11383          DO I = 1, NDX
11384            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
11385            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
11386          END DO
11387        END IF
1138850      CALL G(NEQ,T0ST,Y,NGC,G0)
11389        NGE = NGE + 1
11390        ZROOT = .FALSE.
11391        DO 60 I = 1, NGC
11392          IF (ABS(G0(I))>ZERO) GOTO 60
11393          JROOT(I) = 1
11394          ZROOT = .TRUE.
1139560      END DO
11396        IF (.NOT.ZROOT) GOTO 70
11397!       g has a zero at T0ST and also close to T0ST. Return root.
11398        IRT = 1
11399        RETURN
11400!       G0 has no zero components. Proceed to check relevant interval.
1140170      IF (ABS(TN-TLAST)<=ZERO) GOTO 130
11402
1140380      CONTINUE
11404!       Set T1 to TN or TOUTC, whichever comes first, and get g at T1.
11405        IF (ITASKC==2 .OR. ITASKC==3 .OR. ITASKC==5) GOTO 90
11406        IF ((TOUTC-TN)*H>=ZERO) GOTO 90
11407        T1 = TOUTC
11408        IF ((T1-T0ST)*H<=ZERO) GOTO 130
11409        CALL DVINDY_CORE(T1,0,YH,NYH,Y,IFLAG)
11410        IF (BOUNDS) THEN
11411          DO I = 1, NDX
11412            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
11413            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
11414          END DO
11415        END IF
11416        GOTO 100
1141790      T1 = TN
11418        DO I = 1, N
11419          Y(I) = YH(I,1)
11420        END DO
11421100     CALL G(NEQ,T1,Y,NGC,G1)
11422        NGE = NGE + 1
11423!       Call DVROOTS to search for root in interval from T0ST to T1.
11424        JFLAG = 0
11425110     CONTINUE
11426        CALL DVROOTS(NGC,HMING,JFLAG,T0ST,T1,G0,G1,GX,X)
11427        IF (JFLAG>1) GOTO 120
11428        CALL DVINDY_CORE(X,0,YH,NYH,Y,IFLAG)
11429        IF (BOUNDS) THEN
11430          DO I = 1, NDX
11431            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
11432            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
11433          END DO
11434        END IF
11435        CALL G(NEQ,X,Y,NGC,GX)
11436        NGE = NGE + 1
11437        GOTO 110
11438120     T0ST = X
11439        CALL DCOPY_F90(NGC,GX,1,G0,1)
11440        IF (JFLAG==4) GOTO 130
11441!       Found a root. Interpolate to X and return.
11442        CALL DVINDY_CORE(X,0,YH,NYH,Y,IFLAG)
11443        IF (BOUNDS) THEN
11444          DO I = 1, NDX
11445            Y(IDX(I)) = MAX(Y(IDX(I)),LB(I))
11446            Y(IDX(I)) = MIN(Y(IDX(I)),UB(I))
11447          END DO
11448        END IF
11449        IRT = 1
11450        RETURN
11451130     CONTINUE
11452        RETURN
11453
11454      END SUBROUTINE DVCHECK
11455!_______________________________________________________________________
11456
11457      SUBROUTINE DVROOTS(NG,HMIN,JFLAG,X0,X1,G0,G1,GX,X)
11458! ..
11459! Perform root finding for DVODE_F90.
11460! ..
11461! This is essentially subroutine DROOTS from LSODAR.
11462! ..
11463     IMPLICIT NONE
11464! ..
11465! .. Scalar Arguments ..
11466        KPP_REAL, INTENT (IN) :: HMIN
11467        KPP_REAL, INTENT (INOUT) :: X, X0, X1
11468        INTEGER, INTENT (INOUT) :: JFLAG
11469        INTEGER, INTENT (IN) :: NG
11470! ..
11471! .. Array Arguments ..
11472        KPP_REAL, INTENT (INOUT) :: G0(NG), G1(NG), GX(NG)
11473! ..
11474! .. Local Scalars ..
11475        KPP_REAL :: T2, TMAX
11476        INTEGER :: I, IMXOLD, NXLAST
11477        LOGICAL :: SGNCHG, XROOT, ZROOT
11478! ..
11479! .. Intrinsic Functions ..
11480        INTRINSIC ABS, SIGN
11481! ..
11482! This subroutine finds the leftmost root of a set of arbitrary
11483! functions gi(x) (i = 1,...,NG) in an interval (X0,X1). Only roots
11484! of odd multiplicity (i.e. changes of sign of the gi) are found.
11485! Here the sign of X1 - X0 is arbitrary, but is constant for a given
11486! problem, and 'leftmost' means nearest to X0.The values of the
11487! vector-valued function g(x) = (gi, i=1...NG) are communicated
11488! through the call sequence of DVROOTS. The method used is the
11489! Illinois algorithm.
11490
11491! Reference:
11492! Kathie L. Hiebert and Lawrence F. Shampine, Implicitly Defined
11493! Output Points for Solutions of ODEs, Sandia Report SAND/80-0180,
11494! February 1980.
11495
11496! Description of parameters.
11497
11498! NG     = number of functions gi, or the number of components of
11499!          the vector valued function g(x). Input only.
11500
11501! HMIN   = resolution parameter in X. Input only. When a root is
11502!          found, it is located only to within an error of HMIN in X.
11503!          Typically, HMIN should be set to something on the order of
11504!               100 * UROUND * MAX(ABS(X0),ABS(X1)),
11505!          where UROUND is the unit roundoff of the machine.
11506
11507! JFLAG  = integer flag for input and output communication.
11508
11509!          On input, set JFLAG = 0 on the first call for the problem,
11510!          and leave it unchanged until the problem is completed.
11511!          (The problem is completed when JFLAG >= 2 on return.)
11512
11513!          On output, JFLAG has the following values and meanings:
11514!          JFLAG = 1 means DVROOTS needs a value of g(x). Set GX = g(X)
11515!                    and call DVROOTS again.
11516!          JFLAG = 2 means a root has been found. The root is
11517!                    at X, and GX contains g(X). (Actually, X is the
11518!                    rightmost approximation to the root on an interval
11519!                    (X0,X1) of size HMIN or less.)
11520!          JFLAG = 3 means X = X1 is a root, with one or more of the gi
11521!                    being zero at X1 and no sign changes in (X0,X1).
11522!                    GX contains g(X) on output.
11523!          JFLAG = 4 means no roots (of odd multiplicity) were
11524!                    found in (X0,X1) (no sign changes).
11525
11526! X0,X1  = endpoints of the interval where roots are sought.
11527!          X1 and X0 are input when JFLAG = 0 (first call), and
11528!          must be left unchanged between calls until the problem is
11529!          completed. X0 and X1 must be distinct, but X1 - X0 may be
11530!          of either sign. However, the notion of 'left' and 'right'
11531!          will be used to mean nearer to X0 or X1, respectively.
11532!          When JFLAG >= 2 on return, X0 and X1 are output, and
11533!          are the endpoints of the relevant interval.
11534
11535! G0,G1  = arrays of length NG containing the vectors g(X0) and g(X1),
11536!          respectively. When JFLAG = 0, G0 and G1 are input and
11537!          none of the G0(i) should be zero.
11538!          When JFLAG >= 2 on return, G0 and G1 are output.
11539
11540! GX     = array of length NG containing g(X). GX is input
11541!          when JFLAG = 1, and output when JFLAG >= 2.
11542
11543! X      = independent variable value. Output only.
11544!          When JFLAG = 1 on output, X is the point at which g(x)
11545!          is to be evaluated and loaded into GX.
11546!          When JFLAG = 2 or 3, X is the root.
11547!          When JFLAG = 4, X is the right endpoint of the interval, X1.
11548
11549! JROOT  = integer array of length NG. Output only.
11550!          When JFLAG = 2 or 3, JROOT indicates which components
11551!          of g(x) have a root at X. JROOT(i) is 1 if the i-th
11552!          component has a root, and JROOT(i) = 0 otherwise.
11553! ..
11554! .. FIRST EXECUTABLE STATEMENT DVROOTS
11555! ..
11556        IF (JFLAG==1) GOTO 90
11557!       JFLAG /= 1. Check for change in sign of g or zero at X1.
11558        IMAX = 0
11559        TMAX = ZERO
11560        ZROOT = .FALSE.
11561        DO 20 I = 1, NG
11562          IF (ABS(G1(I))>ZERO) GOTO 10
11563          ZROOT = .TRUE.
11564          GOTO 20
11565!         At this point, G0(i) has been checked and cannot be zero.
1156610        IF (ABS(SIGN(ONE,G0(I))-SIGN(ONE,G1(I)))<=ZERO) GOTO 20
11567          T2 = ABS(G1(I)/(G1(I)-G0(I)))
11568          IF (T2<=TMAX) GOTO 20
11569          TMAX = T2
11570          IMAX = I
1157120      END DO
11572        IF (IMAX>0) GOTO 30
11573        SGNCHG = .FALSE.
11574        GOTO 40
1157530      SGNCHG = .TRUE.
1157640      IF (.NOT.SGNCHG) GOTO 200
11577!       There is a sign change. Find the first root in the interval.
11578        XROOT = .FALSE.
11579        NXLAST = 0
11580        LAST = 1
11581
11582!       Repeat until the first root in the interval is found. Loop point.
1158350      CONTINUE
11584        IF (XROOT) GOTO 170
11585        IF (NXLAST==LAST) GOTO 60
11586        ALPHA = ONE
11587        GOTO 80
1158860      IF (LAST==0) GOTO 70
11589        ALPHA = HALF*ALPHA
11590        GOTO 80
1159170      ALPHA = TWO*ALPHA
1159280      X2 = X1 - (X1-X0)*G1(IMAX)/(G1(IMAX)-ALPHA*G0(IMAX))
11593!       IF ((ABS(X2 - X0) < HMIN) .AND. (ABS(X1 - X0) > TEN * &
11594!       HMIN)) X2 = X0 + PT1 * (X1 - X0)
11595
11596!       If X2 is too close to X0 or X1, adjust it inward,
11597!       by a fractional distance that is between 0.1 and 0.5.
11598        IF (ABS(X2-X0)<HALF*HMIN) THEN
11599          FRACINT = ABS(X1-X0)/HMIN
11600          FRACSUB = TENTH
11601          IF (FRACINT<=FIVE) FRACSUB = HALF/FRACINT
11602          X2 = X0 + FRACSUB*(X1-X0)
11603        END IF
11604        IF (ABS(X1-X2)<HALF*HMIN) THEN
11605          FRACINT = ABS(X1-X0)/HMIN
11606          FRACSUB = TENTH
11607          IF (FRACINT<=FIVE) FRACSUB = HALF/FRACINT
11608          X2 = X1 - FRACSUB*(X1-X0)
11609        END IF
11610
11611        JFLAG = 1
11612        X = X2
11613!       Return to the calling routine to get a value of GX = g(X).
11614        RETURN
11615!       Check to see in which interval g changes sign.
1161690      IMXOLD = IMAX
11617        IMAX = 0
11618        TMAX = ZERO
11619        ZROOT = .FALSE.
11620        DO 110 I = 1, NG
11621          IF (ABS(GX(I))>ZERO) GOTO 100
11622          ZROOT = .TRUE.
11623          GOTO 110
11624!         Neither G0(i) nor GX(i) can be zero at this point.
11625100       IF (ABS(SIGN(ONE,G0(I))-SIGN(ONE,GX(I)))<=ZERO) GOTO 110
11626          T2 = ABS(GX(I)/(GX(I)-G0(I)))
11627          IF (T2<=TMAX) GOTO 110
11628          TMAX = T2
11629          IMAX = I
11630110     END DO
11631        IF (IMAX>0) GOTO 120
11632        SGNCHG = .FALSE.
11633        IMAX = IMXOLD
11634        GOTO 130
11635120     SGNCHG = .TRUE.
11636130     NXLAST = LAST
11637        IF (.NOT.SGNCHG) GOTO 140
11638!       Sign change between X0 and X2, so replace X1 with X2.
11639        X1 = X2
11640        CALL DCOPY_F90(NG,GX,1,G1,1)
11641        LAST = 1
11642        XROOT = .FALSE.
11643        GOTO 160
11644140     IF (.NOT.ZROOT) GOTO 150
11645!       Zero value at X2 and no sign change in (X0,X2), so X2 is a root.
11646        X1 = X2
11647        CALL DCOPY_F90(NG,GX,1,G1,1)
11648        XROOT = .TRUE.
11649        GOTO 160
11650!       No sign change between X0 and X2. Replace X0 with X2.
11651150     CONTINUE
11652        CALL DCOPY_F90(NG,GX,1,G0,1)
11653        X0 = X2
11654        LAST = 0
11655        XROOT = .FALSE.
11656160     IF (ABS(X1-X0)<=HMIN) XROOT = .TRUE.
11657        GOTO 50
11658
11659!       Return with X1 as the root. Set JROOT. Set X = X1 and GX = G1.
11660170     JFLAG = 2
11661        X = X1
11662        CALL DCOPY_F90(NG,G1,1,GX,1)
11663        DO 190 I = 1, NG
11664          JROOT(I) = 0
11665          IF (ABS(G1(I))>ZERO) GOTO 180
11666          JROOT(I) = 1
11667          GOTO 190
11668180       IF (ABS(SIGN(ONE,G0(I))-SIGN(ONE,G1(I)))>ZERO) JROOT(I) = 1
11669190     END DO
11670        RETURN
11671
11672!       No sign change in the interval. Check for zero at right endpoint.
11673200     IF (.NOT.ZROOT) GOTO 210
11674
11675!       Zero value at X1 and no sign change in (X0,X1). Return JFLAG = 3.
11676        X = X1
11677        CALL DCOPY_F90(NG,G1,1,GX,1)
11678        DO I = 1, NG
11679          JROOT(I) = 0
11680          IF (ABS(G1(I))<=ZERO) JROOT(I) = 1
11681        END DO
11682        JFLAG = 3
11683        RETURN
11684
11685!       No sign changes in this interval. Set X = X1, return JFLAG = 4.
11686210     CALL DCOPY_F90(NG,G1,1,GX,1)
11687        X = X1
11688        JFLAG = 4
11689        RETURN
11690
11691      END SUBROUTINE DVROOTS
11692!_______________________________________________________________________
11693
11694      SUBROUTINE DVNRDP(Y,IYDIM,NEQN,NQ)
11695! ..
11696! Retract the Nordsieck array (undo prediction).
11697! ..
11698     IMPLICIT NONE
11699! ..
11700! .. Scalar Arguments ..
11701        INTEGER :: IYDIM, NEQN, NQ
11702! ..
11703! .. Array Arguments ..
11704        KPP_REAL :: Y(*)
11705! ..
11706! .. Local Scalars ..
11707        INTEGER :: I, J, J1, J2
11708! ..
11709! .. FIRST EXECUTABLE STATEMENT DVNRDP
11710! ..
11711        DO J1 = 1, NQ
11712          DO J2 = J1, NQ
11713            J = (NQ+J1) - J2
11714            DO I = 1, NEQN
11715! Original:
11716!             Y(I,J) = Y(I,J) + Y(I,J+1)
11717              Y(I+(J-1)*IYDIM) = Y(I+(J-1)*IYDIM) + Y(I+J*IYDIM)
11718            END DO
11719          END DO
11720        END DO
11721        RETURN
11722
11723      END SUBROUTINE DVNRDP
11724!_______________________________________________________________________
11725
11726      SUBROUTINE DVNRDN(Y,IYDIM,NEQN,NQ)
11727! ..
11728! Apply the Nordsieck array (predict).
11729! ..
11730     IMPLICIT NONE
11731! ..
11732! .. Scalar Arguments ..
11733        INTEGER :: IYDIM, NEQN, NQ
11734! ..
11735! .. Array Arguments ..
11736        KPP_REAL :: Y(*)
11737! ..
11738! .. Local Scalars ..
11739        INTEGER :: I, J, J1, J2
11740! ..
11741! .. FIRST EXECUTABLE STATEMENT DVNRDN
11742! ..
11743        DO J1 = 1, NQ
11744          DO J2 = J1, NQ
11745            J = (NQ+J1) - J2
11746            DO I = 1, NEQN
11747! Original:
11748!             Y(I,J) = Y(I,J) - Y(I,J+1)
11749              Y(I+(J-1)*IYDIM) = Y(I+(J-1)*IYDIM) - Y(I+J*IYDIM)
11750            END DO
11751          END DO
11752        END DO
11753        RETURN
11754
11755      END SUBROUTINE DVNRDN
11756!_______________________________________________________________________
11757
11758      SUBROUTINE DVNRDS(Y,IYDIM,NEQN,L,RH)
11759! ..
11760! Scale the Nordsieck array.
11761! ..
11762     IMPLICIT NONE
11763! ..
11764! .. Scalar Arguments ..
11765        KPP_REAL :: RH
11766        INTEGER :: IYDIM, L, NEQN
11767! ..
11768! .. Array Arguments ..
11769        KPP_REAL :: Y(*)
11770! ..
11771! .. Local Scalars ..
11772        KPP_REAL :: R1
11773        INTEGER :: I, J
11774! ..
11775! .. FIRST EXECUTABLE STATEMENT DVNRDS
11776! ..
11777        R1 = ONE
11778        DO J = 2, L
11779          R1 = R1*RH
11780          DO I = 1, NEQN
11781! Original:
11782!           Y(I,J) = Y(I,J)*R1
11783            Y(I+(J-1)*IYDIM) = Y(I+(J-1)*IYDIM)*R1
11784          END DO
11785        END DO
11786        RETURN
11787
11788      END SUBROUTINE DVNRDS
11789!_______________________________________________________________________
11790
11791      SUBROUTINE RELEASE_ARRAYS
11792! ..
11793! Deallocate any allocated arrays and determine how much storage was
11794! used (not called by DVODE_F90).
11795! ..
11796     IMPLICIT NONE
11797! ..
11798! .. Local Scalars ..
11799        INTEGER :: IER, II, IR
11800        CHARACTER (80) :: MSG
11801! ..
11802! .. Intrinsic Functions ..
11803        INTRINSIC ALLOCATED, SIZE
11804! ..
11805!_______________________________________________________________________
11806! *****MA48 build change point. Insert these statements.
11807!     INTEGER INFO
11808!     INTEGER ISIZE
11809!     COMMON /MA48SIZE/ ISIZE
11810!_______________________________________________________________________
11811! ..
11812! .. FIRST EXECUTABLE STATEMENT RELEASE_ARRAYS
11813! ..
11814        IR = 0
11815        IF (ALLOCATED(ACOR)) THEN
11816          IR = IR + SIZE(ACOR)
11817          DEALLOCATE (ACOR,STAT=IER)
11818          CALL CHECK_STAT(IER,880)
11819        END IF
11820        IF (ALLOCATED(CSCALEX)) THEN
11821          IR = IR + SIZE(CSCALEX) + SIZE(RSCALEX) + SIZE(WSCALEX)
11822          DEALLOCATE (CSCALEX,RSCALEX,WSCALEX,STAT=IER)
11823          CALL CHECK_STAT(IER,890)
11824        END IF
11825        IF (ALLOCATED(DTEMP)) THEN
11826          IR = IR + SIZE(DTEMP)
11827          DEALLOCATE (DTEMP,STAT=IER)
11828          CALL CHECK_STAT(IER,900)
11829        END IF
11830        IF (ALLOCATED(EWT)) THEN
11831          IR = IR + SIZE(EWT)
11832          DEALLOCATE (EWT,STAT=IER)
11833          CALL CHECK_STAT(IER,910)
11834        END IF
11835        IF (ALLOCATED(FACDS)) THEN
11836          IR = IR + SIZE(FACDS)
11837          DEALLOCATE (FACDS,STAT=IER)
11838          CALL CHECK_STAT(IER,920)
11839        END IF
11840        IF (ALLOCATED(FPTEMP)) THEN
11841          IR = IR + SIZE(FPTEMP)
11842          DEALLOCATE (FPTEMP,STAT=IER)
11843          CALL CHECK_STAT(IER,930)
11844        END IF
11845        IF (ALLOCATED(FTEMP)) THEN
11846          IR = IR + SIZE(FTEMP)
11847          DEALLOCATE (FTEMP,STAT=IER)
11848          CALL CHECK_STAT(IER,940)
11849        END IF
11850        IF (ALLOCATED(FTEMP1)) THEN
11851          IR = IR + SIZE(FTEMP1)
11852          DEALLOCATE (FTEMP1,STAT=IER)
11853          CALL CHECK_STAT(IER,950)
11854        END IF
11855        IF (ALLOCATED(G0)) THEN
11856          IR = IR + SIZE(G0)
11857          DEALLOCATE (G0,STAT=IER)
11858          CALL CHECK_STAT(IER,960)
11859        END IF
11860        IF (ALLOCATED(G1)) THEN
11861          IR = IR + SIZE(G1)
11862          DEALLOCATE (G1,STAT=IER)
11863          CALL CHECK_STAT(IER,970)
11864        END IF
11865        IF (ALLOCATED(GX)) THEN
11866          IR = IR + SIZE(GX)
11867          DEALLOCATE (GX,STAT=IER)
11868          CALL CHECK_STAT(IER,980)
11869        END IF
11870        IF (ALLOCATED(JMAT)) THEN
11871          IR = IR + SIZE(JMAT)
11872          DEALLOCATE (JMAT,STAT=IER)
11873          CALL CHECK_STAT(IER,990)
11874        END IF
11875        IF (ALLOCATED(LB)) THEN
11876          IR = IR + SIZE(LB)
11877          DEALLOCATE (LB,STAT=IER)
11878          CALL CHECK_STAT(IER,1000)
11879        END IF
11880        IF (ALLOCATED(UB)) THEN
11881          IR = IR + SIZE(UB)
11882          DEALLOCATE (UB,STAT=IER)
11883          CALL CHECK_STAT(IER,1000)
11884        END IF
11885        IF (ALLOCATED(PMAT)) THEN
11886          IR = IR + SIZE(PMAT)
11887          DEALLOCATE (PMAT,STAT=IER)
11888          CALL CHECK_STAT(IER,1010)
11889        END IF
11890        IF (ALLOCATED(RWORK)) THEN
11891          IR = IR + SIZE(RWORK)
11892          DEALLOCATE (RWORK,STAT=IER)
11893          CALL CHECK_STAT(IER,1020)
11894        END IF
11895        IF (ALLOCATED(SAVF)) THEN
11896          IR = IR + SIZE(SAVF)
11897          DEALLOCATE (SAVF,STAT=IER)
11898          CALL CHECK_STAT(IER,1030)
11899        END IF
11900        IF (ALLOCATED(YMAX)) THEN
11901          IR = IR + SIZE(YMAX)
11902          DEALLOCATE (YMAX,STAT=IER)
11903          CALL CHECK_STAT(IER,1040)
11904        END IF
11905        IF (ALLOCATED(WM)) THEN
11906          IR = IR + SIZE(WM)
11907          DEALLOCATE (WM,STAT=IER)
11908          CALL CHECK_STAT(IER,1050)
11909        END IF
11910        IF (ALLOCATED(YHNQP2)) THEN
11911          IR = IR + SIZE(YHNQP2)
11912          DEALLOCATE (YHNQP2,STAT=IER)
11913          CALL CHECK_STAT(IER,1060)
11914        END IF
11915        IF (ALLOCATED(YHTEMP)) THEN
11916          IR = IR + SIZE(YHTEMP)
11917          DEALLOCATE (YHTEMP,STAT=IER)
11918          CALL CHECK_STAT(IER,1070)
11919        END IF
11920        IF (ALLOCATED(YMAX)) THEN
11921          IR = IR + SIZE(YMAX)
11922          DEALLOCATE (YMAX,STAT=IER)
11923          CALL CHECK_STAT(IER,1080)
11924        END IF
11925        IF (ALLOCATED(YNNEG)) THEN
11926          IR = IR + SIZE(YNNEG)
11927          DEALLOCATE (YNNEG,STAT=IER)
11928          CALL CHECK_STAT(IER,1090)
11929        END IF
11930        IF (ALLOCATED(YSCALEDS)) THEN
11931          IR = IR + SIZE(YSCALEDS)
11932          DEALLOCATE (YSCALEDS,STAT=IER)
11933          CALL CHECK_STAT(IER,1100)
11934        END IF
11935        IF (ALLOCATED(YTEMP)) THEN
11936          IR = IR + SIZE(YTEMP)
11937          DEALLOCATE (YTEMP,STAT=IER)
11938          CALL CHECK_STAT(IER,1110)
11939        END IF
11940        IF (ALLOCATED(WKDS)) THEN
11941          IR = IR + SIZE(WKDS)
11942          DEALLOCATE (WKDS,STAT=IER)
11943          CALL CHECK_STAT(IER,1120)
11944        END IF
11945        II = 0
11946        IF (ALLOCATED(BIGP)) THEN
11947          II = II + SIZE(BIGP)
11948          DEALLOCATE (BIGP,STAT=IER)
11949          CALL CHECK_STAT(IER,1130)
11950        END IF
11951        IF (ALLOCATED(BJGP)) THEN
11952          II = II + SIZE(BJGP)
11953          DEALLOCATE (BJGP,STAT=IER)
11954          CALL CHECK_STAT(IER,1140)
11955        END IF
11956        IF (ALLOCATED(IA)) THEN
11957          II = II + SIZE(IA)
11958          DEALLOCATE (IA,STAT=IER)
11959          CALL CHECK_STAT(IER,1150)
11960        END IF
11961        IF (ALLOCATED(IAB)) THEN
11962          II = II + SIZE(IAB)
11963          DEALLOCATE (IAB,STAT=IER)
11964          CALL CHECK_STAT(IER,1160)
11965        END IF
11966        IF (ALLOCATED(IAN)) THEN
11967          II = II + SIZE(IAN)
11968          DEALLOCATE (IAN,STAT=IER)
11969          CALL CHECK_STAT(IER,1170)
11970        END IF
11971        IF (ALLOCATED(ICN)) THEN
11972          II = II + SIZE(ICN)
11973          DEALLOCATE (ICN,STAT=IER)
11974          CALL CHECK_STAT(IER,1180)
11975        END IF
11976        IF (ALLOCATED(IDX)) THEN
11977          II = II + SIZE(IDX)
11978          DEALLOCATE (IDX,STAT=IER)
11979          CALL CHECK_STAT(IER,1190)
11980        END IF
11981        IF (ALLOCATED(IGP)) THEN
11982          II = II + SIZE(IGP)
11983          DEALLOCATE (IGP,STAT=IER)
11984          CALL CHECK_STAT(IER,1200)
11985        END IF
11986        IF (ALLOCATED(IKEEP28)) THEN
11987          II = II + SIZE(IKEEP28,1)*SIZE(IKEEP28,2)
11988          DEALLOCATE (IKEEP28,STAT=IER)
11989          CALL CHECK_STAT(IER,1210)
11990        END IF
11991        IF (ALLOCATED(INDCOLDS)) THEN
11992          II = II + SIZE(INDCOLDS)
11993          DEALLOCATE (INDCOLDS,STAT=IER)
11994          CALL CHECK_STAT(IER,1220)
11995        END IF
11996        IF (ALLOCATED(INDROWDS)) THEN
11997
11998          II = II + SIZE(INDROWDS)
11999          DEALLOCATE (INDROWDS,STAT=IER)
12000          CALL CHECK_STAT(IER,1230)
12001        END IF
12002        IF (ALLOCATED(IOPTDS)) THEN
12003          II = II + SIZE(IOPTDS)
12004          DEALLOCATE (IOPTDS,STAT=IER)
12005          CALL CHECK_STAT(IER,1240)
12006        END IF
12007        IF (ALLOCATED(IPNTRDS)) THEN
12008          II = II + SIZE(IPNTRDS)
12009          DEALLOCATE (IPNTRDS,STAT=IER)
12010          CALL CHECK_STAT(IER,1250)
12011        END IF
12012        IF (ALLOCATED(IWADS)) THEN
12013          II = II + SIZE(IWADS)
12014          DEALLOCATE (IWADS,STAT=IER)
12015          CALL CHECK_STAT(IER,1260)
12016        END IF
12017        IF (ALLOCATED(IWKDS)) THEN
12018          II = II + SIZE(IWKDS)
12019          DEALLOCATE (IWKDS,STAT=IER)
12020          CALL CHECK_STAT(IER,1270)
12021        END IF
12022        IF (ALLOCATED(IWORK)) THEN
12023          II = II + SIZE(IWORK)
12024          DEALLOCATE (IWORK,STAT=IER)
12025          CALL CHECK_STAT(IER,1280)
12026        END IF
12027        IF (ALLOCATED(IW28)) THEN
12028          II = II + SIZE(IW28,1)*SIZE(IW28,2)
12029          DEALLOCATE (IW28,STAT=IER)
12030          CALL CHECK_STAT(IER,1290)
12031        END IF
12032        IF (ALLOCATED(JA)) THEN
12033          II = II + SIZE(JA)
12034          DEALLOCATE (JA,STAT=IER)
12035          CALL CHECK_STAT(IER,1300)
12036        END IF
12037        IF (ALLOCATED(JAB)) THEN
12038          II = II + SIZE(JAB)
12039          DEALLOCATE (JAB,STAT=IER)
12040          CALL CHECK_STAT(IER,1310)
12041        END IF
12042        IF (ALLOCATED(JAN)) THEN
12043          II = II + SIZE(JAN)
12044          DEALLOCATE (JAN,STAT=IER)
12045          CALL CHECK_STAT(IER,1320)
12046        END IF
12047        IF (ALLOCATED(JATEMP)) THEN
12048          II = II + SIZE(JATEMP)
12049          DEALLOCATE (JATEMP,STAT=IER)
12050          CALL CHECK_STAT(IER,1330)
12051        END IF
12052        IF (ALLOCATED(JGP)) THEN
12053          II = II + SIZE(JGP)
12054          DEALLOCATE (JGP,STAT=IER)
12055          CALL CHECK_STAT(IER,1340)
12056        END IF
12057        IF (ALLOCATED(JPNTRDS)) THEN
12058          II = II + SIZE(JPNTRDS)
12059          DEALLOCATE (JPNTRDS,STAT=IER)
12060          CALL CHECK_STAT(IER,1350)
12061        END IF
12062        IF (ALLOCATED(JROOT)) THEN
12063          II = II + SIZE(JROOT)
12064          DEALLOCATE (JROOT,STAT=IER)
12065          CALL CHECK_STAT(IER,1360)
12066        END IF
12067        IF (ALLOCATED(JVECT)) THEN
12068          II = II + SIZE(JVECT)
12069          DEALLOCATE (JVECT,STAT=IER)
12070          CALL CHECK_STAT(IER,1370)
12071        END IF
12072        IF (ALLOCATED(NGRPDS)) THEN
12073          II = II + SIZE(NGRPDS)
12074          DEALLOCATE (NGRPDS,STAT=IER)
12075          CALL CHECK_STAT(IER,1380)
12076        END IF
12077        IF (ALLOCATED(SUBDS)) THEN
12078          II = II + SIZE(SUBDS)
12079          DEALLOCATE (SUBDS,STAT=IER)
12080          CALL CHECK_STAT(IER,1390)
12081        END IF
12082        IF (ALLOCATED(SUPDS)) THEN
12083          II = II + SIZE(SUPDS)
12084          DEALLOCATE (SUPDS,STAT=IER)
12085          CALL CHECK_STAT(IER,1400)
12086        END IF
12087!_______________________________________________________________________
12088! *****MA48 build change point. Insert these statements.
12089!       IF (MA48_WAS_USED) THEN
12090!          CALL MA48_FINALIZE(FACTORS,CONTROL,INFO)
12091!          IF (INFO /= 0) THEN
12092!             MSG = 'The call to MA48_FINALIZE FAILED.'
12093!             CALL XERRDV(MSG,1740,1,1,II,0,0,ZERO,ZERO)
12094!          END IF
12095!          MSG = 'Size of MA48 deallocated arrays (I1) = '
12096!          CALL XERRDV(MSG,1750,1,1,ISIZE,0,0,ZERO,ZERO)
12097!       END IF
12098!_______________________________________________________________________
12099
12100!       Print the amount of storage used.
12101        MSG = 'I1 = Total length of REAL arrays used.'
12102        CALL XERRDV(MSG,1760,1,1,IR,0,0,ZERO,ZERO)
12103        MSG = 'I1 = Total length of INTEGER arrays used.'
12104        CALL XERRDV(MSG,1760,1,1,II,0,0,ZERO,ZERO)
12105
12106!       In case DVODE_F90 is subsequently called:
12107        OPTS_CALLED = .FALSE.
12108        RETURN
12109
12110      END SUBROUTINE RELEASE_ARRAYS
12111! End of DVODE_F90 subroutines
12112!_______________________________________________________________________
12113
12114! Beginning of LINPACK and BLAS subroutines
12115      SUBROUTINE DGEFA_F90(A,LDA,N,IPVT,INFO)
12116! ..
12117! Factor a matrix using Gaussian elimination.
12118! ..
12119!     DGEFA_F90 factors a real(wp) matrix by Gaussian elimination.
12120!     DGEFA_F90 is usually called by DGECO, but it can be called
12121!     directly with a saving in time if RCOND is not needed.
12122!     (Time for DGECO) = (1 + 9/N)*(Time for DGEFA_F90).
12123!     On Entry
12124!        A       REAL(KIND=WP)(LDA, N)
12125!                the matrix to be factored.
12126!        LDA     INTEGER
12127!                the leading dimension of the array A.
12128!        N       INTEGER
12129!                the order of the matrix A.
12130!     On Return
12131!        A       an upper triangular matrix and the multipliers
12132!                which were used to obtain it.
12133!                The factorization can be written A = L*U where
12134!                L is a product of permutation and unit lower
12135!                triangular matrices and U is upper triangular.
12136!        IPVT    INTEGER(N)
12137!                an integer vector of pivot indices.
12138!        INFO    INTEGER
12139!                = 0  normal value.
12140!                = K  if U(K,K) == 0.0. This is not an error
12141!                     condition for this subroutine, but it does
12142!                     indicate that DGESL_F90 or DGEDI will divide
12143!                     by zero if called. Use RCOND in DGECO for a
12144!                     reliable indication of singularity.
12145! ..
12146     IMPLICIT NONE
12147! ..
12148! .. Scalar Arguments ..
12149        INTEGER, INTENT (INOUT) :: INFO
12150        INTEGER, INTENT (IN) :: LDA, N
12151! ..
12152! .. Array Arguments ..
12153        KPP_REAL, INTENT (INOUT) :: A(LDA,*)
12154        INTEGER, INTENT (INOUT) :: IPVT(*)
12155! ..
12156! .. Local Scalars ..
12157        KPP_REAL :: T
12158        INTEGER :: J, K, KP1, L, NM1
12159! ..
12160! .. Intrinsic Functions ..
12161        INTRINSIC ABS
12162! ..
12163! .. FIRST EXECUTABLE STATEMENT DGEFA_F90
12164! ..
12165        INFO = 0
12166        NM1 = N - 1
12167        IF (NM1<1) GOTO 50
12168        DO K = 1, NM1
12169          KP1 = K + 1
12170
12171!         Find L = pivot index.
12172
12173! Original:
12174!         L = IDAMAX_F90(N-K+1,A(K,K),1) + K - 1
12175          L = IDAMAX_F90(N-K+1,A(K:N,K),1) + K - 1
12176          IPVT(K) = L
12177
12178!         Zero pivot implies this column already triangularized.
12179
12180!         IF (A(L, K) == ZERO) GOTO 40
12181          IF (ABS(A(L,K))<=ZERO) GOTO 30
12182
12183!         Interchange if necessary.
12184
12185          IF (L==K) GOTO 10
12186          T = A(L,K)
12187          A(L,K) = A(K,K)
12188          A(K,K) = T
1218910        CONTINUE
12190
12191!         Compute multipliers.
12192
12193          T = -ONE/A(K,K)
12194! Original:         
12195!         CALL DSCAL_F90(N-K,T,A(K+1,K),1)         
12196          CALL DSCAL_F90(N-K,T,A(K+1:N,K),1)
12197
12198!         Row elimination with column indexing.
12199
12200          DO J = KP1, N
12201            T = A(L,J)
12202            IF (L==K) GOTO 20
12203            A(L,J) = A(K,J)
12204            A(K,J) = T
1220520          CONTINUE
12206! Original:           
12207!           CALL DAXPY_F90(N-K,T,A(K+1,K),1,A(K+1,J),1)
12208            CALL DAXPY_F90(N-K,T,A(K+1:N,K),1,A(K+1:N,J),1)
12209          END DO
12210          GOTO 40
1221130        CONTINUE
12212          INFO = K
1221340        CONTINUE
12214        END DO
1221550      CONTINUE
12216        IPVT(N) = N
12217!       IF (A(N, N) == ZERO) INFO = N
12218        IF (ABS(A(N,N))<=ZERO) INFO = N
12219        RETURN
12220
12221      END SUBROUTINE DGEFA_F90
12222!_______________________________________________________________________
12223
12224      SUBROUTINE DGESL_F90(A,LDA,N,IPVT,B,JOB)
12225! ..
12226! Solve the real system A*X=B or TRANS(A)*X=B using the factors
12227! computed by DGECO or DGEFA_F90.
12228! ..
12229!     DGESL_F90 solves the real(wp) system
12230!     A * X = B or TRANS(A) * X = B
12231!     using the factors computed by DGECO or DGEFA_F90.
12232!     On Entry
12233!        A       REAL(KIND=WP)(LDA, N)
12234!                the output from DGECO or DGEFA_F90.
12235!        LDA     INTEGER
12236!                the leading dimension of the array A.
12237!        N       INTEGER
12238!                the order of the matrix A.
12239!        IPVT    INTEGER(N)
12240!                the pivot vector from DGECO or DGEFA_F90.
12241!        B       REAL(KIND=WP)(N)
12242!                the right hand side vector.
12243!        JOB     INTEGER
12244!                = 0         to solve A*X = B,
12245
12246!                = nonzero   to solve TRANS(A)*X = B where
12247!                            TRANS(A)is the transpose.
12248!     On Return
12249!        B       the solution vector X.
12250!     Error Condition
12251!        A division by zero will occur if the input factor contains a
12252!        zero on the diagonal. Technically this indicates singularity
12253!        but it is often caused by improper arguments or improper
12254!        setting of LDA. It will not occur if the subroutines are
12255!        called correctly and if DGECO has set RCOND > 0.0 or
12256!        DGEFA_F90 has set INFO == 0.
12257!     To compute INVERSE(A) * C where C is a matrix
12258!     with P columns
12259!           CALL DGECO(A,LDA,N,IPVT,RCOND,Z)
12260!           IF (RCOND is too small) GOTO
12261!           DO J = 1, P
12262!              CALL DGESL_F90(A,LDA,N,IPVT,C(1,J),0)
12263!           END DO
12264! ..
12265     IMPLICIT NONE
12266! ..
12267! .. Scalar Arguments ..
12268        INTEGER, INTENT (IN) :: JOB, LDA, N
12269! ..
12270! .. Array Arguments ..
12271        KPP_REAL, INTENT (INOUT) :: A(LDA,*), B(*)
12272        INTEGER, INTENT (INOUT) :: IPVT(*)
12273! ..
12274! .. Local Scalars ..
12275        KPP_REAL :: T
12276        INTEGER :: K, KB, L, NM1
12277! ..
12278! .. FIRST EXECUTABLE STATEMENT DGESL_F90
12279! ..
12280        NM1 = N - 1
12281        IF (JOB/=0) GOTO 30
12282
12283!       JOB = 0, solve A*X = B.
12284!       First solve L*Y = B.
12285
12286        IF (NM1<1) GOTO 20
12287        DO K = 1, NM1
12288          L = IPVT(K)
12289          T = B(L)
12290          IF (L==K) GOTO 10
12291          B(L) = B(K)
12292          B(K) = T
1229310        CONTINUE
12294! Original:
12295!         CALL DAXPY_F90(N-K,T,A(K+1,K),1,B(K+1),1)
12296          CALL DAXPY_F90(N-K,T,A(K+1:N,K),1,B(K+1:N),1)
12297        END DO
1229820      CONTINUE
12299
12300!       Now solve U*X = Y.
12301
12302        DO KB = 1, N
12303          K = N + 1 - KB
12304          B(K) = B(K)/A(K,K)
12305          T = -B(K)
12306! Original:
12307!         CALL DAXPY_F90(K-1,T,A(1,K),1,B(1),1)
12308          CALL DAXPY_F90(K-1,T,A(1:K-1,K),1,B(1:K-1),1)
12309        END DO
12310        GOTO 60
1231130      CONTINUE
12312
12313!       JOB /= 0, solve TRANS(A)*X = B.
12314!       First solve TRANS(U)*Y = B.
12315
12316        DO K = 1, N
12317          T = DDOT_F90(K-1,A(1,K),1,B(1),1)
12318          B(K) = (B(K)-T)/A(K,K)
12319        END DO
12320
12321!       Now solve TRANS(L)*X = Y.
12322
12323        IF (NM1<1) GOTO 50
12324        DO KB = 1, NM1
12325          K = N - KB
12326          B(K) = B(K) + DDOT_F90(N-K,A(K+1,K),1,B(K+1),1)
12327          L = IPVT(K)
12328          IF (L==K) GOTO 40
12329          T = B(L)
12330          B(L) = B(K)
12331          B(K) = T
1233240        CONTINUE
12333        END DO
1233450      CONTINUE
1233560      CONTINUE
12336        RETURN
12337
12338      END SUBROUTINE DGESL_F90
12339!_______________________________________________________________________
12340
12341      SUBROUTINE DGBFA_F90(ABD,LDA,N,ML,MU,IPVT,INFO)
12342! ..
12343! Factor a banded matrix using Gaussian elimination.
12344! ..
12345!     DGBFA_F90 factors a real(wp) band matrix by elimination.
12346!     DGBFA_F90 is usually called by DGBCO, but it can be called
12347!     directly with a saving in time if RCOND is not needed.
12348!     On Entry
12349!        ABD     REAL(KIND=WP)(LDA, N)
12350!                contains the matrix in band storage. The columns
12351!                of the matrix are stored in the columns of ABD and
12352!                the diagonals of the matrix are stored in rows
12353!                ML+1 through 2*ML+MU+1 of ABD.
12354!                See the comments below for details.
12355!        LDA     INTEGER
12356!                the leading dimension of the array ABD.
12357!                LDA must be >= 2*ML + MU + 1.
12358!        N       INTEGER
12359!                the order of the original matrix.
12360!        ML      INTEGER
12361!                number of diagonals below the main diagonal.
12362!                0 <= ML < N.
12363!        MU      INTEGER
12364!                number of diagonals above the main diagonal.
12365!                0 <= MU < N.
12366!                More efficient if ML <= MU.
12367!     On Return
12368!        ABD     an upper triangular matrix in band storage and
12369!                the multipliers which were used to obtain it.
12370!                The factorization can be written A = L*U where
12371!                L is a product of permutation and unit lower
12372!                triangular matrices and U is upper triangular.
12373!        IPVT    INTEGER(N)
12374!                an integer vector of pivot indices.
12375!        INFO    INTEGER
12376!                = 0  normal value.
12377!                = K  if U(K,K) == 0.0. This is not an error
12378!                     condition for this subroutine, but it does
12379!                     indicate that DGBSL_F90 will divide by zero
12380!                     if called. Use RCOND in DGBCO for a reliable
12381!                     indication of singularity.
12382!     Band Storage
12383!           If A is a band matrix, the following program segment
12384!           will set up the input.
12385!                   ML = (band width below the diagonal)
12386!                   MU = (band width above the diagonal)
12387!                   M = ML + MU + 1
12388!                   DO J = 1, N
12389!                      I1 = MAX(1, J-MU)
12390!                      I2 = MIN(N, J+ML)
12391!                      DO 10 I = I1, I2
12392!                         K = I - J + M
12393!                         ABD(K,J) = A(I,J)
12394!                      END DO
12395!                   END DO
12396!           This uses rows ML+1 through 2*ML+MU+1 of ABD.
12397!           In addition, the first ML rows in ABD are used for
12398!           elements generated during the triangularization.
12399!           The total number of rows needed in ABD is 2*ML+MU+1.
12400!           The ML+MU by ML+MU upper left triangle and the
12401!           ML by ML lower right triangle are not referenced.
12402! ..
12403     IMPLICIT NONE
12404! ..
12405! .. Scalar Arguments ..
12406        INTEGER, INTENT (INOUT) :: INFO
12407        INTEGER, INTENT (IN) :: LDA, ML, MU, N
12408! ..
12409! .. Array Arguments ..
12410        KPP_REAL, INTENT (INOUT) :: ABD(LDA,*)
12411        INTEGER, INTENT (INOUT) :: IPVT(*)
12412! ..
12413! .. Local Scalars ..
12414        KPP_REAL :: T
12415        INTEGER :: I0, J, J0, J1, JU, JZ, K, KP1, L, LM, M, MM, NM1
12416! ..
12417! .. Intrinsic Functions ..
12418        INTRINSIC ABS, MAX, MIN
12419! ..
12420! .. FIRST EXECUTABLE STATEMENT DGBFA_F90
12421! ..
12422        M = ML + MU + 1
12423        INFO = 0
12424
12425!       Zero initial fill-in columns.
12426
12427        J0 = MU + 2
12428        J1 = MIN(N,M) - 1
12429        IF (J1<J0) GOTO 10
12430        DO JZ = J0, J1
12431          I0 = M + 1 - JZ
12432          ABD(I0:ML,JZ) = ZERO
12433        END DO
1243410      CONTINUE
12435        JZ = J1
12436        JU = 0
12437
12438!       Gaussian elimination with partial pivoting.
12439
12440        NM1 = N - 1
12441        IF (NM1<1) GOTO 80
12442        DO K = 1, NM1
12443          KP1 = K + 1
12444
12445!         Zero next fill-in column.
12446
12447          JZ = JZ + 1
12448          IF (JZ>N) GOTO 20
12449          IF (ML<1) GOTO 20
12450          ABD(1:ML,JZ) = ZERO
1245120        CONTINUE
12452
12453!         Find L = pivot index.
12454
12455          LM = MIN(ML,N-K)
12456! Original:
12457!         L = IDAMAX_F90(LM+1,ABD(M,K),1) + M - 1
12458          L = IDAMAX_F90(LM+1,ABD(M:M+LM,K),1) + M - 1
12459
12460          IPVT(K) = L + K - M
12461
12462!         Zero pivot implies this column already triangularized.
12463
12464!         IF (ABD(L, K) == ZERO) GOTO 100
12465          IF (ABS(ABD(L,K))<=ZERO) GOTO 60
12466
12467!         Interchange if necessary.
12468
12469          IF (L==M) GOTO 30
12470          T = ABD(L,K)
12471          ABD(L,K) = ABD(M,K)
12472          ABD(M,K) = T
1247330        CONTINUE
12474
12475!         Compute multipliers.
12476
12477          T = -ONE/ABD(M,K)
12478! Original:
12479!         CALL DSCAL_F90(LM,T,ABD(M+1,K),1)
12480          CALL DSCAL_F90(LM,T,ABD(M+1:M+LM,K),1)
12481
12482!         Row elimination with column indexing.
12483
12484          JU = MIN(MAX(JU,MU+IPVT(K)),N)
12485          MM = M
12486          IF (JU<KP1) GOTO 50
12487          DO J = KP1, JU
12488            L = L - 1
12489            MM = MM - 1
12490            T = ABD(L,J)
12491            IF (L==MM) GOTO 40
12492            ABD(L,J) = ABD(MM,J)
12493            ABD(MM,J) = T
1249440          CONTINUE
12495! Original:
12496!           CALL DAXPY_F90(LM,T,ABD(M+1,K),1,ABD(MM+1,J),1)
12497            CALL DAXPY_F90(LM,T,ABD(M+1:M+LM,K),1,ABD(MM+1:M+LM,J),1)
12498          END DO
1249950        CONTINUE
12500          GOTO 70
1250160        CONTINUE
12502          INFO = K
1250370        CONTINUE
12504        END DO
1250580      CONTINUE
12506        IPVT(N) = N
12507!       IF (ABD(M, N) == ZERO) INFO = N
12508        IF (ABS(ABD(M,N))<=ZERO) INFO = N
12509        RETURN
12510
12511      END SUBROUTINE DGBFA_F90
12512!_______________________________________________________________________
12513
12514      SUBROUTINE DGBSL_F90(ABD,LDA,N,ML,MU,IPVT,B,JOB)
12515! ..
12516! Solve the real band system A*X=B or TRANS(A)*X=B using the factors
12517! computed by DGBCO or DGBFA_F90.
12518! ..
12519!     DGBSL_F90 solves the real(wp) band system
12520!     A * X = B or TRANS(A) * X = B
12521!     using the factors computed by DGBCO or DGBFA_F90.
12522!     On Entry
12523!        ABD     REAL(KIND=WP)(LDA, N)
12524!                the output from DGBCO or DGBFA_F90.
12525!        LDA     INTEGER
12526!                the leading dimension of the array ABD.
12527!        N       INTEGER
12528!                the order of the original matrix.
12529!        ML      INTEGER
12530!                number of diagonals below the main diagonal.
12531!        MU      INTEGER
12532!                number of diagonals above the main diagonal.
12533!        IPVT    INTEGER(N)
12534!                the pivot vector from DGBCO or DGBFA_F90.
12535!        B       REAL(KIND=WP)(N)
12536!                the right hand side vector.
12537!        JOB     INTEGER
12538!                = 0         to solve A*X = B,
12539!                = nonzero   to solve TRANS(A)*X = B, where
12540!                            TRANS(A) is the transpose.
12541!     On Return
12542!        B       the solution vector X.
12543!     Error Condition
12544!        A division by zero will occur if the input factor contains a
12545!        zero on the diagonal. Technically this indicates singularity
12546!        but it is often caused by improper arguments or improper
12547!        setting of LDA. It will not occur if the subroutines are
12548!        called correctly and if DGBCO has set RCOND > 0.0
12549!        or DGBFA_F90 has set INFO == 0 .
12550!     To compute INVERSE(A) * C where C is a matrix
12551!     with P columns
12552!           CALL DGBCO(ABD,LDA,N,ML,MU,IPVT,RCOND,Z)
12553!           IF (RCOND is too small) GOTO ...
12554!           DO J = 1, P
12555!              CALL DGBSL_F90(ABD,LDA,N,ML,MU,IPVT,C(1,J),0)
12556!           END DO
12557! ..
12558     IMPLICIT NONE
12559! ..
12560! .. Scalar Arguments ..
12561        INTEGER, INTENT (IN) :: JOB, LDA, ML, MU, N
12562! ..
12563! .. Array Arguments ..
12564        KPP_REAL, INTENT (INOUT) :: ABD(LDA,*), B(*)
12565        INTEGER, INTENT (INOUT) :: IPVT(*)
12566! ..
12567! .. Local Scalars ..
12568        KPP_REAL :: T
12569        INTEGER :: K, KB, L, LA, LB, LM, M, NM1
12570! ..
12571! .. Intrinsic Functions ..
12572        INTRINSIC MIN
12573! ..
12574! .. FIRST EXECUTABLE STATEMENT DGBSL_F90
12575! ..
12576        M = MU + ML + 1
12577        NM1 = N - 1
12578        IF (JOB/=0) GOTO 30
12579
12580!       JOB = 0, solve A*X = B.
12581!       First solve L*Y = B.
12582
12583        IF (ML==0) GOTO 20
12584        IF (NM1<1) GOTO 20
12585        DO K = 1, NM1
12586          LM = MIN(ML,N-K)
12587          L = IPVT(K)
12588          T = B(L)
12589          IF (L==K) GOTO 10
12590          B(L) = B(K)
12591          B(K) = T
1259210        CONTINUE
12593! Original:
12594!         CALL DAXPY_F90(LM,T,ABD(M+1,K),1,B(K+1),1)
12595          CALL DAXPY_F90(LM,T,ABD(M+1:M+LM,K),1,B(K+1:K+LM),1)
12596        END DO
1259720      CONTINUE
12598
12599!       Now solve U*X = Y.
12600
12601        DO KB = 1, N
12602          K = N + 1 - KB
12603          B(K) = B(K)/ABD(M,K)
12604          LM = MIN(K,M) - 1
12605          LA = M - LM
12606          LB = K - LM
12607          T = -B(K)
12608! Original:
12609!         CALL DAXPY_F90(LM,T,ABD(LA,K),1,B(LB),1)
12610          CALL DAXPY_F90(LM,T,ABD(LA:LA+LM-1,K),1,B(LB:LB+LM-1),1)
12611        END DO
12612        GOTO 60
1261330      CONTINUE
12614
12615!       JOB /= 0, solve TRANS(A)*X = B.
12616
12617!       First solve TRANS(U)*Y = B.
12618
12619        DO K = 1, N
12620          LM = MIN(K,M) - 1
12621          LA = M - LM
12622          LB = K - LM
12623! Original:
12624!         T = DDOT_F90(LM,ABD(LA,K),1,B(LB),1)
12625          T = DDOT_F90(LM,ABD(LA:LA+LM-1,K),1,B(LB:LB+LM-1),1)
12626          B(K) = (B(K)-T)/ABD(M,K)
12627        END DO
12628
12629!       Now solve TRANS(L)*X = Y.
12630
12631        IF (ML==0) GOTO 50
12632        IF (NM1<1) GOTO 50
12633        DO KB = 1, NM1
12634          K = N - KB
12635          LM = MIN(ML,N-K)
12636! Original:
12637!         B(K) = B(K) + DDOT_F90(LM,ABD(M+1,K),1,B(K+1),1)
12638          B(K) = B(K) + DDOT_F90(LM,ABD(M+1:M+LM,K),1,B(K+1:K+LM),1)
12639          L = IPVT(K)
12640          IF (L==K) GOTO 40
12641          T = B(L)
12642          B(L) = B(K)
12643          B(K) = T
1264440        CONTINUE
12645        END DO
1264650      CONTINUE
1264760      CONTINUE
12648        RETURN
12649
12650      END SUBROUTINE DGBSL_F90
12651!_______________________________________________________________________
12652
12653      SUBROUTINE DAXPY_F90(N,DA,DX,INCX,DY,INCY)
12654! ..
12655! Compute a constant times a vector plus a vector.
12656! ..
12657!     Description of Parameters
12658!     Input:
12659!     N    - number of elements in input vector(s)
12660!     DA   - real(wp) scalar multiplier
12661!     DX   - real(wp) vector with N elements
12662!     INCX - storage spacing between elements of DX
12663!     DY   - real(wp) vector with N elements
12664!     INCY -  storage spacing between elements of DY
12665!     Output:
12666!     DY - real(wp) result (unchanged if N <= 0)
12667!     Overwrite real(wp) DY with real(wp) DA*DX + DY.
12668!     For I = 0 to N-1, replace  DY(LY+I*INCY) with
12669!     DA*DX(LX+I*INCX) + DY(LY+I*INCY),
12670!     where LX = 1 if INCX >= 0, else LX = 1+(1-N)*INCX,
12671!     and LY is defined in a similar way using INCY.
12672! ..
12673     IMPLICIT NONE
12674! ..
12675! .. Scalar Arguments ..
12676        KPP_REAL, INTENT (IN) :: DA
12677        INTEGER, INTENT (IN) :: INCX, INCY, N
12678! ..
12679! .. Array Arguments ..
12680        KPP_REAL, INTENT (IN) :: DX(*)
12681        KPP_REAL, INTENT (INOUT) :: DY(*)
12682! ..
12683! .. Local Scalars ..
12684        INTEGER :: I, IX, IY, M, MP1, NS
12685! ..
12686! .. Intrinsic Functions ..
12687        INTRINSIC ABS, MOD
12688! ..
12689! .. FIRST EXECUTABLE STATEMENT DAXPY_F90
12690! ..
12691!       IF (N <= 0 .OR. DA == ZERO) RETURN
12692        IF (N<=0 .OR. ABS(DA)<=ZERO) RETURN
12693!       IF (INCX==INCY) IF (INCX-1) 10, 20, 40
12694        IF (INCX == INCY) THEN
12695          IF (INCX < 1) THEN
12696             GOTO 10
12697          ELSEIF (INCX == 1) THEN
12698             GOTO 20
12699          ELSE
12700             GOTO 40
12701          END IF
12702        END IF
12703
12704!       Code for unequal or nonpositive increments.
12705
1270610      IX = 1
12707        IY = 1
12708        IF (INCX<0) IX = (-N+1)*INCX + 1
12709        IF (INCY<0) IY = (-N+1)*INCY + 1
12710        DO I = 1, N
12711          DY(IY) = DY(IY) + DA*DX(IX)
12712          IX = IX + INCX
12713          IY = IY + INCY
12714        END DO
12715        RETURN
12716
12717!       Code for both increments equal to 1.
12718
12719!       Clean-up loop so remaining vector length is a multiple of 4.
12720
1272120      M = MOD(N,4)
12722        IF (M==0) GOTO 30
12723        DY(1:M) = DY(1:M) + DA*DX(1:M)
12724        IF (N<4) RETURN
1272530      MP1 = M + 1
12726        DO I = MP1, N, 4
12727          DY(I) = DY(I) + DA*DX(I)
12728          DY(I+1) = DY(I+1) + DA*DX(I+1)
12729          DY(I+2) = DY(I+2) + DA*DX(I+2)
12730          DY(I+3) = DY(I+3) + DA*DX(I+3)
12731        END DO
12732        RETURN
12733
12734!       Code for equal, positive, non-unit increments.
12735
1273640      NS = N*INCX
12737        DO I = 1, NS, INCX
12738          DY(I) = DA*DX(I) + DY(I)
12739        END DO
12740        RETURN
12741
12742      END SUBROUTINE DAXPY_F90
12743!_______________________________________________________________________
12744
12745      SUBROUTINE DCOPY_F90(N,DX,INCX,DY,INCY)
12746! ..
12747! Copy a vector to another vector.
12748! ..
12749!     Description of Parameters
12750!     Input:
12751!     N    - number of elements in input vector(s)
12752!     DX   - real(wp) vector with N elements
12753!     INCX - storage spacing between elements of DX
12754!     DY   - real(wp) vector with N elements
12755!     INCY - storage spacing between elements of DY
12756!     Output:
12757!     DY - copy of vector DX(unchanged if N <= 0)
12758!     Copy real(wp) DX to real(wp) DY.
12759!     For I = 0 to N-1, copy DX(LX+I*INCX) to DY(LY+I*INCY),
12760!     where LX = 1 if INCX >= 0, else LX = 1+(1-N)*INCX,
12761!     and LY is defined in a similar way using INCY.
12762! ..
12763     IMPLICIT NONE
12764! ..
12765! .. Scalar Arguments ..
12766        INTEGER, INTENT (IN) :: INCX, INCY, N
12767! ..
12768! .. Array Arguments ..
12769        KPP_REAL, INTENT (IN) :: DX(*)
12770        KPP_REAL, INTENT (INOUT) :: DY(*)
12771! ..
12772! .. Local Scalars ..
12773        INTEGER :: I, IX, IY, M, MP1, NS
12774! ..
12775! .. Intrinsic Functions ..
12776        INTRINSIC MOD
12777! ..
12778! .. FIRST EXECUTABLE STATEMENT DCOPY_F90
12779! ..
12780        IF (N<=0) RETURN
12781!       IF (INCX==INCY) IF (INCX-1) 10, 20, 40
12782        IF (INCX == INCY) THEN
12783          IF (INCX < 1) THEN
12784             GOTO 10
12785          ELSEIF (INCX == 1) THEN
12786             GOTO 20
12787          ELSE
12788             GOTO 40
12789          END IF
12790        END IF
12791
12792!       Code for unequal or nonpositive increments.
12793
1279410      IX = 1
12795        IY = 1
12796        IF (INCX<0) IX = (-N+1)*INCX + 1
12797        IF (INCY<0) IY = (-N+1)*INCY + 1
12798        DO I = 1, N
12799          DY(IY) = DX(IX)
12800          IX = IX + INCX
12801          IY = IY + INCY
12802        END DO
12803        RETURN
12804
12805!       Code for both increments equal to 1.
12806
12807!       Clean-up loop so remaining vector length is a multiple of 7.
12808
1280920      M = MOD(N,7)
12810        IF (M==0) GOTO 30
12811        DO I = 1, M
12812          DY(I) = DX(I)
12813        END DO
12814        IF (N<7) RETURN
1281530      MP1 = M + 1
12816        DO I = MP1, N, 7
12817          DY(I) = DX(I)
12818          DY(I+1) = DX(I+1)
12819          DY(I+2) = DX(I+2)
12820          DY(I+3) = DX(I+3)
12821          DY(I+4) = DX(I+4)
12822          DY(I+5) = DX(I+5)
12823          DY(I+6) = DX(I+6)
12824        END DO
12825        RETURN
12826
12827!       Code for equal, positive, non-unit increments.
12828
1282940      NS = N*INCX
12830        DO I = 1, NS, INCX
12831          DY(I) = DX(I)
12832        END DO
12833        RETURN
12834
12835      END SUBROUTINE DCOPY_F90
12836!_______________________________________________________________________
12837
12838      FUNCTION DDOT_F90(N,DX,INCX,DY,INCY)
12839! ..
12840! Compute the inner product of two vectors.
12841! ..
12842!     Description of Parameters
12843!     Input:
12844!     N    - number of elements in input vector(s)
12845!     DX   - real(wp) vector with N elements
12846!     INCX - storage spacing between elements of DX
12847!     DY   - real(wp) vector with N elements
12848!     INCY - storage spacing between elements of DY
12849!     Output:
12850!     DDOT_F90 - real(wp) dot product (zero if N <= 0)
12851!     Returns the dot product of real(wp) DX and DY.
12852!     DDOT_F90 = sum for I = 0 to N-1 of  DX(LX+I*INCX) * DY(LY+I*INCY),
12853!     where LX = 1 if INCX >= 0, else LX = 1+(1-N)*INCX, and LY is
12854!     defined in a similar way using INCY.
12855! ..
12856     IMPLICIT NONE
12857! ..
12858! .. Function Return Value ..
12859        KPP_REAL :: DDOT_F90
12860! ..
12861! .. Scalar Arguments ..
12862        INTEGER, INTENT (IN) :: INCX, INCY, N
12863! ..
12864! .. Array Arguments ..
12865        KPP_REAL, INTENT (IN) :: DX(*), DY(*)
12866! ..
12867! .. Local Scalars ..
12868        INTEGER :: I, IX, IY, M, MP1, NS
12869! ..
12870! .. Intrinsic Functions ..
12871        INTRINSIC MOD
12872! ..
12873! .. FIRST EXECUTABLE STATEMENT DDOT_F90
12874! ..
12875        DDOT_F90 = ZERO
12876        IF (N<=0) RETURN
12877!       IF (INCX==INCY) IF (INCX-1) 10, 20, 40
12878        IF (INCX == INCY) THEN
12879          IF (INCX < 1) THEN
12880             GOTO 10
12881          ELSEIF (INCX == 1) THEN
12882             GOTO 20
12883          ELSE
12884             GOTO 40
12885          END IF
12886        END IF
12887
12888!       Code for unequal or nonpositive increments.
12889
1289010      IX = 1
12891        IY = 1
12892        IF (INCX<0) IX = (-N+1)*INCX + 1
12893        IF (INCY<0) IY = (-N+1)*INCY + 1
12894        DO I = 1, N
12895          DDOT_F90 = DDOT_F90 + DX(IX)*DY(IY)
12896          IX = IX + INCX
12897          IY = IY + INCY
12898        END DO
12899        RETURN
12900
12901!       Code for both increments equal to 1.
12902
12903!       Clean-up loop so remaining vector length is a multiple of 5.
12904
1290520      M = MOD(N,5)
12906        IF (M==0) GOTO 30
12907        DO I = 1, M
12908          DDOT_F90 = DDOT_F90 + DX(I)*DY(I)
12909        END DO
12910        IF (N<5) RETURN
1291130      MP1 = M + 1
12912        DO I = MP1, N, 5
12913          DDOT_F90 = DDOT_F90 + DX(I)*DY(I) + DX(I+1)*DY(I+1) + &
12914            DX(I+2)*DY(I+2) + DX(I+3)*DY(I+3) + DX(I+4)*DY(I+4)
12915        END DO
12916        RETURN
12917
12918!       Code for equal, positive, non-unit increments.
12919
1292040      NS = N*INCX
12921        DO I = 1, NS, INCX
12922          DDOT_F90 = DDOT_F90 + DX(I)*DY(I)
12923        END DO
12924        RETURN
12925
12926      END FUNCTION DDOT_F90
12927!_______________________________________________________________________
12928
12929      SUBROUTINE DSCAL_F90(N,DA,DX,INCX)
12930! ..
12931! Multiply a vector by a constant.
12932! ..
12933!     Description of Parameters
12934!     Input:
12935!     N    - number of elements in input vector(s)
12936!     DA   - real(wp) scale factor
12937!     DX   - real(wp) vector with N elements
12938!     INCX - storage spacing between elements of DX
12939!     Output:
12940!     DX - real(wp) result (unchanged if N <= 0)
12941!     Replace real(wp) DX by real(wp) DA*DX.
12942!     For I = 0 to N-1, replace DX(IX+I*INCX) with DA * DX(IX+I*INCX),
12943!     where IX = 1 if INCX >= 0, else IX = 1+(1-N)*INCX.
12944! ..
12945     IMPLICIT NONE
12946! ..
12947! .. Scalar Arguments ..
12948        KPP_REAL, INTENT (IN) :: DA
12949        INTEGER, INTENT (IN) :: INCX, N
12950! ..
12951! .. Array Arguments ..
12952        KPP_REAL, INTENT (INOUT) :: DX(*)
12953! ..
12954! .. Local Scalars ..
12955        INTEGER :: I, IX, M, MP1
12956! ..
12957! .. Intrinsic Functions ..
12958        INTRINSIC MOD
12959! ..
12960! .. FIRST EXECUTABLE STATEMENT DSCAL_F90
12961! ..
12962        IF (N<=0) RETURN
12963        IF (INCX==1) GOTO 10
12964
12965!       Code for increment not equal to 1.
12966
12967        IX = 1
12968        IF (INCX<0) IX = (-N+1)*INCX + 1
12969        DO I = 1, N
12970          DX(IX) = DA*DX(IX)
12971          IX = IX + INCX
12972        END DO
12973        RETURN
12974
12975!       Code for increment equal to 1.
12976
12977!       Clean-up loop so remaining vector length is a multiple of 5.
12978
1297910      M = MOD(N,5)
12980        IF (M==0) GOTO 20
12981        DX(1:M) = DA*DX(1:M)
12982        IF (N<5) RETURN
1298320      MP1 = M + 1
12984        DO I = MP1, N, 5
12985          DX(I) = DA*DX(I)
12986          DX(I+1) = DA*DX(I+1)
12987          DX(I+2) = DA*DX(I+2)
12988          DX(I+3) = DA*DX(I+3)
12989          DX(I+4) = DA*DX(I+4)
12990        END DO
12991        RETURN
12992
12993      END SUBROUTINE DSCAL_F90
12994!_______________________________________________________________________
12995
12996      FUNCTION IDAMAX_F90(N,DX,INCX)
12997! ..
12998! Find the smallest index of that component of a vector
12999! having the maximum magnitude.
13000! ..
13001!     Description of Parameters
13002!     Input:
13003!     N    - number of elements in input vector(s)
13004!     DX   - real(wp) vector with N elements
13005!     INCX - storage spacing between elements of DX
13006!     Output:
13007!     IDAMAX_F90 - smallest index (zero if N <= 0)
13008!     Find smallest index of maximum magnitude of real(wp) DX.
13009!     IDAMAX_F90 = first I, I = 1 to N, to maximize
13010!     ABS(DX(IX+(I-1)*INCX)), where IX = 1 if INCX >= 0,
13011!     else IX = 1+(1-N)*INCX.
13012! ..
13013     IMPLICIT NONE
13014! ..
13015! .. Function Return Value ..
13016        INTEGER :: IDAMAX_F90
13017! ..
13018! .. Scalar Arguments ..
13019        INTEGER, INTENT (IN) :: INCX, N
13020! ..
13021! .. Array Arguments ..
13022        KPP_REAL, INTENT (IN) :: DX(*)
13023! ..
13024! .. Local Scalars ..
13025        KPP_REAL :: DMAX, XMAG
13026        INTEGER :: I, IX
13027! ..
13028! .. Intrinsic Functions ..
13029        INTRINSIC ABS
13030! ..
13031! .. FIRST EXECUTABLE STATEMENT IDAMAX_F90
13032! ..
13033        IDAMAX_F90 = 0
13034        IF (N<=0) RETURN
13035        IDAMAX_F90 = 1
13036        IF (N==1) RETURN
13037
13038        IF (INCX==1) GOTO 10
13039
13040!       Code for increments not equal to 1.
13041
13042        IX = 1
13043        IF (INCX<0) IX = (-N+1)*INCX + 1
13044        DMAX = ABS(DX(IX))
13045        IX = IX + INCX
13046        DO I = 2, N
13047          XMAG = ABS(DX(IX))
13048          IF (XMAG>DMAX) THEN
13049            IDAMAX_F90 = I
13050            DMAX = XMAG
13051          END IF
13052          IX = IX + INCX
13053        END DO
13054        RETURN
13055
13056!       Code for increments equal to 1.
13057
1305810      DMAX = ABS(DX(1))
13059        DO I = 2, N
13060          XMAG = ABS(DX(I))
13061          IF (XMAG>DMAX) THEN
13062            IDAMAX_F90 = I
13063            DMAX = XMAG
13064          END IF
13065        END DO
13066        RETURN
13067
13068      END FUNCTION IDAMAX_F90
13069! End of LINPACK and BLAS subroutines
13070!_______________________________________________________________________
13071
13072! Beginning of MA28 subroutines
13073! THIS IS A FORTRAN 90 TRANSLATION OF HSL'S F77 MA28. IT IS INTENDED
13074! ONLY FOR USE IN CONJUNCTION WITH THE ODE SOLVER DVODE_F90 AND IS
13075! NOT FUNCTIONAL IN A STANDALONE MANNER. PLEASE NOTE THAT MA28 IS NOT
13076! PUBLIC DOMAIN SOFTWARE BUT HAS BEEN MADE AVAILABLE TO THE NUMERICAL
13077! ANALYSIS COMMUNITY BY HARWELL. FOR OTHER USE PLEASE CONTACT HARWELL
13078! AT HTTP://WWW.HSL-LIBRARY.COM OR CONTACT HSL@HYPROTECH.COM IF YOU
13079! WISH TO SOLVE GENERAL SPARSE LINEAR SYSTEMS. IF YOU FIND A BUG OR
13080! ENCOUNTER A PROBLEM WITH THE USE OF MA28 WITH DVODE.F90, PLEASE
13081! CONTACT ONE OF THE AUTHORS OF DVODE_F90:
13082!           G.D. Byrne (gbyrne@wi.rr.com)
13083!           S. Thompson, thompson@radford.edu
13084! NUMEROUS CHANGES WERE MADE IN CONNECTION WITH DVODE_F90 USAGE. THESE
13085! INCLUDE USING METCALF'S CONVERTER TO TRANSLATE THE ORIGINAL f77 CODE
13086! TO F90, MOVING INITIALIZATIONS TO THE DVODE_F90 PRIVATE SECTION,
13087! ELIMINATION OF HOLLERITHS IN FORMAT STATEMENTS, ELIMINATION OF
13088! BLOCKDATA, CHANGES IN ARITHMETICAL OPERATOR SYNTAX, AND CONVERSION
13089! TO UPPER CASE. THIS VERSION OF MA28 IS INTENDED ONLY FOR USE WITH
13090! DVODE_F90. PLEASE DO NOT MODIFY IT FOR ANY OTHER PURPOSE. IF YOU
13091! HAVE LICENSED ACCESS TO THE HSL LIBRARY, AN ALTERNATE VERSION OF
13092! DVODE_F90 BASED ON THE SUCCESSOR TO MA28, MA48, IS AVAILABLE FROM
13093! THE AUTHORS. PLEASE NOTE THAT THE ALTERNATE VERSION OF DVODE_F90
13094! IS NOT SELF CONTAINED SINCE MA48 IS NOT DISTRIBUTED WITH DVODE_F90.
13095!******************************************************************
13096!             *****MA28 COPYRIGHT NOTICE*****
13097! COPYRIGHT (C) 2001 COUNCIL FOR THE CENTRAL LABORATORY
13098!               OF THE RESEARCH COUNCILS
13099! ALL RIGHTS RESERVED.
13100
13101! NONE OF THE COMMENTS IN THIS COPYRIGHT NOTICE BETWEEN THE LINES
13102! OF ASTERISKS SHALL BE REMOVED OR ALTERED IN ANY WAY.
13103
13104! THIS PACKAGE IS INTENDED FOR COMPILATION WITHOUT MODIFICATION,
13105! SO MOST OF THE EMBEDDED COMMENTS HAVE BEEN REMOVED.
13106
13107! ALL USE IS SUBJECT TO LICENCE. IF YOU NEED FURTHER CLARIFICATION,
13108! PLEASE SEE HTTP://WWW.HSL-LIBRARY.COM OR CONTACT HSL@HYPROTECH.COM
13109
13110! PLEASE NOTE THAT:
13111
13112! 1. THE PACKAGES MAY ONLY BE USED FOR THE PURPOSES SPECIFIED IN THE
13113!    LICENCE AGREEMENT AND MUST NOT BE COPIED BY THE LICENSEE FOR
13114!    USE BY ANY OTHER PERSONS. USE OF THE PACKAGES IN ANY COMMERCIAL
13115!    APPLICATION SHALL BE SUBJECT TO PRIOR WRITTEN AGREEMENT BETWEEN
13116!    HYPROTECH UK LIMITED AND THE LICENSEE ON SUITABLE TERMS AND
13117!    CONDITIONS, WHICH WILL INCLUDE FINANCIAL CONDITIONS.
13118! 2. ALL INFORMATION ON THE PACKAGE IS PROVIDED TO THE LICENSEE ON
13119!    THE UNDERSTANDING THAT THE DETAILS THEREOF ARE CONFIDENTIAL.
13120! 3. ALL PUBLICATIONS ISSUED BY THE LICENSEE THAT INCLUDE RESULTS
13121!    OBTAINED WITH THE HELP OF ONE OR MORE OF THE PACKAGES SHALL
13122!    ACKNOWLEDGE THE USE OF THE PACKAGES. THE LICENSEE WILL NOTIFY
13123!    HSL@HYPROTECH.COM OR HYPROTECH UK LIMITED OF ANY SUCH PUBLICATION.
13124! 4. THE PACKAGES MAY BE MODIFIED BY OR ON BEHALF OF THE LICENSEE
13125!    FOR SUCH USE IN RESEARCH APPLICATIONS BUT AT NO TIME SHALL SUCH
13126!    PACKAGES OR MODIFICATIONS THEREOF BECOME THE PROPERTY OF THE
13127!    LICENSEE. THE LICENSEE SHALL MAKE AVAILABLE FREE OF CHARGE TO THE
13128!    COPYRIGHT HOLDER FOR ANY PURPOSE ALL INFORMATION RELATING TO
13129!    ANY MODIFICATION.
13130! 5. NEITHER COUNCIL FOR THE CENTRAL LABORATORY OF THE RESEARCH
13131!    COUNCILS NOR HYPROTECH UK LIMITED SHALL BE LIABLE FOR ANY
13132!    DIRECT OR CONSEQUENTIAL LOSS OR DAMAGE WHATSOEVER ARISING OUT OF
13133!    THE USE OF PACKAGES BY THE LICENSEE.
13134!******************************************************************
13135
13136      SUBROUTINE MA28AD(N,NZ,A,LICN,IRN,LIRN,ICN,U,IKEEP,IW,W,IFLAG)
13137! ..
13138! This subroutine performs the LU factorization of A.
13139! ..
13140! The parameters are as follows:
13141! N     Order of matrix. Not altered by subroutine.
13142! NZ    Number of non-zeros in input matrix. Not altered by subroutine.
13143! A     Array of length LICN. Holds non-zeros of matrix
13144!       on entry and non-zeros of factors on exit. Reordered by
13145!       MA20AD and MC23AD and altered by MA30AD.
13146! LICN  Length of arrays A and ICN. Not altered by subroutine.
13147! IRN   Array of length LIRN. Holds row indices on input.
13148!       Used as workspace by MA30AD to hold column orientation of
13149!       matrix.
13150! LIRN  Length of array IRN. Not altered by the subroutine.
13151! ICN   Array of length LICN. Holds column indices on entry
13152!       and column indices of decomposed matrix on exit. Reordered
13153!       by MA20AD and MC23AD and altered by MA30AD.
13154! U     Variable set by user to control bias towards numeric or
13155!       sparsity pivoting. U = 1.0 gives partial pivoting
13156!       while U = 0. does not check multipliers at all. Values of U
13157!       greater than one are treated as one while negative values
13158!       are treated as zero. Not altered by subroutine.
13159! IKEEP Array of length 5*N used as workspace by MA28AD.
13160!       (See later comments.) It is not required to be set on entry
13161!       and, on exit, it contains information about the decomposition.
13162!       It should be preserved between this call and subsequent calls
13163!       to MA28BD or MA30CD.
13164!       IKEEP(I,1),I = 1,N holds the total length of the part of row
13165!       I in the diagonal block.
13166!       Row IKEEP(I,2),I = 1,N of the input matrix is the Ith row in
13167!       pivot order.
13168!       Column IKEEP(I,3),I = 1,N of the input matrix is the Ith
13169!       Column in pivot order.
13170!       IKEEP(I,4),I = 1,N holds the length of the part of row I in
13171!       the L part of the LU decomposition.
13172!       IKEEP(I,5),I = 1,N holds the length of the part of row I in
13173!       the off-diagonal blocks. If there is only one diagonal block,
13174!       IKEEP(1,5) will be set to -1.
13175! IW    Array of length 8*N. If the option NSRCH <= N is used, then
13176!       the length of array IW can be reduced to 7*N.
13177! W     Array length N. Used by MC24AD both as workspace and to return
13178!       growth estimate in W(1). The use of this array by MA28AD is
13179!       thus optional depending on logical variable GROW.
13180! IFLAG Variable used as error flag by subroutine. A positive or
13181!       zero value on exit indicates success. Possible negative
13182!       values are -1 through -14.
13183
13184! Private Variable Information.
13185! LP, MP Default value 6 (line printer). Unit number for error
13186!     messages and duplicate element warning, respectively.
13187! NLP, MLP INTEGER. Unit number for messages from MA30AD and
13188!     MC23AD. Set by MA28AD to the value of LP.
13189! LBLOCK Logical variable with default value .TRUE. If .TRUE.,
13190!     MC23AD is used to first permute the matrix to block lower
13191!     triangular form.
13192! GROW Logical variable with default value .TRUE. If .TRUE., then
13193!     an estimate of the increase in size of matrix elements during
13194!     LU decomposition is given by MC24AD.
13195! EPS, RMIN, RESID. Variables not referenced by MA28AD.
13196! IRNCP, ICNCP INTEGER. Set to number of compresses on arrays IRN
13197!     and ICN/A, respectively.
13198! MINIRN, MINICN INTEGER. Minimum length of arrays IRN and ICN/A,
13199!     respectively, for success on future runs.
13200! IRANK INTEGER. Estimated rank of matrix.
13201! MIRNCP, MICNCP, MIRANK, MIRN, MICN INTEGER. Variables used to
13202!     communicate between MA30FD and MA28FD values of
13203!     abovenamed variables with somewhat similar names.
13204! ABORT1, ABORT2 LOGICAL. Variables with default value .TRUE.
13205!     If .FALSE., then decomposition will be performed even
13206!     if the matrix is structurally or numerically singular,
13207!     respectively.
13208! ABORTA, ABORTB LOGICAL. Variables used to communicate values
13209!     of ABORT1 and ABORT2 to MA30AD.
13210! ABORT Logical variable used to communicate value of ABORT1
13211!     to MC23AD.
13212! ABORT3 Logical variable. Not referenced by MA28AD.
13213! IDISP Array of length 2. Used to communicate information
13214!     on decomposition between this call to MA28AD and subsequent
13215!     calls to MA28BD and MA30CD. On exit, IDISP(1) and
13216!     IDISP(2) indicate position in arrays A and ICN of the
13217!     first and last elements in the LU decomposition of the
13218!     diagonal blocks, respectively.
13219! NUMNZ Structural rank of matrix.
13220! NUM   Number of diagonal blocks.
13221! LARGE Size of largest diagonal block.
13222! ..
13223     IMPLICIT NONE
13224! ..
13225! .. Scalar Arguments ..
13226        KPP_REAL :: U
13227        INTEGER :: IFLAG, LICN, LIRN, N, NZ
13228! ..
13229! .. Array Arguments ..
13230        KPP_REAL :: A(LICN), W(N)
13231        INTEGER :: ICN(LICN), IKEEP(N,5), IRN(LIRN), IW(N,8)
13232! ..
13233! .. Local Scalars ..
13234        KPP_REAL :: UPRIV
13235        INTEGER :: I, I1, IEND, II, J, J1, J2, JAY, JJ, KNUM, LENGTH, MOVE, &
13236          NEWJ1, NEWPOS
13237        CHARACTER (80) :: MSG
13238! ..
13239! .. Intrinsic Functions ..
13240        INTRINSIC ABS, MAX
13241! ..
13242! .. FIRST EXECUTABLE STATEMENT MA28AD
13243! ..
13244!       Check that this call was made from DVODE_F90 and, if not, stop.
13245        IF (.NOT.OK_TO_CALL_MA28) THEN
13246          MSG = 'This version of MA28 may be used only in conjunction with DVODE_F90.'
13247          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13248          MSG = 'Please refer to the following HSL copyright notice for MA28.'
13249          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13250          MSG = '******************************************************************     '
13251          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13252          MSG = '             *****MA28 COPYRIGHT NOTICE*****                           '
13253          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13254          MSG = ' COPYRIGHT (C) 2001 COUNCIL FOR THE CENTRAL LABORATORY                 '
13255          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13256          MSG = '               OF THE RESEARCH COUNCILS                                '
13257          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13258          MSG = ' ALL RIGHTS RESERVED.                                                  '
13259          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13260          MSG = ' NONE OF THE COMMENTS IN THIS COPYRIGHT NOTICE BETWEEN THE LINES       '
13261          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13262          MSG = ' OF ASTERISKS SHALL BE REMOVED OR ALTERED IN ANY WAY.                  '
13263          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13264          MSG = ' THIS PACKAGE IS INTENDED FOR COMPILATION WITHOUT MODIFICATION,        '
13265          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13266          MSG = ' SO MOST OF THE EMBEDDED COMMENTS HAVE BEEN REMOVED.                   '
13267          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13268          MSG = ' ALL USE IS SUBJECT TO LICENCE. IF YOU NEED FURTHER CLARIFICATION,     '
13269          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13270          MSG = ' PLEASE SEE HTTP://WWW.HSL-LIBRARY.COM OR CONTACT HSL@HYPROTECH.COM    '
13271          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13272          MSG = ' PLEASE NOTE THAT:                                                     '
13273          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13274          MSG = ' 1. THE PACKAGES MAY ONLY BE USED FOR THE PURPOSES SPECIFIED IN THE    '
13275          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13276          MSG = '    LICENCE AGREEMENT AND MUST NOT BE COPIED BY THE LICENSEE FOR       '
13277          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13278          MSG = '    USE BY ANY OTHER PERSONS. USE OF THE PACKAGES IN ANY COMMERCIAL    '
13279          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13280          MSG = '    APPLICATION SHALL BE SUBJECT TO PRIOR WRITTEN AGREEMENT BETWEEN    '
13281          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13282          MSG = '    HYPROTECH UK LIMITED AND THE LICENSEE ON SUITABLE TERMS AND        '
13283          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13284          MSG = '    CONDITIONS, WHICH WILL INCLUDE FINANCIAL CONDITIONS.               '
13285          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13286          MSG = ' 2. ALL INFORMATION ON THE PACKAGE IS PROVIDED TO THE LICENSEE ON      '
13287          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13288          MSG = '    THE UNDERSTANDING THAT THE DETAILS THEREOF ARE CONFIDENTIAL.       '
13289          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13290          MSG = ' 3. ALL PUBLICATIONS ISSUED BY THE LICENSEE THAT INCLUDE RESULTS       '
13291          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13292          MSG = '    OBTAINED WITH THE HELP OF ONE OR MORE OF THE PACKAGES SHALL        '
13293          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13294          MSG = '    ACKNOWLEDGE THE USE OF THE PACKAGES. THE LICENSEE WILL NOTIFY      '
13295          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13296          MSG = '    HSL@HYPROTECH.COM OR HYPROTECH UK LIMITED OF ANY SUCH PUBLICATION. '
13297          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13298          MSG = ' 4. THE PACKAGES MAY BE MODIFIED BY OR ON BEHALF OF THE LICENSEE       '
13299          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13300          MSG = '    FOR SUCH USE IN RESEARCH APPLICATIONS BUT AT NO TIME SHALL SUCH    '
13301          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13302          MSG = '    PACKAGES OR MODIFICATIONS THEREOF BECOME THE PROPERTY OF THE       '
13303          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13304          MSG = '    LICENSEE. THE LICENSEE SHALL MAKE AVAILABLE FREE OF CHARGE TO THE  '
13305          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13306          MSG = '    COPYRIGHT HOLDER FOR ANY PURPOSE ALL INFORMATION RELATING TO       '
13307          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13308          MSG = '    ANY MODIFICATION.                                                  '
13309          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13310          MSG = ' 5. NEITHER COUNCIL FOR THE CENTRAL LABORATORY OF THE RESEARCH         '
13311          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13312          MSG = '    COUNCILS NOR HYPROTECH UK LIMITED SHALL BE LIABLE FOR ANY          '
13313          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13314          MSG = '    DIRECT OR CONSEQUENTIAL LOSS OR DAMAGE WHATSOEVER ARISING OUT OF   '
13315          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13316          MSG = '    THE USE OF PACKAGES BY THE LICENSEE.                               '
13317          CALL XERRDV(MSG,1770,1,0,0,0,0,ZERO,ZERO)
13318          MSG = '******************************************************************     '
13319          CALL XERRDV(MSG,1770,2,0,0,0,0,ZERO,ZERO)
13320        END IF
13321
13322!       Some initialization and transfer of information between
13323!       common blocks (see earlier comments).
13324        IFLAG = 0
13325        ABORTA = ABORT1
13326        ABORTB = ABORT2
13327        ABORT = ABORT1
13328        MLP = LP
13329        NLP = LP
13330        TOL1 = TOL
13331        LBIG1 = LBIG
13332        NSRCH1 = NSRCH
13333!       UPRIV private copy of U is used in case it is outside
13334!       range zero to one and is thus altered by MA30AD.
13335        UPRIV = U
13336!       Simple data check on input variables and array dimensions.
13337        IF (N>0) GOTO 10
13338        IFLAG = -8
13339        IF (LP/=0) WRITE (LP,90000) N
13340        GOTO 170
1334110      IF (NZ>0) GOTO 20
13342        IFLAG = -9
13343        IF (LP/=0) WRITE (LP,90001) NZ
13344        GOTO 170
1334520      IF (LICN>=NZ) GOTO 30
13346        IFLAG = -10
13347        IF (LP/=0) WRITE (LP,90002) LICN
13348        GOTO 170
1334930      IF (LIRN>=NZ) GOTO 40
13350        IFLAG = -11
13351        IF (LP/=0) WRITE (LP,90003) LIRN
13352        GOTO 170
13353
13354!       Data check to see if all indices lie between 1 and N.
1335540      DO 50 I = 1, NZ
13356          IF (IRN(I)>0 .AND. IRN(I)<=N .AND. ICN(I)>0 .AND. ICN(I)<=N) &
13357            GOTO 50
13358          IF (IFLAG==0 .AND. LP/=0) WRITE (LP,90004)
13359          IFLAG = -12
13360          IF (LP/=0) WRITE (LP,90005) I, A(I), IRN(I), ICN(I)
1336150      END DO
13362        IF (IFLAG<0) GOTO 180
13363
13364!       Sort matrix into row order.
13365        CALL MC20AD(N,NZ,A,ICN,IW(1,1),IRN,0)
13366!       Part of IKEEP is used here as a work-array. IKEEP(I,2) is
13367!       the last row to have a non-zero in column I. IKEEP(I,3)
13368!       is the off-set of column I from the start of the row.
13369        IKEEP(1:N,2) = 0
13370        IKEEP(1:N,1) = 0
13371
13372!       Check for duplicate elements summing any such entries
13373!       and printing a warning message on unit MP.
13374!       MOVE is equal to the number of duplicate elements found.
13375        MOVE = 0
13376!       The loop also calculates the largest element in the matrix,
13377!       THEMAX.
13378        THEMAX = ZERO
13379!       J1 is position in arrays of first non-zero in row.
13380        J1 = IW(1,1)
13381        DO 90 I = 1, N
13382          IEND = NZ + 1
13383          IF (I/=N) IEND = IW(I+1,1)
13384          LENGTH = IEND - J1
13385          IF (LENGTH==0) GOTO 90
13386          J2 = IEND - 1
13387          NEWJ1 = J1 - MOVE
13388          DO 80 JJ = J1, J2
13389            J = ICN(JJ)
13390            THEMAX = MAX(THEMAX,ABS(A(JJ)))
13391            IF (IKEEP(J,2)==I) GOTO 70
13392!           First time column has ocurred in current row.
13393            IKEEP(J,2) = I
13394            IKEEP(J,3) = JJ - MOVE - NEWJ1
13395            IF (MOVE==0) GOTO 80
13396!           Shift necessary because of previous duplicate element.
13397            NEWPOS = JJ - MOVE
13398            A(NEWPOS) = A(JJ)
13399            ICN(NEWPOS) = ICN(JJ)
13400            GOTO 80
13401!           Duplicate element.
1340270          MOVE = MOVE + 1
13403            LENGTH = LENGTH - 1
13404            JAY = IKEEP(J,3) + NEWJ1
13405            IF (MP/=0) WRITE (MP,90006) I, J, A(JJ)
13406            A(JAY) = A(JAY) + A(JJ)
13407            THEMAX = MAX(THEMAX,ABS(A(JAY)))
1340880        END DO
13409          IKEEP(I,1) = LENGTH
13410          J1 = IEND
1341190      END DO
13412
13413!       KNUM is actual number of non-zeros in matrix with any multiple
13414!       entries counted only once.
13415        KNUM = NZ - MOVE
13416        IF (.NOT.LBLOCK) GOTO 100
13417
13418!       Perform block triangularisation.
13419        CALL MC23AD(N,ICN,A,LICN,IKEEP(1,1),IDISP,IKEEP(1,2),IKEEP(1,3), &
13420          IKEEP(1,5),IW(1,3),IW)
13421        IF (IDISP(1)>0) GOTO 130
13422        IFLAG = -7
13423        IF (IDISP(1)==-1) IFLAG = -1
13424        IF (LP/=0) WRITE (LP,90007)
13425        GOTO 170
13426
13427!       Block triangularization not requested.
13428!       Move structure to end of data arrays in preparation for MA30AD.
13429!       Also set LENOFF(1) to -1 and set permutation arrays.
13430100     DO I = 1, KNUM
13431          II = KNUM - I + 1
13432          NEWPOS = LICN - I + 1
13433          ICN(NEWPOS) = ICN(II)
13434          A(NEWPOS) = A(II)
13435        END DO
13436        IDISP(1) = 1
13437        IDISP(2) = LICN - KNUM + 1
13438        DO I = 1, N
13439          IKEEP(I,2) = I
13440          IKEEP(I,3) = I
13441        END DO
13442        IKEEP(1,5) = -1
13443130     IF (LBIG) BIG1 = THEMAX
13444        IF (NSRCH<=N) GOTO 140
13445
13446!       Perform LU decomposition on diagonal blocks.
13447        CALL MA30AD(N,ICN,A,LICN,IKEEP(1,1),IKEEP(1,4),IDISP,IKEEP(1,2),       &
13448          IKEEP(1,3),IRN,LIRN,IW(1,2),IW(1,3),IW(1,4),IW(1,5),IW(1,6),IW(1,7), &
13449          IW(1,8),IW,UPRIV,IFLAG)
13450        GOTO 150
13451!       This call if used if NSRCH has been set less than or equal to N.
13452!       In this case, two integer work arrays of length can be saved.
13453140     CALL MA30AD(N,ICN,A,LICN,IKEEP(1,1),IKEEP(1,4),IDISP,IKEEP(1,2),       &
13454          IKEEP(1,3),IRN,LIRN,IW(1,2),IW(1,3),IW(1,4),IW(1,5),IW,IW,IW(1,6),IW,&
13455          UPRIV,IFLAG)
13456
13457!       Transfer private variable information.
13458!150    MINIRN = MAX(MIRN,NZ)
13459!       MINICN = MAX(MICN,NZ)
13460150     MINIRN = MAX(MINIRN,NZ)
13461        MINICN = MAX(MINICN,NZ)
13462!       IRNCP = MIRNCP
13463!       ICNCP = MICNCP
13464!       IRANK = MIRANK
13465!       NDROP = NDROP1
13466        IF (LBIG) BIG = BIG1
13467        IF (IFLAG>=0) GOTO 160
13468        IF (LP/=0) WRITE (LP,90008)
13469        GOTO 170
13470
13471!       Reorder off-diagonal blocks according to pivot permutation.
13472160     I1 = IDISP(1) - 1
13473        IF (I1/=0) CALL MC22AD(N,ICN,A,I1,IKEEP(1,5),IKEEP(1,2), &
13474          IKEEP(1,3),IW,IRN)
13475        I1 = IDISP(1)
13476        IEND = LICN - I1 + 1
13477
13478!       Optionally calculate element growth estimate.
13479        IF (GROW) CALL MC24AD(N,ICN,A(I1),IEND,IKEEP,IKEEP(1,4),W)
13480!       Increment growth estimate by original maximum element.
13481        IF (GROW) W(1) = W(1) + THEMAX
13482        IF (GROW .AND. N>1) W(2) = THEMAX
13483!       Set flag if the only error is due to duplicate elements.
13484        IF (IFLAG>=0 .AND. MOVE/=0) IFLAG = -14
13485        GOTO 180
13486170     IF (LP/=0) WRITE (LP,90009)
13487180     RETURN
1348890000   FORMAT (' N is out of range = ',I10)
1348990001   FORMAT (' NZ is non positive = ',I10)
1349090002   FORMAT (' LICN is too small = ',I10)
1349190003   FORMAT (' LIRN is too small = ',I10)
1349290004   FORMAT (' Error return from MA28AD because indices found out', &
13493          ' of range')
1349490005   FORMAT (1X,I6,'The element with value ',1P,D22.14, &
13495          ' is out of range with indices ',I8,',',I8)
1349690006   FORMAT (' Duplicate element in position ',I8,',',I8,' with value ',1P, &
13497          D22.14)
1349890007   FORMAT (' Error return from MC23AD')
1349990008   FORMAT (' Error return from MA30AD')
1350090009   FORMAT (' Error return from MA28AD')
13501
13502      END SUBROUTINE MA28AD
13503!_______________________________________________________________________
13504
13505      SUBROUTINE MA28BD(N,NZ,A,LICN,IVECT,JVECT,ICN,IKEEP,IW,W,IFLAG)
13506! ..
13507! This subroutine factorizes a matrix of a similar sparsity
13508! pattern to that previously factorized by MA28AD.
13509! ..
13510! The parameters are as follows:
13511! N            Order of matrix. Not altered by subroutine.
13512! NZ           Number of non-zeros in input matrix. Not
13513!              altered by subroutine.
13514! A            Array of length LICN. Holds non-zeros of
13515!              matrix on entry and non-zeros of factors on exit.
13516!              Reordered by MA28DD and altered by MA30BD.
13517! LICN         Length of arrays A and ICN. Not altered by
13518!              subroutine.
13519! IVECT, JVECT Arrays of length NZ. Hold row and column
13520!              indices of non-zeros, respectively. Not altered
13521!              by subroutine.
13522! ICN          Array of length LICN. Same array as output
13523!              from MA28AD. Unchanged by MA28BD.
13524! IKEEP        Array of length 5*N. Same array as output
13525!              from MA28AD. Unchanged by MA28BD.
13526! IW           Array length 5*N. Used as workspace by
13527!              MA28DD and MA30BD.
13528! W            Array of length N. Used as workspace by
13529!              MA28DD, MA30BD and (optionally) MC24AD.
13530! IFLAG        Integer used as error flag, with positive
13531!              or zero value indicating success.
13532
13533! Private Variable Information.
13534! Unless otherwise stated private variables are as in MA28AD.
13535! Those variables referenced by MA28BD are mentioned below.
13536! LP, MP     Integers used as in MA28AD as unit number for error
13537!            and warning messages, respectively.
13538! NLP        Integer variable used to give value of LP to MA30ED.
13539! EPS        MA30BD will output a positive value
13540!            for IFLAG if any modulus of the ratio of pivot element
13541!            to the largest element in its row (U part only) is less
13542!            than EPS (unless EPS is greater than 1.0 when no action
13543!            takes place).
13544! RMIN       Variable equal to the value of this minimum ratio in
13545!            cases where EPS is less than or equal to 1.0.
13546! MEPS,MRMIN Variables used by the subroutine to communicate between
13547!            MA28FD and MA30GD.
13548! IDISP      Integer array of length 2. The same as that used by
13549!            MA28AD. Unchanged by MA28BD.
13550! ..
13551     IMPLICIT NONE
13552! ..
13553! .. Scalar Arguments ..
13554        INTEGER :: IFLAG, LICN, N, NZ
13555! ..
13556! .. Array Arguments ..
13557        KPP_REAL :: A(LICN), W(N)
13558        INTEGER :: ICN(LICN), IKEEP(N,5), IVECT(NZ), IW(N,5), JVECT(NZ)
13559! ..
13560! .. Local Scalars ..
13561        INTEGER :: I1, IDUP, IEND
13562! ..
13563! .. FIRST EXECUTABLE STATEMENT MA28BD
13564! ..
13565!       Check to see if elements were dropped in previous MA28AD call.
13566        IF (NDROP==0) GOTO 10
13567        IFLAG = -15
13568        IF (LP/=0) WRITE (LP,90000) IFLAG, NDROP
13569        GOTO 70
1357010      IFLAG = 0
13571        MEPS = EPS
13572        NLP = LP
13573!       Simple data check on variables.
13574        IF (N>0) GOTO 20
13575        IFLAG = -11
13576        IF (LP/=0) WRITE (LP,90001) N
13577        GOTO 60
1357820      IF (NZ>0) GOTO 30
13579        IFLAG = -10
13580        IF (LP/=0) WRITE (LP,90002) NZ
13581        GOTO 60
1358230      IF (LICN>=NZ) GOTO 40
13583        IFLAG = -9
13584        IF (LP/=0) WRITE (LP,90003) LICN
13585        GOTO 60
13586
1358740      CALL MA28DD(N,A,LICN,IVECT,JVECT,NZ,ICN,IKEEP(1,1),IKEEP(1,4), &
13588          IKEEP(1,5),IKEEP(1,2),IKEEP(1,3),IW(1,3),IW,W(1),IFLAG)
13589!       THEMAX is largest element in matrix.
13590        THEMAX = W(1)
13591        IF (LBIG) BIG1 = THEMAX
13592!       IDUP equals one if there were duplicate elements, zero otherwise.
13593        IDUP = 0
13594        IF (IFLAG==(N+1)) IDUP = 1
13595        IF (IFLAG<0) GOTO 60
13596
13597!       Perform row Gauss elimination on the structure received from MA28DD.
13598        CALL MA30BD(N,ICN,A,LICN,IKEEP(1,1),IKEEP(1,4),IDISP,IKEEP(1,2), &
13599          IKEEP(1,3),W,IW,IFLAG)
13600
13601!       Transfer private variable information.
13602        IF (LBIG) BIG1 = BIG
13603!       RMIN = MRMIN
13604        IF (IFLAG>=0) GOTO 50
13605        IFLAG = -2
13606        IF (LP/=0) WRITE (LP,90004)
13607        GOTO 60
13608
13609!       Optionally calculate the growth parameter.
1361050      I1 = IDISP(1)
13611        IEND = LICN - I1 + 1
13612        IF (GROW) CALL MC24AD(N,ICN,A(I1),IEND,IKEEP,IKEEP(1,4),W)
13613!       Increment estimate by largest element in input matrix.
13614        IF (GROW) W(1) = W(1) + THEMAX
13615        IF (GROW .AND. N>1) W(2) = THEMAX
13616!       Set flag if the only error is due to duplicate elements.
13617        IF (IDUP==1 .AND. IFLAG>=0) IFLAG = -14
13618        GOTO 70
1361960      IF (LP/=0) WRITE (LP,90005)
1362070      RETURN
1362190000   FORMAT (' Error return from MA28BD with IFLAG = ',I4/I7, &
13622          ' Entries dropped from structure by MA28AD')
1362390001   FORMAT (' N is out of range = ',I10)
1362490002   FORMAT (' NZ is non positive = ',I10)
1362590003   FORMAT (' LICN is too small = ',I10)
1362690004   FORMAT (' Error return from MA30BD')
1362790005   FORMAT (' + Error return from MA28BD')
13628
13629      END SUBROUTINE MA28BD
13630!_______________________________________________________________________
13631
13632      SUBROUTINE MA28DD(N,A,LICN,IVECT,JVECT,NZ,ICN,LENR,LENRL,LENOFF, &
13633        IP,IQ,IW1,IW,W1,IFLAG)
13634! ..
13635! This subroutine need never be called by the user directly. It sorts
13636! the user's matrix into the structure of the decomposed form and checks
13637! for the presence of duplicate entries or non-zeros lying outside the
13638! sparsity pattern of the decomposition. It also calculates the largest
13639! element in the input matrix.
13640! ..
13641     IMPLICIT NONE
13642! ..
13643! .. Scalar Arguments ..
13644        KPP_REAL :: W1
13645        INTEGER :: IFLAG, LICN, N, NZ
13646! ..
13647! .. Array Arguments ..
13648        KPP_REAL :: A(LICN)
13649        INTEGER :: ICN(LICN), IP(N), IQ(N), IVECT(NZ), IW(N,2), IW1(N,3), &
13650          JVECT(NZ), LENOFF(N), LENR(N), LENRL(N)
13651! ..
13652! .. Local Scalars ..
13653        KPP_REAL :: AA
13654        INTEGER :: I, IBLOCK, IDISP2, IDUMMY, II, INEW, IOLD, J1, J2, JCOMP, &
13655          JDUMMY, JJ, JNEW, JOLD, MIDPT
13656        LOGICAL :: BLOCKL
13657! ..
13658! .. Intrinsic Functions ..
13659        INTRINSIC ABS, IABS, MAX
13660! ..
13661! .. FIRST EXECUTABLE STATEMENT MA28DD
13662! ..
13663        BLOCKL = LENOFF(1) >= 0
13664!       IW1(I,3) is set to the block in which row I lies and the
13665!       inverse permutations to IP and IQ are set in IW1(:,1) and
13666!       IW1(:,2), respectively.
13667!       Pointers to beginning of the part of row I in diagonal and
13668!       off-diagonal blocks are set in IW(I,2) and IW(I,1),
13669!       respectively.
13670        IBLOCK = 1
13671        IW(1,1) = 1
13672        IW(1,2) = IDISP(1)
13673        DO 10 I = 1, N
13674          IW1(I,3) = IBLOCK
13675          IF (IP(I)<0) IBLOCK = IBLOCK + 1
13676          II = IABS(IP(I)+0)
13677!         II = IABS(IP(I))
13678          IW1(II,1) = I
13679          JJ = IQ(I)
13680          JJ = IABS(JJ)
13681          IW1(JJ,2) = I
13682          IF (I==1) GOTO 10
13683          IF (BLOCKL) IW(I,1) = IW(I-1,1) + LENOFF(I-1)
13684          IW(I,2) = IW(I-1,2) + LENR(I-1)
1368510      END DO
13686!       Place each non-zero in turn into its correct location in
13687!       the A/ICN array.
13688        IDISP2 = IDISP(2)
13689        DO 170 I = 1, NZ
13690!         Necessary to avoid reference to unassigned element of ICN.
13691          IF (I>IDISP2) GOTO 20
13692          IF (ICN(I)<0) GOTO 170
1369320        IOLD = IVECT(I)
13694          JOLD = JVECT(I)
13695          AA = A(I)
13696!         This is a dummy loop for following a chain of interchanges.
13697!         It will be executed NZ TIMES in total.
13698          DO IDUMMY = 1, NZ
13699!           Perform some validity checks on IOLD and JOLD.
13700            IF (IOLD<=N .AND. IOLD>0 .AND. JOLD<=N .AND. JOLD>0) GOTO 30
13701            IF (LP/=0) WRITE (LP,90000) I, A(I), IOLD, JOLD
13702            IFLAG = -12
13703            GOTO 180
1370430          INEW = IW1(IOLD,1)
13705            JNEW = IW1(JOLD,2)
13706!           Are we in a valid block and is it diagonal or off-diagonal?
13707!           IF (IW1(INEW,3)-IW1(JNEW,3)) 40, 60, 50
13708!40         IFLAG = -13
13709            IF (IW1(INEW,3)-IW1(JNEW,3) == 0) GOTO 60
13710            IF (IW1(INEW,3)-IW1(JNEW,3) > 0) GOTO 50
13711            IFLAG = -13
13712            IF (LP/=0) WRITE (LP,90001) IOLD, JOLD
13713            GOTO 180
1371450          J1 = IW(INEW,1)
13715            J2 = J1 + LENOFF(INEW) - 1
13716            GOTO 110
13717!           Element is in diagonal block.
1371860          J1 = IW(INEW,2)
13719            IF (INEW>JNEW) GOTO 70
13720            J2 = J1 + LENR(INEW) - 1
13721            J1 = J1 + LENRL(INEW)
13722            GOTO 110
1372370          J2 = J1 + LENRL(INEW)
13724!           Binary search of ordered list. Element in L part of row.
13725            DO 100 JDUMMY = 1, N
13726              MIDPT = (J1+J2)/2
13727              JCOMP = IABS(ICN(MIDPT)+0)
13728!             JCOMP = IABS(ICN(MIDPT))
13729!             IF (JNEW-JCOMP) 80, 130, 90
13730!80           J2 = MIDPT
13731              IF (JNEW-JCOMP == 0) GOTO 130
13732              IF (JNEW-JCOMP > 0) GOTO 90
13733              J2 = MIDPT
13734              GOTO 100
1373590            J1 = MIDPT
13736100         END DO
13737            IFLAG = -13
13738            IF (LP/=0) WRITE (LP,90002) IOLD, JOLD
13739            GOTO 180
13740!           Linear search. Element in L part of row or off-diagonal blocks.
13741110         DO MIDPT = J1, J2
13742              IF (IABS(ICN(MIDPT)+0)==JNEW) GOTO 130
13743!             IF (IABS(ICN(MIDPT))==JNEW) GOTO 130
13744            END DO
13745            IFLAG = -13
13746            IF (LP/=0) WRITE (LP,90002) IOLD, JOLD
13747            GOTO 180
13748!           Equivalent element of ICN is in position MIDPT.
13749130         IF (ICN(MIDPT)<0) GOTO 160
13750            IF (MIDPT>NZ .OR. MIDPT<=I) GOTO 150
13751            W1 = A(MIDPT)
13752            A(MIDPT) = AA
13753            AA = W1
13754            IOLD = IVECT(MIDPT)
13755            JOLD = JVECT(MIDPT)
13756            ICN(MIDPT) = -ICN(MIDPT)
13757          END DO
13758150       A(MIDPT) = AA
13759          ICN(MIDPT) = -ICN(MIDPT)
13760          GOTO 170
13761160       A(MIDPT) = A(MIDPT) + AA
13762!        Set flag for duplicate elements.
13763          iflag = n + 1
13764170     END DO
13765!       Reset ICN array and zero elements in LU but not in A.
13766!       Also calculate the maximum element of A.
13767180     W1 = ZERO
13768        DO 200 I = 1, IDISP2
13769          IF (ICN(I)<0) GOTO 190
13770          A(I) = ZERO
13771          GOTO 200
13772190       ICN(I) = -ICN(I)
13773          W1 = MAX(W1,ABS(A(I)))
13774200     END DO
13775        RETURN
1377690000   FORMAT (' Element ',I6,' with value ',D22.14,' has indices ',I8, &
13777          ','/I8,' indices out of range')
1377890001   FORMAT (' Non-zero ',I7,',',I6,' in zero off-diagonal',' block')
1377990002   FORMAT (' Element ',I6,',',I6,' was not in LU pattern')
13780
13781      END SUBROUTINE MA28DD
13782!_______________________________________________________________________
13783
13784      SUBROUTINE MA28CD(N,A,LICN,ICN,IKEEP,RHS,W,MTYPE)
13785! ..
13786! This subroutine uses the factors from MA28AD or MA28BD to solve a
13787! system of equations without iterative refinement.
13788! ..
13789! The parameters are:
13790! N     Order of matrix. Not altered by subroutine.
13791! A     array of length LICN. the same array as
13792!       was used in the most recent call to MA28AD or MA28BD.
13793! LICN  Length of arrays A and ICN. Not altered by subroutine.
13794! ICN   Array of length LICN. Same array as output from
13795!       MA28AD. Unchanged by MA30CD.
13796! IKEEP Array of length 5*N. Same array as output from
13797!       MA28AD. Unchanged by MA30CD.
13798! RHS   Array of length N. On entry, it holds the
13799!       right hand side, on exit, the solution vector.
13800! W     Array of length N. Used as workspace by MA30CD.
13801! MTYPE Integer used to tell MA30CD to solve the direct
13802!       equation (MTYPE = 1) or its transpose (MTYPE /= 1).
13803
13804! Private Variable Information.
13805! Unless otherwise stated private variables are as in MA28AD.
13806! Those variables referenced by MA30CD are mentioned below.
13807! RESID   Variable which returns maximum residual of
13808!         equations where pivot was zero.
13809! MRESID  Variable used by MA30CD to communicate between
13810!         MA28FD and MA30HD.
13811! IDISP   Integer array of length 2. The same as that used
13812!         by MA28AD. Unchanged by MA28BD.
13813! ..
13814     IMPLICIT NONE
13815! ..
13816! .. Scalar Arguments ..
13817        INTEGER :: LICN, MTYPE, N
13818! ..
13819! .. Array Arguments ..
13820        KPP_REAL :: A(LICN), RHS(N), W(N)
13821        INTEGER :: ICN(LICN), IKEEP(N,5)
13822! ..
13823! .. FIRST EXECUTABLE STATEMENT MA28CD
13824! ..
13825!       This call performs the solution of the set of equations.
13826        CALL MA30CD(N,ICN,A,LICN,IKEEP(1,1),IKEEP(1,4),IKEEP(1,5),IDISP, &
13827          IKEEP(1,2),IKEEP(1,3),RHS,W,MTYPE)
13828!       Transfer private variable information.
13829        RESID = MRESID
13830        RETURN
13831
13832      END SUBROUTINE MA28CD
13833!_______________________________________________________________________
13834
13835      SUBROUTINE MA28ID(N,NZ,AORG,IRNORG,ICNORG,LICN,A,ICN,IKEEP,RHS, &
13836        X,R,W,MTYPE,PREC,IFLAG)
13837! ..
13838! This subroutine uses the factors from an earlier call to MA28AD or
13839! MA28BD to solve the system of equations with iterative refinement.
13840! ..
13841! The parameters are:
13842! N      Order of the matrix. Not altered by the subroutine.
13843! NZ     Number of entries in the original matrix. Not altered by
13844!        the subroutine.
13845!        For this entry the original matrix must have been saved in
13846!        AORG, IRNORG, ICNORG where entry AORG(K) is in row IRNORG(K)
13847!        and column ICNORG(K),K = 1,...,NZ. Information about the
13848!        factors of A is communicated to this subroutine via the
13849!        parameters LICN, A, ICN and IKEEP where:
13850! AORG   Array of length NZ. Not altered by MA28ID.
13851! IRNORG Array of length NZ. Not altered by MA28ID.
13852! ICNORG Array of length NZ. Not altered by MA28ID.
13853! LICN   Length of arrays A and ICN. Not altered by the subroutine.
13854! A      Array of length LICN. It must be unchanged since the
13855!        last call to MA28AD or MA28BD. Not altered by the
13856!        subroutine.
13857! ICN, IKEEP are the arrays (of lengths LICN and 5*N, respectively)
13858!        of the same names as in the previous all to MA28AD. They
13859!        should be unchanged since this earlier call and they are
13860!        not altered by MA28ID.
13861! The other parameters are as follows:
13862! RHS    Array of length N. The user must set RHS(I) to contain
13863!        the value of the Ith component of the right hand side.
13864!        Not altered by MA28ID.
13865! X      Array of length N. If an initial guess of the solution
13866!        is given (ISTART equal to 1), then the user must set X(I)
13867!        to contain the value of the Ith component of the estimated
13868!        solution. On exit, X(I) contains the Ith component of the
13869!        solution vector.
13870! R      Array of length N. It need not be set on entry. On exit,
13871!        R(I) contains the Ith component of an estimate of the error
13872!        if MAXIT is greater than 0.
13873! W      Array of length N. Used as workspace by MA28ID.
13874! MTYPE  Must be set to determine whether MA28ID will solve A*X = RHS
13875!        (MTYPE = 1) or AT*X = RHS (MTYPE /= 1). Not altered by MA28ID.
13876! PREC   Should be set by the user to the relative accuracy required.
13877!        The iterative refinement will terminate if the magnitude of
13878!        the largest component of the estimated error relative to the
13879!        largest component in the solution is less than PREC.
13880!        Not altered by MA28ID.
13881! IFLAG  Diagnostic flag which will be set to zero on successful
13882!        exit from MA28ID. Otherwise it will have a non-zero value.
13883!        The non-zero value IFLAG can have on exit from MA28ID are
13884!        -16 indicating that more than MAXIT iteartions are required.
13885!        -17 indicating that more convergence was too slow.
13886! ..
13887     IMPLICIT NONE
13888! ..
13889! .. Scalar Arguments ..
13890        KPP_REAL :: PREC
13891        INTEGER :: IFLAG, LICN, MTYPE, N, NZ
13892! ..
13893! .. Array Arguments ..
13894        KPP_REAL :: A(LICN), AORG(NZ), R(N), RHS(N), W(N), X(N)
13895        INTEGER :: ICN(LICN), ICNORG(NZ), IKEEP(N,5), IRNORG(NZ)
13896! ..
13897! .. Local Scalars ..
13898        KPP_REAL :: CONVER, D, DD
13899        INTEGER :: I, ITERAT, NCOL, NROW
13900! ..
13901! .. Intrinsic Functions ..
13902        INTRINSIC ABS, MAX
13903! ..
13904! .. FIRST EXECUTABLE STATEMENT MA28ID
13905! ..
13906!       Initialization of NOITER, ERRMAX, and IFLAG.
13907        NOITER = 0
13908        ERRMAX = ZERO
13909        IFLAG = 0
13910
13911!       Jump if a starting vector has been supplied by the user.
13912
13913        IF (ISTART==1) GOTO 20
13914
13915!       Make a copy of the right-hand side vector.
13916
13917        X(1:N) = RHS(1:N)
13918
13919!       Find the first solution.
13920
13921        CALL MA28CD(N,A,LICN,ICN,IKEEP,X,W,MTYPE)
13922
13923!       Stop the computations if MAXIT = 0.
13924
1392520      IF (MAXIT==0) GOTO 160
13926
13927!       Calculate the max-norm of the first solution.
13928
13929        DD = 0.0
13930        DO I = 1, N
13931          DD = MAX(DD,ABS(X(I)))
13932        END DO
13933        DXMAX = DD
13934
13935!       Begin the iterative process.
13936
13937        DO 120 ITERAT = 1, MAXIT
13938          D = DD
13939
13940!         Calculate the residual vector.
13941
13942          R(1:N) = RHS(1:N)
13943          IF (MTYPE==1) GOTO 60
13944          DO I = 1, NZ
13945            NROW = IRNORG(I)
13946            NCOL = ICNORG(I)
13947            R(NCOL) = R(NCOL) - AORG(I)*X(NROW)
13948          END DO
13949          GOTO 80
13950!         MTYPE = 1.
1395160        DO I = 1, NZ
13952            NROW = IRNORG(I)
13953            NCOL = ICNORG(I)
13954            R(NROW) = R(NROW) - AORG(I)*X(NCOL)
13955          END DO
1395680        DRES = 0.0
13957
13958!         Find the max-norm of the residual vector.
13959
13960          DO I = 1, N
13961            DRES = MAX(DRES,ABS(R(I)))
13962          END DO
13963
13964!         Stop the calculations if the max-norm of
13965!         the residual vector is zero.
13966
13967!         IF (DRES == 0.0) GOTO 150
13968          IF (ABS(DRES)<=ZERO) GOTO 150
13969
13970!         Calculate the correction vector.
13971
13972          NOITER = NOITER + 1
13973          CALL MA28CD(N,A,LICN,ICN,IKEEP,R,W,MTYPE)
13974
13975!         Find the max-norm of the correction vector.
13976
13977          DD = 0.0
13978          DO I = 1, N
13979            DD = MAX(DD,ABS(R(I)))
13980          END DO
13981
13982!         Check the convergence.
13983
13984          IF (DD>D*CGCE .AND. ITERAT>=2) GOTO 130
13985          IF (ABS((DXMAX*TEN+DD)-(DXMAX*TEN))<=ZERO) GOTO 140
13986
13987!         Attempt to improve the solution.
13988
13989          DXMAX = 0.0
13990          DO I = 1, N
13991            X(I) = X(I) + R(I)
13992            DXMAX = MAX(DXMAX,ABS(X(I)))
13993          END DO
13994
13995!         Check the stopping criterion.
13996 
13997          IF (DD<PREC*DXMAX) GOTO 140
13998120     END DO
13999!       More than MAXIT iterations required.
14000        IFLAG = -16
14001        WRITE (LP,90000) IFLAG, MAXIT
14002        GOTO 140
14003!       Convergence rate unacceptably slow.
14004130     IFLAG = -17
14005        CONVER = DD/D
14006        WRITE (LP,90001) IFLAG, CONVER, CGCE
14007
14008!       The iterative process is terminated.
14009
14010140     ERRMAX = DD
14011150     CONTINUE
14012160     RETURN
1401390000   FORMAT (' Error return from MA28ID with IFLAG = ',I3/' More than ', &
14014          I5,' iterations required')
1401590001   FORMAT (' Error return from MA28I with IFLAG = ', &
14016          I3/' Convergence rate of ',1P,E9.2,' too slow'/ &
14017          ' Maximum acceptable rate set to ',1P,E9.2)
14018
14019      END SUBROUTINE MA28ID
14020!_______________________________________________________________________
14021
14022! Private Variable Information.
14023! LP, MP are used by the subroutine as the unit numbers for its warning
14024!     and diagnostic messages. Default value for both is 6 (for line
14025!     printer output). The user can either reset them to a different
14026!     stream number or suppress the output by setting them to zero.
14027!     While LP directs the output of error diagnostics from the
14028!     principal subroutines and internally called subroutines, MP
14029!     controls only the output of a message which warns the user that
14030!     he has input two or more non-zeros A(I),. .,A(K) with the same
14031!     row and column indices. The action taken in this case is to
14032!     proceed using a numerical value of A(I)+...+A(K). In the absence
14033!     of other errors, IFLAG will equal -14 on exit.
14034! LBLOCK Is a logical variable which controls an option of first
14035!     preordering the matrix to block lower triangular form (using
14036!     Harwell subroutine MC23A). The preordering is performed if LBLOCK
14037!     is equal to its default value of .TRUE. If LBLOCK is set to
14038!     .FALSE., the option is not invoked and the space allocated to
14039!     IKEEP can be reduced to 4*N+1.
14040! GROW is a logical variable. If it is left at its default value of
14041!     .TRUE., then on return from MA28AD or MA28BD, W(1) will give
14042!     an estimate (an upper bound) of the increase in size of elements
14043!     encountered during the decomposition. If the matrix is well
14044!     scaled, then a high value for W(1), relative to the largest entry
14045!     in the input matrix, indicates that the LU decomposition may be
14046!     inaccurate and the user should be wary of his results and perhaps
14047!     increase U for subsequent runs. We would like to emphasise that
14048!     this value only relates to the accuracy of our LU decomposition
14049!     and gives no indication as to the singularity of the matrix or the
14050!     accuracy of the solution. This upper bound can be a significant
14051!     overestimate particularly if the matrix is badly scaled. If an
14052!     accurate value for the growth is required, LBIG(Q.V.) should be
14053!     set to .TRUE.
14054! EPS, RMIN If, on entry to MA28BD, EPS is less than one, then RMIN
14055!     will give the smallest ratio of the pivot to the largest element
14056!     in the corresponding row of the upper triangular factor thus
14057!     monitoring the stability of successive factorizations. If RMIN
14058!     becomes very large and W(1) from MA28BD is also very large, it
14059!     may be advisable to perform a new decomposition using MA28AD.
14060! RESID Variable which on exit from MA30CD gives the value of the
14061!     maximum residual over all the equations unsatisfied because
14062!     of dependency (zero pivots).
14063! IRNCP, ICNCP Variables which monitor the adequacy of "elbow room"
14064!     in IRN and A/ICN, respectively. If either is quite large (say
14065!     greater than N/10), it will probably pay to increase the size of
14066!     the corresponding array for subsequent runs. If either is very low
14067!     or zero, then one can perhaps save storage by reducing the size of
14068!     the corresponding array.
14069! MINIRN, MINICN Integer variables which, in the event of a successful
14070!     return (IFLAG >= 0 or IFLAG = -14) give the minimum size of IRN
14071!     and A/ICN, respectively which would enable a successful run on
14072!     an identical matrix. On an exit with IFLAG equal to -5, MINICN
14073!     gives the minimum value of ICN for success on subsequent runs on
14074!     an identical matrix. In the event of failure with IFLAG = -6,-4,
14075!     -3,-2, OR -1, then MINICN and MINIRN give the minimum value of
14076!     LICN and LIRN, respectively which would be required for a
14077!     successful decomposition up to the point at which the failure
14078!     occurred.
14079! IRANK Integer variable which gives an upper bound on the rank of
14080!     the matrix.
14081! ABORT1 is a logical variable with default value .TRUE. If ABORT1 is
14082!     set to .FALSE., then MA28AD will decompose structurally singular
14083!     matrices (including rectangular ones).
14084! ABORT2 is a logical variable with default value .TRUE. If ABORT2 is
14085!     set to .FALSE., then MA28AD will decompose numerically singular
14086!     matrices.
14087! IDISP is an integer array of length 2. On output from MA28AD, The
14088!     indices of the diagonal blocks of the factors lie in positions
14089!     IDISP(1) to IDISP(2) of A/ICN. This array must be preserved
14090!     between a call to MA28AD and subsequent calls to MA28BD,
14091!     MA30CD or MA28ID.
14092! TOL If set to a positive value, then any non-zero whose modulus is
14093!     less than TOL will be dropped from the factorization. The
14094!     factorization will then require less storage but will be
14095!     inaccurate. After a run of MA28AD with TOL positive it is not
14096!     possible to use MA28BD and the user is recommended to use
14097!     MA28ID to obtain the solution. The default value for TOL is 0.0.
14098! THEMAX On exit from MA28AD, THEMAX will hold the largest entry of
14099!     the original matrix.
14100! BIG If LBIG has been set to .TRUE., BIG will hold the largest entry
14101!     encountered during the factorization by MA28AD or MA28BD.
14102! DXMAX On exit from MA28ID, DXMAX will be set to the largest component
14103!     of the solution.
14104! ERRMAX If MAXIT is positive, ERRMAX will be set to the largest
14105!     component in the estimate of the error.
14106! DRES On exit from MA28ID, if MAXIT is positive, DRES will be set to
14107!     the largest component of the residual.
14108! CGCE Used by MA28ID to check the convergence rate. If the ratio of
14109!     successive corrections is not less than CGCE, then we terminate
14110!     since the convergence rate is adjudged too slow.
14111! NDROP If TOL has been set positive on exit from MA28AD, NDROP will
14112!     hold the number of entries dropped from the data structure.
14113! MAXIT Maximum number of iterations performed by MA28ID. Default = 16.
14114! NOITER Set by MA28ID to the number of iterative refinement iterations
14115!     actually used.
14116! NSRCH If NSRCH is set to a value less than N, then a different pivot
14117!     option will be employed by MA28AD. This may result in different
14118!     fill-in and execution time for MA28AD. If NSRCH is less than or
14119!     equal to N, the workspace array IW can be reduced in length. The
14120!     default value for NSRCH is 32768.
14121! ISTART If ISTART is set to a value other than zero, then the user
14122!     must supply an estimate of the solution to MA28ID. The default
14123!     value for istart is zero.
14124! LBIG If LBIG is set to .TRUE., the value of the largest element
14125!     encountered in the factorization by MA28AD or MA28BD is returned
14126!     in BIG. Setting LBIG to .TRUE. will increase the time for MA28AD
14127!     marginally and that for MA28BD by about 20%. The default value
14128!     for LBIG is .FALSE.
14129!_______________________________________________________________________
14130
14131      SUBROUTINE MA30AD(NN,ICN,A,LICN,LENR,LENRL,IDISP,IP,IQ,IRN,LIRN, &
14132        LENC,IFIRST,LASTR,NEXTR,LASTC,NEXTC,IPTR,IPC,U,IFLAG)
14133! ..
14134!     If the user requires a more convenient data interface then the
14135!     MA28 package should be used. The MA28 subroutines call the MA30
14136!     subroutines after checking the user's input data and optionally
14137!     using MC23AD to permute the matrix to block triangular form.
14138!     This package of subroutines (MA30AD, MA30BD, MA30CD, and MA30DD)
14139!     performs operations pertinent to the solution of a general
14140!     sparse N by N system of linear equations (i.e., solve
14141!     AX = B). Structually singular matrices are permitted including
14142!     those with row or columns consisting entirely of zeros (i.e.,
14143!     including rectangular matrices). It is assumed that the
14144!     non-zeros of the matrix A do not differ widely in size. If
14145!     necessary a prior call of the scaling subroutine MA19AD may be
14146!     made.
14147!     A discussion of the design of these subroutines is given by Duff
14148!     and Reid (ACM TRANS MATH SOFTWARE 5 PP 18-35, 1979(CSS 48)) while
14149!     fuller details of the implementation are given in duff (HARWELL
14150!     REPORT AERE-R 8730, 1977). The additional pivoting option in
14151!     ma30ad and the use of drop tolerances (see private variables for
14152!     MA30ID) were added to the package after joint work with Reid,
14153!     Schaumburg, Wasniewski and Zlatev (Duff, Reid, Schaumburg,
14154!     Wasniewski and Zlatev, HARWELL REPORT CSS 135, 1983).
14155
14156!     MA30AD performs the LU decomposition of the diagonal blocks of
14157!     the permutation PAQ of a sparse matrix A, where input permutations
14158!     P1 and Q1 are used to define the diagonal blocks. There may be
14159!     non-zeros in the off-diagonal blocks but they are unaffected by
14160!     MA30AD. P and P1 differ only within blocks as do Q and Q1. The
14161!     permutations P1 and Q1 may be found by calling MC23AD or the
14162!     matrix may be treated as a single block by using P1 = Q1 = I. The
14163!     matrix non-zeros should be held compactly by rows, although it
14164!     should be noted that the user can supply the matrix by columns
14165!     to get the LU decomposition of A transpose.
14166
14167!     This description should also be consulted for further information
14168!     on most of the parameters of MA30BD and MA30CD.
14169!     The parameters are:
14170! N   is an integer variable which must be set by the user to the order
14171!     of the matrix. It is not altered by MA30AD.
14172! ICN is an integer array of length LICN. Positions IDISP(2) to
14173!     LICN must be set by the user to contain the column indices of
14174!     the non-zeros in the diagonal blocks of P1*A*Q1. Those belonging
14175!     to a single row must be contiguous but the ordering of column
14176!     indices with each row is unimportant. The non-zeros of row I
14177!     precede those of row I+1,I = 1,...,N-1 and no wasted space is
14178!     allowed between the rows. On output the column indices of the
14179!     LU decomposition of PAQ are held in positions IDISP(1) to
14180!     IDISP(2), the rows are in pivotal order, and the column indices
14181!     of the L Part of each row are in pivotal order and precede those
14182!     of U. Again there is no wasted space either within a row or
14183!     between the rows. ICN(1) to ICN(IDISP(1)-1), are neither
14184!     required nor altered. If MC23AD has been called, these will hold
14185!     information about the off-diagonal blocks.
14186! A   Array of length LICN whose entries IDISP(2) to LICN must be set
14187!     by the user to the values of the non-zero entries of the matrix
14188!     in the order indicated by ICN. On output A will hold the LU
14189!     factors of the matrix where again the position in the matrix
14190!     is determined by the corresponding values in ICN.
14191!     A(1) to A(IDISP(1)-1) are neither required nor altered.
14192! LICN is an integer variable which must be set by the user to the
14193!     length of arrays ICN and A. It must be big enough for A and ICN
14194!     to hold all the non-zeros of L and U and leave some "elbow
14195!     room". It is possible to calculate a minimum value for LICN by
14196!     a preliminary run of MA30AD. The adequacy of the elbow room
14197!     can be judged by the size of the private variable ICNCP.
14198!     It is not altered by MA30AD.
14199! LENR is an integer array of length N. On input, LENR(I) should
14200!     equal the number of non-zeros in row I,I = 1,...,N of the
14201!     diagonal blocks of P1*A*Q1. On output, LENR(I) will equal the
14202!     total number of non-zeros in row I of L and row I of U.
14203! LENRL is an integer array of length N. On output from MA30AD,
14204!     LENRL(I) will hold the number of non-zeros in row I of L.
14205! IDISP is an integer array of length 2. The user should set IDISP(1)
14206!     to be the first available position in A/ICN for the LU
14207!     decomposition while IDISP(2) is set to the position in A/ICN of
14208!     the first non-zero in the diagonal blocks of P1*A*Q1. On output,
14209!     IDISP(1) will be unaltered while IDISP(2) will be set to the
14210!     position in A/ICN of the last non-zero of the LU decomposition.
14211! IP  is an integer array of length N which holds a permutation of
14212!     the integers 1 to N. On input to MA30AD, the absolute value of
14213!     IP(I) must be set to the row of A which is row I of P1*A*Q1. A
14214!     negative value for IP(I) indicates that row I is at the end of a
14215!     diagonal block. On output from MA30AD, IP(I) indicates the row
14216!     of A which is the Ith row in PAQ. IP(I) will still be negative
14217!     for the last row of each block (except the last).
14218! IQ  is an integer array of length N which again holds a
14219!     permutation of the integers 1 to N. On input to MA30AD, IQ(J)
14220!     must be set to the column of A which is column J of P1*A*Q1. On
14221!     output from MA30AD, the absolute value of IQ(J) indicates the
14222!     column of A which is the Jth in PAQ. For rows, I say, in which
14223!     structural or numerical singularity is detected IQ(I) is
14224!     negated.
14225! IRN is an integer array of length LIRN used as workspace by
14226!     MA30AD.
14227! LIRN is an integer variable. It should be greater than the
14228!     largest number of non-zeros in a diagonal block of P1*A*Q1 but
14229!     need not be as large as LICN. It is the length of array IRN and
14230!     should be large enough to hold the active part of any block,
14231!     plus some "elbow room", the a posteriori adequacy of which can
14232!     be estimated by examining the size of private variable
14233!     IRNCP.
14234! LENC, FIRST, LASTR, NEXTR, LASTC, NEXTC are all integer arrays of
14235!     length N which are used as workspace by MA30AD. If NSRCH is
14236!     set to a value less than or equal to N, then arrays LASTC and
14237!     NEXTC are not referenced by MA30AD and so can be dummied in
14238!     the call to MA30AD.
14239! IPTR, IPC are integer arrays of length N which are used as
14240!     workspace by MA30AD.
14241! U   is a real(kind=wp) variable which should be set by the user
14242!     to a value between 0. and 1.0. If less than zero it is reset
14243!     to zero and if its value is 1.0 or greater it is reset to
14244!     0.9999 (0.999999999 in D version). It determines the balance
14245!     between pivoting for sparsity and for stability, values near
14246!     zero emphasizing sparsity and values near one emphasizing
14247!     stability. We recommend U = 0.1 as a posible first trial value.
14248!     The stability can be judged by a later call to MC24AD or by
14249!     setting LBIG to .TRUE.
14250! IFLAG is an integer variable. It will have a non-negative value
14251!     if MA30AD is successful. Negative values indicate error
14252!     conditions while positive values indicate that the matrix has
14253!     been successfully decomposed but is singular. For each non-zero
14254!     value, an appropriate message is output on unit LP. Possible
14255!     non-zero values for IFLAG are
14256! -1  THe matrix is structurally singular with rank given by IRANK
14257!     in private variables for MA30FD.
14258! +1  If, however, the user wants the LU decomposition of a
14259!     structurally singular matrix and sets the private variable
14260!     ABORT1 to .FALSE., then, in the event of singularity and a
14261!     successful decomposition, Iflag is returned with the value +1
14262!     and no message is output.
14263! -2  The matrix is numerically singular (it may also be structurally
14264!     singular) with estimated rank given by IRANK in private variables
14265!     for MA30FD.
14266! +2  THE user can choose to continue the decomposition even when a
14267!     zero pivot is encountered by setting private variable
14268!     ABORT2 TO .FALSE. If a singularity is encountered, IFLAG will
14269!     then return with a value of +2, and no message is output if
14270!     the decomposition has been completed successfully.
14271! -3  LIRN has not been large enough to continue with the
14272!     decomposition. If the stage was zero then private variable
14273!     MINIRN gives the length sufficient to start the decomposition on
14274!     this block. FOr a successful decomposition on this block the
14275!     user should make LIRN slightly (say about N/2) greater than this
14276!     value.
14277! -4  LICN is not large enough to continue with the decomposition.
14278! -5  The decomposition has been completed but some of the LU factors
14279!     have been discarded to create enough room in A/ICN to continue
14280!     the decomposition. The variable MINICN in private variables for
14281!     MA30FD. Then gives the size that LICN should be to enable the
14282!     factorization to be successful. If the user sets private
14283!     variable ABORT3 to .TRUE., then the subroutine will exit
14284!     immediately instead of destroying any factors and continuing.
14285! -6  Both LICN and LIRN are too small. Termination has been caused
14286!     by lack of space in IRN (see error IFLAG = -3), but already
14287!     some of the LU factors in A/ICN have been lost (see error
14288!     IFLAG = -5). MINICN gives the minimum amount of space
14289!     required in A/ICN for decomposition up to this point.
14290! ..
14291     IMPLICIT NONE
14292! ..
14293! .. Scalar Arguments ..
14294        KPP_REAL :: U
14295        INTEGER :: IFLAG, LICN, LIRN, NN
14296! ..
14297! .. Array Arguments ..
14298        KPP_REAL :: A(LICN)
14299        INTEGER :: ICN(LICN), IDISP(2), IFIRST(NN), IP(NN), IPC(NN), &
14300          IPTR(NN), IQ(NN), IRN(LIRN), LASTC(NN), LASTR(NN),         &
14301          LENC(NN), LENR(NN), LENRL(NN), NEXTC(NN), NEXTR(NN)
14302! ..
14303! .. Local Scalars ..
14304        KPP_REAL :: AANEW, AMAX, ANEW, AU, PIVR, PIVRAT, SCALE
14305        INTEGER :: COLUPD, DISPC, I, I1, I2, IACTIV, IBEG, IDISPC,   &
14306          IDROP, IDUMMY, IEND, IFILL, IFIR, II, III, IJFIR, IJP1,    &
14307          IJPOS, ILAST, INDROW, IOP, IPIV, IPOS, IROWS, ISING, ISRCH,&
14308          ISTART, ISW, ISW1, ITOP, J, J1, J2, JBEG, JCOST, JCOUNT,   &
14309          JDIFF, JDUMMY, JEND, JJ, JMORE, JNEW, JNPOS, JOLD, JPIV,   &
14310          JPOS, JROOM, JVAL, JZER, JZERO, K, KCOST, KDROP, L, LC,    &
14311          LENPIV, LENPP, LL, LR, MOREI, MSRCH, N, NBLOCK, NC, NNM1,  &
14312          NR, NUM, NZ, NZ2, NZCOL, NZMIN, NZPC, NZROW, OLDEND,       &
14313          OLDPIV, PIVEND, PIVOT, PIVROW, ROWI
14314! ..
14315! .. Intrinsic Functions ..
14316        INTRINSIC ABS, IABS, MAX, MIN
14317! ..
14318! .. FIRST EXECUTABLE STATEMENT MA30AD
14319! ..
14320        MSRCH = NSRCH
14321        NDROP = 0
14322        LNPIV(1:10) = 0
14323        LPIV(1:10) = 0
14324        MAPIV = 0
14325        MANPIV = 0
14326        IAVPIV = 0
14327        IANPIV = 0
14328        KOUNTL = 0
14329        MINIRN = 0
14330        MINICN = IDISP(1) - 1
14331        MOREI = 0
14332        IRANK = NN
14333        IRNCP = 0
14334        ICNCP = 0
14335        IFLAG = 0
14336!       Reset U if necessary.
14337        U = MIN(U,UMAX)
14338!       IBEG is the position of the next pivot row after elimination
14339!       step using it.
14340        U = MAX(U,ZERO)
14341        IBEG = IDISP(1)
14342!       IACTIV is the position of the first entry in the active part
14343!       of A/ICN.
14344        IACTIV = IDISP(2)
14345!       NZROW is current number of non-zeros in active and unprocessed
14346!       part of row file ICN.
14347        NZROW = LICN - IACTIV + 1
14348        MINICN = NZROW + MINICN
14349
14350!       Count the number of diagonal blocks and set up pointers to the
14351!       beginnings of the rows. NUM is the number of diagonal blocks.
14352        NUM = 1
14353        IPTR(1) = IACTIV
14354        IF (NN==1) GOTO 30
14355        NNM1 = NN - 1
14356        DO I = 1, NNM1
14357          IF (IP(I)<0) NUM = NUM + 1
14358          IPTR(I+1) = IPTR(I) + LENR(I)
14359        END DO
14360!       ILAST is the last row in the previous block.
1436130      ILAST = 0
14362
14363! ***********************************************
14364! ****    LU decomposition of block NBLOCK   ****
14365! ***********************************************
14366
14367!       Each pass through this loop performs LU decomposition on one
14368!       of the diagonal blocks.
14369        DO 1070 NBLOCK = 1, NUM
14370          ISTART = ILAST + 1
14371          DO IROWS = ISTART, NN
14372            IF (IP(IROWS)<0) GOTO 50
14373          END DO
14374          IROWS = NN
1437550        ILAST = IROWS
14376!         N is the number of rows in the current block.
14377!         ISTART is the index of the first row in the current block.
14378!         ILAST is the index of the last row in the current block.
14379!         IACTIV is the position of the first entry in the block.
14380!         ITOP is the position of the last entry in the block.
14381          N = ILAST - ISTART + 1
14382          IF (N/=1) GOTO 100
14383
14384!         Code for dealing WITH 1x1 block.
14385          LENRL(ILAST) = 0
14386          ISING = ISTART
14387          IF (LENR(ILAST)/=0) GOTO 60
14388!         Block is structurally singular.
14389          IRANK = IRANK - 1
14390          ISING = -ISING
14391          IF (IFLAG/=2 .AND. IFLAG/=-5) IFLAG = 1
14392          IF (.NOT.ABORT1) GOTO 90
14393          IDISP(2) = IACTIV
14394          IFLAG = -1
14395          IF (LP/=0) WRITE (LP,90000)
14396!         RETURN
14397          GOTO 1190
1439860        SCALE = ABS(A(IACTIV))
14399          IF (ABS(SCALE)<=ZERO) GOTO 70
14400          IF (LBIG) BIG = MAX(BIG,SCALE)
14401          GOTO 80
1440270        ISING = -ISING
14403          IRANK = IRANK - 1
14404          IPTR(ILAST) = 0
14405          IF (IFLAG/=-5) IFLAG = 2
14406          IF (.NOT.ABORT2) GOTO 80
14407          IDISP(2) = IACTIV
14408          IFLAG = -2
14409          IF (LP/=0) WRITE (LP,90001)
14410          GOTO 1190
1441180        A(IBEG) = A(IACTIV)
14412          ICN(IBEG) = ICN(IACTIV)
14413          IACTIV = IACTIV + 1
14414          IPTR(ISTART) = 0
14415          IBEG = IBEG + 1
14416          NZROW = NZROW - 1
1441790        LASTR(ISTART) = ISTART
14418          IPC(ISTART) = -ISING
14419          GOTO 1070
14420
14421!         Non-trivial block.
14422100       ITOP = LICN
14423          IF (ILAST/=NN) ITOP = IPTR(ILAST+1) - 1
14424
14425!         Set up column oriented storage.
14426          LENRL(ISTART:ILAST) = 0
14427          LENC(ISTART:ILAST) = 0
14428          IF (ITOP-IACTIV<LIRN) GOTO 120
14429          MINIRN = ITOP - IACTIV + 1
14430          PIVOT = ISTART - 1
14431          GOTO 1170
14432
14433!         Calculate column counts.
14434120       DO II = IACTIV, ITOP
14435            I = ICN(II)
14436            LENC(I) = LENC(I) + 1
14437          END DO
14438!         Set up column pointers so that IPC(J) points to position
14439!         after end of column J in column file.
14440          IPC(ILAST) = LIRN + 1
14441          J1 = ISTART + 1
14442          DO JJ = J1, ILAST
14443            J = ILAST - JJ + J1 - 1
14444            IPC(J) = IPC(J+1) - LENC(J+1)
14445          END DO
14446          DO 160 INDROW = ISTART, ILAST
14447            J1 = IPTR(INDROW)
14448            J2 = J1 + LENR(INDROW) - 1
14449            IF (J1>J2) GOTO 160
14450            DO JJ = J1, J2
14451              J = ICN(JJ)
14452              IPOS = IPC(J) - 1
14453              IRN(IPOS) = INDROW
14454              IPC(J) = IPOS
14455            END DO
14456160       END DO
14457!         DISPC is the lowest indexed active location in the column file.
14458          DISPC = IPC(ISTART)
14459          NZCOL = LIRN - DISPC + 1
14460          MINIRN = MAX(NZCOL,MINIRN)
14461          NZMIN = 1
14462
14463!         Initialize array IFIRST. IFIRST(I) = +/- K indicates that
14464!         row/col K has I non-zeros. If IFIRST(I) = 0, there is no
14465!         row or column with I non-zeros.
14466          IFIRST(1:N) = 0
14467
14468!         Compute ordering of row and column counts.
14469!         First run through columns (from column N to column 1).
14470          DO 190 JJ = ISTART, ILAST
14471            J = ILAST - JJ + ISTART
14472            NZ = LENC(J)
14473            IF (NZ/=0) GOTO 180
14474            IPC(J) = 0
14475            GOTO 190
14476180         IF (NSRCH<=NN) GOTO 190
14477            ISW = IFIRST(NZ)
14478            IFIRST(NZ) = -J
14479            LASTC(J) = 0
14480            NEXTC(J) = -ISW
14481            ISW1 = IABS(ISW)
14482            IF (ISW/=0) LASTC(ISW1) = J
14483190       END DO
14484!        Now run through rows (again from N to 1).
14485          DO 220 II = ISTART, ILAST
14486               I = ILAST - II + ISTART
14487            NZ = LENR(I)
14488            IF (NZ/=0) GOTO 200
14489            IPTR(I) = 0
14490            LASTR(I) = 0
14491            GOTO 220
14492200         ISW = IFIRST(NZ)
14493            IFIRST(NZ) = I
14494            IF (ISW>0) GOTO 210
14495            NEXTR(I) = 0
14496            LASTR(I) = ISW
14497            GOTO 220
14498210         NEXTR(I) = ISW
14499            LASTR(I) = LASTR(ISW)
14500            LASTR(ISW) = I
14501220       END DO
14502
14503! **********************************************
14504! ****    Start of main elimination loop    ****
14505! **********************************************
14506          DO 1050 PIVOT = ISTART, ILAST
14507
14508!           First find the pivot using MARKOWITZ criterion with
14509!           stability control.
14510!           JCOST is the Markowitz cost of the best pivot so far.
14511!           This pivot is in row IPIV and column JPIV.
14512            NZ2 = NZMIN
14513            JCOST = N*N
14514
14515!           Examine rows/columns in order of ascending count.
14516            DO L = 1, 2
14517              PIVRAT = ZERO
14518              ISRCH = 1
14519              LL = L
14520!             A pass with L equal to 2 is only performed in the
14521!             case of singularity.
14522              DO 340 NZ = NZ2, N
14523                IF (JCOST<=(NZ-1)**2) GOTO 430
14524                IJFIR = IFIRST(NZ)
14525!               IF (IJFIR) 240, 230, 250
14526!230            IF (LL==1) NZMIN = NZ + 1
14527                IF (IJFIR < 0) GOTO 240
14528                IF (IJFIR > 0) GOTO 250
14529                IF (LL==1) NZMIN = NZ + 1
14530                GOTO 340
14531240             LL = 2
14532                IJFIR = -IJFIR
14533                GOTO 300
14534250             LL = 2
14535!               Scan rows with NZ non-zeros.
14536                DO IDUMMY = 1, N
14537                  IF (JCOST<=(NZ-1)**2) GOTO 430
14538                  IF (ISRCH>MSRCH) GOTO 430
14539                  IF (IJFIR==0) GOTO 290
14540!                 Row IJFIR is now examined.
14541                  I = IJFIR
14542                  IJFIR = NEXTR(I)
14543!                 First calculate multiplier threshold level.
14544                  AMAX = ZERO
14545                  J1 = IPTR(I) + LENRL(I)
14546                  J2 = IPTR(I) + LENR(I) - 1
14547                  DO JJ = J1, J2
14548                    AMAX = MAX(AMAX,ABS(A(JJ)))
14549                  END DO
14550                  AU = AMAX*U
14551                  ISRCH = ISRCH + 1
14552!                 Scan row for possible pivots.
14553                  DO 270 JJ = J1, J2
14554                    IF (ABS(A(JJ))<=AU .AND. L==1) GOTO 270
14555                    J = ICN(JJ)
14556                    KCOST = (NZ-1)*(LENC(J)-1)
14557                    IF (KCOST>JCOST) GOTO 270
14558                    PIVR = ZERO
14559                    IF (ABS(AMAX)>ZERO) PIVR = ABS(A(JJ))/AMAX
14560                    IF (KCOST==JCOST .AND. (PIVR<=PIVRAT .OR. NSRCH>NN+1)) &
14561                      GOTO 270
14562!                   Best pivot so far is found.
14563                    JCOST = KCOST
14564                    IJPOS = JJ
14565                    IPIV = I
14566                    JPIV = J
14567                    IF (MSRCH>NN+1 .AND. JCOST<=(NZ-1)**2) GOTO 430
14568                    PIVRAT = PIVR
14569270               END DO
14570                END DO
14571
14572!               Columns with NZ non-zeros now examined.
14573290             IJFIR = IFIRST(NZ)
14574                IJFIR = -LASTR(IJFIR)
14575300             IF (JCOST<=NZ*(NZ-1)) GOTO 430
14576                IF (MSRCH<=NN) GOTO 340
14577                DO 330 IDUMMY = 1, N
14578                  IF (IJFIR==0) GOTO 340
14579                  J = IJFIR
14580                  IJFIR = NEXTC(IJFIR)
14581                  I1 = IPC(J)
14582                  I2 = I1 + NZ - 1
14583!                 Scan column J.
14584                  DO 320 II = I1, I2
14585                    I = IRN(II)
14586                    KCOST = (NZ-1)*(LENR(I)-LENRL(I)-1)
14587                    IF (KCOST>=JCOST) GOTO 320
14588!                   Pivot has best Markowitz count so far. Now
14589!                   check its suitability on numeric grounds by
14590!                   examining the other non-zeros in its row.
14591                    J1 = IPTR(I) + LENRL(I)
14592                    J2 = IPTR(I) + LENR(I) - 1
14593!                   We need a stability check on singleton columns
14594!                   because of possible problems with
14595!                   underdetermined systems.
14596                    AMAX = ZERO
14597                    DO JJ = J1, J2
14598                      AMAX = MAX(AMAX,ABS(A(JJ)))
14599                      IF (ICN(JJ)==J) JPOS = JJ
14600                    END DO
14601                    IF (ABS(A(JPOS))<=AMAX*U .AND. L==1) GOTO 320
14602                    JCOST = KCOST
14603                    IPIV = I
14604                    JPIV = J
14605                    IJPOS = JPOS
14606                    IF (ABS(AMAX)>ZERO) PIVRAT = ABS(A(JPOS))/AMAX
14607                    IF (JCOST<=NZ*(NZ-1)) GOTO 430
14608320               END DO
14609330             END DO
14610340           END DO
14611!             In the event of singularity, we must make sure all
14612!             rows and columns are tested.
14613              MSRCH = N
14614
14615!             Matrix is numerically or structurally singular. Which
14616!             it is will be diagnosed later.
14617              IRANK = IRANK - 1
14618            END DO
14619!           Assign rest of rows and columns to ordering array.
14620!           Matrix is structurally singular.
14621            IF (IFLAG/=2 .AND. IFLAG/=-5) IFLAG = 1
14622            IRANK = IRANK - ILAST + PIVOT + 1
14623            IF (.NOT.ABORT1) GOTO 360
14624            IDISP(2) = IACTIV
14625            IFLAG = -1
14626            IF (LP/=0) WRITE (LP,90000)
14627            GOTO 1190
14628360         K = PIVOT - 1
14629            DO 400 I = ISTART, ILAST
14630              IF (LASTR(I)/=0) GOTO 400
14631              K = K + 1
14632              LASTR(I) = K
14633              IF (LENRL(I)==0) GOTO 390
14634              MINICN = MAX(MINICN,NZROW+IBEG-1+MOREI+LENRL(I))
14635              IF (IACTIV-IBEG>=LENRL(I)) GOTO 370
14636              CALL MA30DD(A,ICN,IPTR(ISTART),N,IACTIV,ITOP,.TRUE.)
14637!             Check now to see if MA30DD has created enough
14638!             available space.
14639              IF (IACTIV-IBEG>=LENRL(I)) GOTO 370
14640!             Create more space by destroying previously created
14641!             LU factors.
14642              MOREI = MOREI + IBEG - IDISP(1)
14643              IBEG = IDISP(1)
14644              IF (LP/=0) WRITE (LP,90002)
14645              IFLAG = -5
14646              IF (ABORT3) GOTO 1160
14647370           J1 = IPTR(I)
14648              J2 = J1 + LENRL(I) - 1
14649              IPTR(I) = 0
14650              DO JJ = J1, J2
14651                A(IBEG) = A(JJ)
14652                ICN(IBEG) = ICN(JJ)
14653                ICN(JJ) = 0
14654                IBEG = IBEG + 1
14655              END DO
14656              NZROW = NZROW - LENRL(I)
14657390           IF (K==ILAST) GOTO 410
14658400         END DO
14659410         K = PIVOT - 1
14660            DO 420 I = ISTART, ILAST
14661              IF (IPC(I)/=0) GOTO 420
14662              K = K + 1
14663              IPC(I) = K
14664              IF (K==ILAST) GOTO 1060
14665420         END DO
14666
14667!           The pivot has now been found in position (IPIV,JPIV)
14668!           in location IJPOS in row file.
14669!           Update column and row ordering arrays to correspond
14670!           with removal of the active part of the matrix.
14671430         ISING = PIVOT
14672            IF (ABS(A(IJPOS))>ZERO) GOTO 440
14673!           Numerical singularity is recorded here.
14674            ISING = -ISING
14675            IF (IFLAG/=-5) IFLAG = 2
14676            IF (.NOT.ABORT2) GOTO 440
14677            IDISP(2) = IACTIV
14678            IFLAG = -2
14679            IF (LP/=0) WRITE (LP,90001)
14680            GOTO 1190
14681440         OLDPIV = IPTR(IPIV) + LENRL(IPIV)
14682            OLDEND = IPTR(IPIV) + LENR(IPIV) - 1
14683!           Changes to column ordering.
14684            IF (NSRCH<=NN) GOTO 470
14685            COLUPD = NN + 1
14686            LENPP = OLDEND - OLDPIV + 1
14687            IF (LENPP<4) LPIV(1) = LPIV(1) + 1
14688            IF (LENPP>=4 .AND. LENPP<=6) LPIV(2) = LPIV(2) + 1
14689            IF (LENPP>=7 .AND. LENPP<=10) LPIV(3) = LPIV(3) + 1
14690            IF (LENPP>=11 .AND. LENPP<=15) LPIV(4) = LPIV(4) + 1
14691            IF (LENPP>=16 .AND. LENPP<=20) LPIV(5) = LPIV(5) + 1
14692            IF (LENPP>=21 .AND. LENPP<=30) LPIV(6) = LPIV(6) + 1
14693            IF (LENPP>=31 .AND. LENPP<=50) LPIV(7) = LPIV(7) + 1
14694            IF (LENPP>=51 .AND. LENPP<=70) LPIV(8) = LPIV(8) + 1
14695            IF (LENPP>=71 .AND. LENPP<=100) LPIV(9) = LPIV(9) + 1
14696            IF (LENPP>=101) LPIV(10) = LPIV(10) + 1
14697            MAPIV = MAX(MAPIV,LENPP)
14698            IAVPIV = IAVPIV + LENPP
14699            DO 460 JJ = OLDPIV, OLDEND
14700              J = ICN(JJ)
14701              LC = LASTC(J)
14702              NC = NEXTC(J)
14703              NEXTC(J) = -COLUPD
14704              IF (JJ/=IJPOS) COLUPD = J
14705              IF (NC/=0) LASTC(NC) = LC
14706              IF (LC==0) GOTO 450
14707              NEXTC(LC) = NC
14708              GOTO 460
14709450           NZ = LENC(J)
14710              ISW = IFIRST(NZ)
14711              IF (ISW>0) LASTR(ISW) = -NC
14712              IF (ISW<0) IFIRST(NZ) = -NC
14713460         END DO
14714!           Changes to row ordering.
14715470         I1 = IPC(JPIV)
14716            I2 = I1 + LENC(JPIV) - 1
14717            DO 490 II = I1, I2
14718              I = IRN(II)
14719              LR = LASTR(I)
14720              NR = NEXTR(I)
14721              IF (NR/=0) LASTR(NR) = LR
14722              IF (LR<=0) GOTO 480
14723              NEXTR(LR) = NR
14724              GOTO 490
14725480           NZ = LENR(I) - LENRL(I)
14726              IF (NR/=0) IFIRST(NZ) = NR
14727              IF (NR==0) IFIRST(NZ) = LR
14728490         END DO
14729
14730!           Move pivot to position LENRL+1 in pivot row and move pivot
14731!           row to the beginning of the available storage. The L part
14732!           and the pivot in the old copy of the pivot row is nullified
14733!           while, in the strictly upper triangular part, the column
14734!           indices, J say, are overwritten by the corresponding entry
14735!           of IQ (IQ(J)) and IQ(J) is set to the negative of the
14736!           displacement of the column index from the pivot entry.
14737            IF (OLDPIV==IJPOS) GOTO 500
14738            AU = A(OLDPIV)
14739            A(OLDPIV) = A(IJPOS)
14740            A(IJPOS) = AU
14741            ICN(IJPOS) = ICN(OLDPIV)
14742            ICN(OLDPIV) = JPIV
14743!           Check to see if there is space immediately available in
14744!           A/ICN to hold new copy of pivot row.
14745500         MINICN = MAX(MINICN,NZROW+IBEG-1+MOREI+LENR(IPIV))
14746            IF (IACTIV-IBEG>=LENR(IPIV)) GOTO 510
14747            CALL MA30DD(A,ICN,IPTR(ISTART),N,IACTIV,ITOP,.TRUE.)
14748            OLDPIV = IPTR(IPIV) + LENRL(IPIV)
14749            OLDEND = IPTR(IPIV) + LENR(IPIV) - 1
14750!           Check now to see if MA30DD has created enough
14751!           available space.
14752            IF (IACTIV-IBEG>=LENR(IPIV)) GOTO 510
14753!           Create more space by destroying previously created
14754!           LU factors.
14755            MOREI = MOREI + IBEG - IDISP(1)
14756            IBEG = IDISP(1)
14757            IF (LP/=0) WRITE (LP,90002)
14758            IFLAG = -5
14759            IF (ABORT3) GOTO 1160
14760            IF (IACTIV-IBEG>=LENR(IPIV)) GOTO 510
14761!           There is still not enough room in A/ICN.
14762            IFLAG = -4
14763            GOTO 1160
14764!           Copy pivot row and set up IQ array.
14765510         IJPOS = 0
14766            J1 = IPTR(IPIV)
14767
14768            DO JJ = J1, OLDEND
14769              A(IBEG) = A(JJ)
14770              ICN(IBEG) = ICN(JJ)
14771              IF (IJPOS/=0) GOTO 520
14772              IF (ICN(JJ)==JPIV) IJPOS = IBEG
14773              ICN(JJ) = 0
14774              GOTO 530
14775520           K = IBEG - IJPOS
14776              J = ICN(JJ)
14777              ICN(JJ) = IQ(J)
14778              IQ(J) = -K
14779530           IBEG = IBEG + 1
14780            END DO
14781
14782            IJP1 = IJPOS + 1
14783            PIVEND = IBEG - 1
14784            LENPIV = PIVEND - IJPOS
14785            NZROW = NZROW - LENRL(IPIV) - 1
14786            IPTR(IPIV) = OLDPIV + 1
14787            IF (LENPIV==0) IPTR(IPIV) = 0
14788
14789!           Remove pivot row (including pivot) from column
14790!           oriented file.
14791            DO JJ = IJPOS, PIVEND
14792              J = ICN(JJ)
14793              I1 = IPC(J)
14794              LENC(J) = LENC(J) - 1
14795!             I2 is last position in new column.
14796              I2 = IPC(J) + LENC(J) - 1
14797              IF (I2<I1) GOTO 560
14798              DO 550 II = I1, I2
14799                IF (IRN(II)/=IPIV) GOTO 550
14800                IRN(II) = IRN(I2+1)
14801                GOTO 560
14802550           END DO
14803560           IRN(I2+1) = 0
14804            END DO
14805            NZCOL = NZCOL - LENPIV - 1
14806
14807!           Go down the pivot column and for each row with a
14808!           non-zero add the appropriate multiple of the pivot
14809!           row to it. We loop on the number of non-zeros in
14810!           the pivot column since MA30DD may change its
14811!           actual position.
14812
14813            NZPC = LENC(JPIV)
14814            IF (NZPC==0) GOTO 940
14815            DO 880 III = 1, NZPC
14816              II = IPC(JPIV) + III - 1
14817              I = IRN(II)
14818!             Search row I For non-zero to be eliminated,
14819!             calculate multiplier, and place it in position
14820!             LENRL+1 in its row. IDROP is the number of
14821!             non-zero entries dropped from row I because
14822!             these fall beneath tolerance level.
14823              IDROP = 0
14824              J1 = IPTR(I) + LENRL(I)
14825              IEND = IPTR(I) + LENR(I) - 1
14826              DO 580 JJ = J1, IEND
14827                IF (ICN(JJ)/=JPIV) GOTO 580
14828!               IF pivot is zero, rest of column is and so
14829!               multiplier is zero.
14830                AU = ZERO
14831                IF (ABS(A(IJPOS))>ZERO) AU = -A(JJ)/A(IJPOS)
14832                IF (LBIG) BIG = MAX(BIG,ABS(AU))
14833                A(JJ) = A(J1)
14834                A(J1) = AU
14835                ICN(JJ) = ICN(J1)
14836                ICN(J1) = JPIV
14837                LENRL(I) = LENRL(I) + 1
14838                GOTO 590
14839580           END DO
14840!             JUMP if pivot row is a singleton.
14841590           IF (LENPIV==0) GOTO 880
14842!             Now perform necessary operations on rest of non-pivot
14843!             row I.
14844              ROWI = J1 + 1
14845              IOP = 0
14846!             Jump if all the pivot row causes fill-in.
14847              IF (ROWI>IEND) GOTO 670
14848!             Perform operations on current non-zeros in row I.
14849!             Innermost loop.
14850              LENPP = IEND - ROWI + 1
14851              IF (LENPP<4) LNPIV(1) = LNPIV(1) + 1
14852              IF (LENPP>=4 .AND. LENPP<=6) LNPIV(2) = LNPIV(2) + 1
14853              IF (LENPP>=7 .AND. LENPP<=10) LNPIV(3) = LNPIV(3) + 1
14854              IF (LENPP>=11 .AND. LENPP<=15) LNPIV(4) = LNPIV(4) + 1
14855              IF (LENPP>=16 .AND. LENPP<=20) LNPIV(5) = LNPIV(5) + 1
14856              IF (LENPP>=21 .AND. LENPP<=30) LNPIV(6) = LNPIV(6) + 1
14857              IF (LENPP>=31 .AND. LENPP<=50) LNPIV(7) = LNPIV(7) + 1
14858              IF (LENPP>=51 .AND. LENPP<=70) LNPIV(8) = LNPIV(8) + 1
14859              IF (LENPP>=71 .AND. LENPP<=100) LNPIV(9) = LNPIV(9) + 1
14860              IF (LENPP>=101) LNPIV(10) = LNPIV(10) + 1
14861              MANPIV = MAX(MANPIV,LENPP)
14862              IANPIV = IANPIV + LENPP
14863              KOUNTL = KOUNTL + 1
14864              DO 600 JJ = ROWI, IEND
14865                J = ICN(JJ)
14866                IF (IQ(J)>0) GOTO 600
14867                IOP = IOP + 1
14868                PIVROW = IJPOS - IQ(J)
14869                A(JJ) = A(JJ) + AU*A(PIVROW)
14870                IF (LBIG) BIG = MAX(ABS(A(JJ)),BIG)
14871                ICN(PIVROW) = -ICN(PIVROW)
14872                IF (ABS(A(JJ))<TOL) IDROP = IDROP + 1
14873600           END DO
14874
14875!             JUMP if no non-zeros in non-pivot row have been removed
14876!             because these are beneath the drop-tolerance TOL.
14877
14878              IF (IDROP==0) GOTO 670
14879
14880!             Run through non-pivot row compressing row so that only
14881!             non-zeros greater than TOL are stored. All non-zeros
14882!             less than TOL are also removed from the column structure.
14883
14884              JNEW = ROWI
14885              DO 650 JJ = ROWI, IEND
14886                IF (ABS(A(JJ))<TOL) GOTO 610
14887                A(JNEW) = A(JJ)
14888                ICN(JNEW) = ICN(JJ)
14889                JNEW = JNEW + 1
14890                GOTO 650
14891
14892!               Remove non-zero entry from column structure.
14893
14894610             J = ICN(JJ)
14895                I1 = IPC(J)
14896                I2 = I1 + LENC(J) - 1
14897                DO II = I1, I2
14898                  IF (IRN(II)==I) GOTO 630
14899                END DO
14900630             IRN(II) = IRN(I2)
14901                IRN(I2) = 0
14902                LENC(J) = LENC(J) - 1
14903                IF (NSRCH<=NN) GOTO 650
14904!               Remove column from column chain and place in
14905!               update chain.
14906                IF (NEXTC(J)<0) GOTO 650
14907!               JUMP if column already in update chain.
14908                LC = LASTC(J)
14909                NC = NEXTC(J)
14910                NEXTC(J) = -COLUPD
14911                COLUPD = J
14912                IF (NC/=0) LASTC(NC) = LC
14913                IF (LC==0) GOTO 640
14914                NEXTC(LC) = NC
14915                GOTO 650
14916640             NZ = LENC(J) + 1
14917                ISW = IFIRST(NZ)
14918                IF (ISW>0) LASTR(ISW) = -NC
14919                IF (ISW<0) IFIRST(NZ) = -NC
14920650           END DO
14921              ICN(JNEW:IEND) = 0
14922!             The value of IDROP might be different from that
14923!             calculated earlier because we may now have dropped
14924!             some non-zeros which were not modified by the pivot
14925!             row.
14926              IDROP = IEND + 1 - JNEW
14927              IEND = JNEW - 1
14928              LENR(I) = LENR(I) - IDROP
14929              NZROW = NZROW - IDROP
14930              NZCOL = NZCOL - IDROP
14931              NDROP = NDROP + IDROP
14932670           IFILL = LENPIV - IOP
14933!             Jump is if there is no fill-in.
14934              IF (IFILL==0) GOTO 770
14935!             Now for the fill-in.
14936              MINICN = MAX(MINICN,MOREI+IBEG-1+NZROW+IFILL+LENR(I))
14937!             See if there is room for fill-in.
14938!             Get maximum space for row I in situ.
14939              DO JDIFF = 1, IFILL
14940                JNPOS = IEND + JDIFF
14941                IF (JNPOS>LICN) GOTO 690
14942                IF (ICN(JNPOS)/=0) GOTO 690
14943              END DO
14944!             There is room for all the fill-in after the end of the
14945!             row so it can be left in situ.
14946!             Next available space for fill-in.
14947              IEND = IEND + 1
14948              GOTO 770
14949!             JMORE spaces for fill-in are required in front of row.
14950690           JMORE = IFILL - JDIFF + 1
14951              I1 = IPTR(I)
14952!             We now look in front of the row to see if there is space
14953!             for the rest of the fill-in.
14954              DO JDIFF = 1, JMORE
14955                JNPOS = I1 - JDIFF
14956                IF (JNPOS<IACTIV) GOTO 710
14957                IF (ICN(JNPOS)/=0) GOTO 720
14958              END DO
14959710           JNPOS = I1 - JMORE
14960              GOTO 730
14961!             Whole row must be moved to the beginning of available
14962!             storage.
14963720           JNPOS = IACTIV - LENR(I) - IFILL
14964!             Jump if there is space immediately available for the
14965!             shifted row.
14966730           IF (JNPOS>=IBEG) GOTO 750
14967              CALL MA30DD(A,ICN,IPTR(ISTART),N,IACTIV,ITOP,.TRUE.)
14968              I1 = IPTR(I)
14969              IEND = I1 + LENR(I) - 1
14970              JNPOS = IACTIV - LENR(I) - IFILL
14971              IF (JNPOS>=IBEG) GOTO 750
14972!             No space available so try to create some by throwing
14973!             away previous LU decomposition.
14974              MOREI = MOREI + IBEG - IDISP(1) - LENPIV - 1
14975              IF (LP/=0) WRITE (LP,90002)
14976              IFLAG = -5
14977              IF (ABORT3) GOTO 1160
14978!             Keep record of current pivot row.
14979              IBEG = IDISP(1)
14980              ICN(IBEG) = JPIV
14981              A(IBEG) = A(IJPOS)
14982              IJPOS = IBEG
14983              DO JJ = IJP1, PIVEND
14984                IBEG = IBEG + 1
14985                A(IBEG) = A(JJ)
14986                ICN(IBEG) = ICN(JJ)
14987              END DO
14988              IJP1 = IJPOS + 1
14989              PIVEND = IBEG
14990              IBEG = IBEG + 1
14991              IF (JNPOS>=IBEG) GOTO 750
14992!             This still does not give enough room.
14993              IFLAG = -4
14994              GOTO 1160
14995750           IACTIV = MIN(IACTIV,JNPOS)
14996!             Move non-pivot row I.
14997              IPTR(I) = JNPOS
14998              DO JJ = I1, IEND
14999                A(JNPOS) = A(JJ)
15000                ICN(JNPOS) = ICN(JJ)
15001                JNPOS = JNPOS + 1
15002                ICN(JJ) = 0
15003              END DO
15004!             First new available space.
15005              IEND = JNPOS
15006770           NZROW = NZROW + IFILL
15007!             Innermost fill-in loop which also resets ICN.
15008              IDROP = 0
15009              DO 850 JJ = IJP1, PIVEND
15010                J = ICN(JJ)
15011                IF (J<0) GOTO 840
15012                ANEW = AU*A(JJ)
15013                AANEW = ABS(ANEW)
15014                IF (AANEW>=TOL) GOTO 780
15015                IDROP = IDROP + 1
15016                NDROP = NDROP + 1
15017                NZROW = NZROW - 1
15018                MINICN = MINICN - 1
15019                IFILL = IFILL - 1
15020                GOTO 850
15021780             IF (LBIG) BIG = MAX(AANEW,BIG)
15022                A(IEND) = ANEW
15023                ICN(IEND) = J
15024                IEND = IEND + 1
15025
15026!               Put new entry in column file.
15027                MINIRN = MAX(MINIRN,NZCOL+LENC(J)+1)
15028                JEND = IPC(J) + LENC(J)
15029                JROOM = NZPC - III + 1 + LENC(J)
15030                IF (JEND>LIRN) GOTO 790
15031                IF (IRN(JEND)==0) GOTO 830
15032790             IF (JROOM<DISPC) GOTO 800
15033!               Compress column file to obtain space for new
15034!               copy of column.
15035                CALL MA30DD(A,IRN,IPC(ISTART),N,DISPC,LIRN,.FALSE.)
15036                IF (JROOM<DISPC) GOTO 800
15037                JROOM = DISPC - 1
15038                IF (JROOM>=LENC(J)+1) GOTO 800
15039!               Column file is not large enough.
15040                GOTO 1170
15041!               Copy column to beginning of file.
15042800             JBEG = IPC(J)
15043                JEND = IPC(J) + LENC(J) - 1
15044                JZERO = DISPC - 1
15045                DISPC = DISPC - JROOM
15046                IDISPC = DISPC
15047                DO II = JBEG, JEND
15048                  IRN(IDISPC) = IRN(II)
15049                  IRN(II) = 0
15050                  IDISPC = IDISPC + 1
15051                END DO
15052                IPC(J) = DISPC
15053                JEND = IDISPC
15054                IRN(JEND:JZERO) = 0
15055830             IRN(JEND) = I
15056                NZCOL = NZCOL + 1
15057                LENC(J) = LENC(J) + 1
15058!               End of adjustment to column file.
15059                GOTO 850
15060840             ICN(JJ) = -J
15061850           END DO
15062              IF (IDROP==0) GOTO 870
15063              DO KDROP = 1, IDROP
15064                ICN(IEND) = 0
15065                IEND = IEND + 1
15066              END DO
15067870           LENR(I) = LENR(I) + IFILL
15068!             End of scan of pivot column.
15069880         END DO
15070
15071!           Remove pivot column from column oriented storage
15072!           and update row ordering arrays.
15073            I1 = IPC(JPIV)
15074            I2 = IPC(JPIV) + LENC(JPIV) - 1
15075            NZCOL = NZCOL - LENC(JPIV)
15076            DO 930 II = I1, I2
15077              I = IRN(II)
15078              IRN(II) = 0
15079              NZ = LENR(I) - LENRL(I)
15080              IF (NZ/=0) GOTO 890
15081              LASTR(I) = 0
15082              GOTO 930
15083890           IFIR = IFIRST(NZ)
15084              IFIRST(NZ) = I
15085!             IF (IFIR) 900, 920, 910
15086!900          LASTR(I) = IFIR
15087              IF (IFIR == 0) GOTO 920
15088              IF (IFIR > 0) GOTO 910
15089              LASTR(I) = IFIR
15090              NEXTR(I) = 0
15091              GOTO 930
15092910           LASTR(I) = LASTR(IFIR)
15093              NEXTR(I) = IFIR
15094              LASTR(IFIR) = I
15095              GOTO 930
15096920           LASTR(I) = 0
15097              NEXTR(I) = 0
15098              NZMIN = MIN(NZMIN,NZ)
15099930         END DO
15100!           Restore IQ and nullify U part of old pivot row.
15101!           Record the column permutation in LASTC(JPIV) and
15102!           the row permutation in LASTR(IPIV).
15103940         IPC(JPIV) = -ISING
15104            LASTR(IPIV) = PIVOT
15105            IF (LENPIV==0) GOTO 1050
15106            NZROW = NZROW - LENPIV
15107            JVAL = IJP1
15108            JZER = IPTR(IPIV)
15109            IPTR(IPIV) = 0
15110            DO JCOUNT = 1, LENPIV
15111              J = ICN(JVAL)
15112              IQ(J) = ICN(JZER)
15113              ICN(JZER) = 0
15114              JVAL = JVAL + 1
15115              JZER = JZER + 1
15116            END DO
15117!           Adjust column ordering arrays.
15118            IF (NSRCH>NN) GOTO 980
15119            DO 970 JJ = IJP1, PIVEND
15120              J = ICN(JJ)
15121              NZ = LENC(J)
15122              IF (NZ/=0) GOTO 960
15123              IPC(J) = 0
15124              GOTO 970
15125960           NZMIN = MIN(NZMIN,NZ)
15126970         END DO
15127            GOTO 1050
15128980         JJ = COLUPD
15129            DO 1040 JDUMMY = 1, NN
15130              J = JJ
15131              IF (J==NN+1) GOTO 1050
15132              JJ = -NEXTC(J)
15133              NZ = LENC(J)
15134              IF (NZ/=0) GOTO 990
15135              IPC(J) = 0
15136              GOTO 1040
15137990           IFIR = IFIRST(NZ)
15138              LASTC(J) = 0
15139!             IF (IFIR) 1000, 1010, 1020
15140!1000         IFIRST(NZ) = -J
15141              IF (IFIR == 0) GOTO 1010
15142              IF (IFIR > 0) GOTO 1020
15143              IFIRST(NZ) = -J
15144              IFIR = -IFIR
15145              LASTC(IFIR) = J
15146              NEXTC(J) = IFIR
15147              GOTO 1040
151481010          IFIRST(NZ) = -J
15149              NEXTC(J) = 0
15150              GOTO 1030
151511020          LC = -LASTR(IFIR)
15152              LASTR(IFIR) = -J
15153              NEXTC(J) = LC
15154              IF (LC/=0) LASTC(LC) = J
151551030          NZMIN = MIN(NZMIN,NZ)
151561040        END DO
151571050      END DO
15158! ********************************************
15159! ****    End of main elimination loop    ****
15160! ********************************************
15161
15162!         Reset IACTIV to point to the beginning of the
15163!         next block.
151641060      IF (ILAST/=NN) IACTIV = IPTR(ILAST+1)
151651070    END DO
15166
15167! ********************************************
15168! ****    End of deomposition of block    ****
15169! ********************************************
15170
15171!     Record singularity (if any) in IQ array.
15172        IF (IRANK==NN) GOTO 1090
15173        DO 1080 I = 1, NN
15174          IF (IPC(I)<0) GOTO 1080
15175          ISING = IPC(I)
15176          IQ(ISING) = -IQ(ISING)
15177          IPC(I) = -ISING
151781080    END DO
15179
15180!       Run through LU decomposition changing column indices
15181!       to that of new order and permuting LENR and LENRL
15182!       arrays according to pivot permutations.
151831090    ISTART = IDISP(1)
15184        IEND = IBEG - 1
15185        IF (IEND<ISTART) GOTO 1110
15186        DO JJ = ISTART, IEND
15187          JOLD = ICN(JJ)
15188          ICN(JJ) = -IPC(JOLD)
15189        END DO
151901110    DO II = 1, NN
15191          I = LASTR(II)
15192          NEXTR(I) = LENR(II)
15193          IPTR(I) = LENRL(II)
15194        END DO
15195        LENRL(1:NN) = IPTR(1:NN)
15196        LENR(1:NN) = NEXTR(1:NN)
15197
15198!       Update permutation arrays IP and IQ.
15199        DO II = 1, NN
15200          I = LASTR(II)
15201          J = -IPC(II)
15202          NEXTR(I) = IABS(IP(II)+0)
15203          IPTR(J) = IABS(IQ(II)+0)
15204!         NEXTR(I) = IABS(IP(II))
15205!         IPTR(J) = IABS(IQ(II))
15206        END DO
15207        DO I = 1, NN
15208          IF (IP(I)<0) NEXTR(I) = -NEXTR(I)
15209          IP(I) = NEXTR(I)
15210          IF (IQ(I)<0) IPTR(I) = -IPTR(I)
15211          IQ(I) = IPTR(I)
15212        END DO
15213        IP(NN) = IABS(IP(NN)+0)
15214!       IP(NN) = IABS(IP(NN))
15215        IDISP(2) = IEND
15216        GOTO 1190
15217
15218!       Error returns
152191160    IDISP(2) = IACTIV
15220        IF (LP==0) GOTO 1190
15221        WRITE (LP,90003)
15222        GOTO 1180
152231170    IF (IFLAG==-5) IFLAG = -6
15224        IF (IFLAG/=-6) IFLAG = -3
15225        IDISP(2) = IACTIV
15226        IF (LP==0) GOTO 1190
15227        IF (IFLAG==-3) WRITE (LP,90004)
15228        IF (IFLAG==-6) WRITE (LP,90005)
152291180    PIVOT = PIVOT - ISTART + 1
15230        WRITE (LP,90006) PIVOT, NBLOCK, ISTART, ILAST
15231        IF (PIVOT==0) WRITE (LP,90007) MINIRN
15232
152331190    RETURN
1523490000   FORMAT (' Error return from MA30AD because matrix is', &
15235          ' structurally singular')
1523690001   FORMAT (' Error return from MA30AD because matrix is', &
15237          ' numerically singular')
1523890002   FORMAT (' LU decomposition destroyed to create more space')
1523990003   FORMAT (' Error return from MA30AD because LICN is not big enough')
1524090004   FORMAT (' Error return from MA30AD because LIRN is not big enough')
1524190005   FORMAT (' Error return from MA30AD LIRN and LICN are too small')
1524290006   FORMAT (' At stage ',I5,' in block ',I5,' with first row ',I5, &
15243          ' and last row ',I5)
1524490007   FORMAT (' To continue set LIRN to at least ',I8)
15245
15246      END SUBROUTINE MA30AD
15247!_______________________________________________________________________
15248
15249      SUBROUTINE MA30DD(A,ICN,IPTR,N,IACTIV,ITOP,REALS)
15250! ..
15251! This subroutine performs garbage collection operations on the arrays
15252! A, ICN, and IRN.
15253! ..
15254! IACTIV is the first position in arrays A/ICN from which the compress
15255! starts. On exit, IACTIV equals the position of the first entry.
15256! ..
15257     IMPLICIT NONE
15258! ..
15259! .. Scalar Arguments ..
15260        INTEGER :: IACTIV, ITOP, N
15261        LOGICAL :: REALS
15262! ..
15263! .. Array Arguments ..
15264        KPP_REAL :: A(ITOP)
15265        INTEGER :: ICN(ITOP), IPTR(N)
15266! ..
15267! .. Local Scalars ..
15268        INTEGER :: J, JPOS, K, KL, KN
15269! ..
15270! .. FIRST EXECUTABLE STATEMENT MA30DD
15271! ..
15272        IF (REALS) ICNCP = ICNCP + 1
15273        IF (.NOT.REALS) IRNCP = IRNCP + 1
15274!       Set the first non-zero entry in each row to the negative of the
15275!       row/col number and hold this row/col index in the row/col
15276!       pointer. This is so that the beginning of each row/col can
15277!       be recognized in the subsequent scan.
15278        DO 10 J = 1, N
15279          K = IPTR(J)
15280          IF (K<IACTIV) GOTO 10
15281          IPTR(J) = ICN(K)
15282          ICN(K) = -J
1528310      END DO
15284        KN = ITOP + 1
15285        KL = ITOP - IACTIV + 1
15286!       Go through arrays in reverse order compressing to the back so
15287!       that there are no zeros held in positions IACTIV to ITOP in ICN.
15288!       Reset first entry of each row/col and pointer array IPTR.
15289        DO 30 K = 1, KL
15290          JPOS = ITOP - K + 1
15291          IF (ICN(JPOS)==0) GOTO 30
15292          KN = KN - 1
15293          IF (REALS) A(KN) = A(JPOS)
15294          IF (ICN(JPOS)>=0) GOTO 20
15295!         First non-zero of row/col has been located.
15296          J = -ICN(JPOS)
15297          ICN(JPOS) = IPTR(J)
15298          IPTR(J) = KN
1529920        ICN(KN) = ICN(JPOS)
1530030      END DO
15301        IACTIV = KN
15302        RETURN
15303
15304      END SUBROUTINE MA30DD
15305!_______________________________________________________________________
15306
15307      SUBROUTINE MA30BD(N,ICN,A,LICN,LENR,LENRL,IDISP,IP,IQ,W,IW,IFLAG)
15308! ..
15309! MA30BD performs the LU decomposition of the diagonal blocks of
15310! a new matrix PAQ of the same sparsity pattern, using information
15311! from a previous call to MA30AD. THe entries of the input matrix
15312! must already be in their final positions in the LU decomposition
15313! structure. This routine executes about five times faster than
15314! MA30AD.
15315! ..
15316! We now describe the argument list for MA30BD. Consult MA30AD for
15317!     further information on these parameters.
15318! N   is an integer variable set to the order of the matrix.
15319! ICN is an integer array of length LICN. It should be unchanged
15320!     since the last call to MA30AD. It is not altered by MA30BD.
15321! A   is a real(kind=wp) array of length LICN. The user must set
15322!     entries IDISP(1) to IDISP(2) to contain the entries in the
15323!     diagonal blocks of the matrix PAQ whose column numbers are
15324!     held in ICN, using corresponding positions. Note that some
15325!     zeros may need to be held explicitly. On output entries
15326!     IDISP(1) to IDISP(2) of array A contain the LU decomposition
15327!     of the diagonal blocks of PAQ. Entries A(1) to A(IDISP(1)-1)
15328!     are neither required nor altered by MA30BD.
15329! LICN is an integer variable which must be set by the user to the
15330!     length of arrays A and ICN. it is not altered by MA30BD.
15331! LENR, LENRL are integer arrays of length N. They should be
15332!     unchanged since the last call to MA30AD. They are not
15333!     altered by MA30BD.
15334! IDISP is an integer array of length 2. It should be unchanged
15335!     since the last call to MA30AD. It is not altered by MA30BD.
15336! IP, IQ are integer arrays of length N. They should be unchanged
15337!     since the last call to MA30AD. They are not altered by
15338!     MA30BD.
15339! W   is a REAL(KIND=WP) array of length N which is used as
15340!     workspace by MA30BD.
15341! IW  is an integer array of length N which is used as workspace
15342!     by MA30BD.
15343! IFLAG is an integer variable. On output from MA30BD, IFLAG has
15344!     the value zero if the factorization was successful, has the
15345!     value I if pivot I was very small and has the value -I if
15346!     an unexpected singularity was detected at stage I of the
15347!     decomposition.
15348! ..
15349     IMPLICIT NONE
15350! ..
15351! .. Scalar Arguments ..
15352        INTEGER :: IFLAG, LICN, N
15353! ..
15354! .. Array Arguments ..
15355        KPP_REAL :: A(LICN), W(N)
15356        INTEGER :: ICN(LICN), IDISP(2), IP(N), IQ(N), IW(N), LENR(N), LENRL(N)
15357! ..
15358! .. Local Scalars ..
15359        KPP_REAL :: AU, ROWMAX
15360        INTEGER :: I, IFIN, ILEND, IPIVJ, ISING, ISTART, J, JAY, JAYJAY, JFIN, &
15361          JJ, PIVPOS
15362        LOGICAL :: STAB
15363! ..
15364! .. Intrinsic Functions ..
15365        INTRINSIC ABS, MAX
15366! ..
15367! .. FIRST EXECUTABLE STATEMENT MA30BD
15368! ..
15369        STAB = EPS <= ONE
15370        RMIN = EPS
15371        ISING = 0
15372        IFLAG = 0
15373        W(1:N) = ZERO
15374!       Set up pointers to the beginning of the rows.
15375        IW(1) = IDISP(1)
15376        IF (N==1) GOTO 30
15377        DO I = 2, N
15378          IW(I) = IW(I-1) + LENR(I-1)
15379        END DO
15380
15381!       Start of main loop.
15382!       At step I, row I of A is transformed to row I of LU by
15383!       adding appropriate multiples of rows 1 TO I-1 using row
15384!       Gauss elimination.
1538530      DO 170 I = 1, N
15386!         ISTART is beginning of row I of A and row I of L.
15387          ISTART = IW(I)
15388!         IFIN is end of row I of A and row I of U.
15389          IFIN = ISTART + LENR(I) - 1
15390!         ILEND is end of row I of L.
15391          ILEND = ISTART + LENRL(I) - 1
15392          IF (ISTART>ILEND) GOTO 100
15393!         Load row I of A into vector W.
15394          DO JJ = ISTART, IFIN
15395            J = ICN(JJ)
15396            W(J) = A(JJ)
15397          END DO
15398
15399!         Add multiples of appropriate rows of I to I-1 to row I.
15400          DO 80 JJ = ISTART, ILEND
15401            J = ICN(JJ)
15402!           IPIVJ is position of pivot in row J.
15403            IPIVJ = IW(J) + LENRL(J)
15404!           Form multiplier AU.
15405            AU = -W(J)/A(IPIVJ)
15406            IF (LBIG) BIG = MAX(ABS(AU),BIG)
15407            W(J) = AU
15408!           AU * ROW J (U part) is added to row I.
15409            IPIVJ = IPIVJ + 1
15410            JFIN = IW(J) + LENR(J) - 1
15411            IF (IPIVJ>JFIN) GOTO 80
15412!           Innermost loop.
15413            IF (LBIG) GOTO 60
15414            DO JAYJAY = IPIVJ, JFIN
15415              JAY = ICN(JAYJAY)
15416              W(JAY) = W(JAY) + AU*A(JAYJAY)
15417            END DO
15418            GOTO 80
1541960          DO JAYJAY = IPIVJ, JFIN
15420              JAY = ICN(JAYJAY)
15421              W(JAY) = W(JAY) + AU*A(JAYJAY)
15422              BIG = MAX(ABS(W(JAY)),BIG)
15423            END DO
1542480        END DO
15425
15426!         Reload W back into A (now LU).
15427          DO JJ = ISTART, IFIN
15428            J = ICN(JJ)
15429            A(JJ) = W(J)
15430            W(J) = ZERO
15431          END DO
15432!         We now perform the stability checks.
15433100       PIVPOS = ILEND + 1
15434          IF (IQ(I)>0) GOTO 150
15435!         Matrix had singularity at this point in MA30AD.
15436!         Is it the first such pivot in current block?
15437          IF (ISING==0) ISING = I
15438!         Does current matrix have a singularity in the same place?
15439          IF (PIVPOS>IFIN) GOTO 110
15440          IF (ABS(A(PIVPOS))>ZERO) GOTO 180
15441!         It does, so set ising if it is not the end of the current
15442!         block. Check to see that appropriate part of LU is zero
15443!         or null.
15444110       IF (ISTART>IFIN) GOTO 130
15445          DO 120 JJ = ISTART, IFIN
15446            IF (ICN(JJ)<ISING) GOTO 120
15447            IF (ABS(A(JJ))>ZERO) GOTO 180
15448120       END DO
15449130       IF (PIVPOS<=IFIN) A(PIVPOS) = ONE
15450          IF (IP(I)>0 .AND. I/=N) GOTO 170
15451!         End of current block. Reset zero pivots and ISING.
15452          DO 140 J = ISING, I
15453            IF ((LENR(J)-LENRL(J))==0) GOTO 140
15454            JJ = IW(J) + LENRL(J)
15455            A(JJ) = ZERO
15456140       END DO
15457          ISING = 0
15458          GOTO 170
15459!         Matrix had non-zero pivot in MA30AD at this stage.
15460150       IF (PIVPOS>IFIN) GOTO 180
15461          IF (ABS(A(PIVPOS))<=ZERO) GOTO 180
15462          IF (.NOT.STAB) GOTO 170
15463          ROWMAX = ZERO
15464          DO JJ = PIVPOS, IFIN
15465            ROWMAX = MAX(ROWMAX,ABS(A(JJ)))
15466          END DO
15467          IF (ABS(A(PIVPOS))/ROWMAX>=RMIN) GOTO 170
15468          IFLAG = I
15469          RMIN = ABS(A(PIVPOS))/ROWMAX
15470!         End of main loop.
15471170     END DO
15472
15473        GOTO 190
15474!       Error return
15475180     IF (LP/=0) WRITE (LP,90000) I
15476        IFLAG = -I
15477
15478190     RETURN
1547990000   FORMAT (' Error return from MA30BD; Singularity detected in',' row', &
15480          I8)
15481
15482      END SUBROUTINE MA30BD
15483!_______________________________________________________________________
15484
15485      SUBROUTINE MA30CD(N,ICN,A,LICN,LENR,LENRL,LENOFF,IDISP,IP,IQ,X, &
15486        W,MTYPE)
15487! ..
15488! MA30CD uses the factors produced by MA30AD or MA30BD to solve
15489! AX = B or A TRANSPOSE X = B when the matrix P1*A*Q1(PAQ) is
15490! block lower triangular (including the case of only one diagonal
15491! block).
15492! ..
15493! We now describe the argument list for MA30CD.
15494! N   is an integer variable set to the order of the matrix. It is
15495!     not altered by the subroutine.
15496! ICN is an integer array of length LICN. Entries IDISP(1) to
15497!     IDISP(2) should be unchanged since the last call to MA30AD. If
15498!     the matrix has more than one diagonal block, then column indices
15499!     corresponding to non-zeros in sub-diagonal blocks of PAQ must
15500!     appear in positions 1 to IDISP(1)-1. For the same row those
15501!     entries must be contiguous, with those in row I preceding those
15502!     in row I+1 (I=1,...,N-1) and no wasted space between rows.
15503!     Entries may be in any order within each row. It is not altered
15504!     by MA30CD.
15505! A   is a REAL(KIND=WP) array of length LICN. Entries IDISP(1) to
15506!     IDISP(2) should be unchanged since the last call to MA30AD or
15507!     MA30BD. If the matrix has more than one diagonal block, then
15508!     the values of the non-zeros in sub-diagonal blocks must be in
15509!     positions 1 to IDISP(1)-1 in the order given by ICN. It is not
15510!     altered by MA30CD.
15511! LICN is an integer variable set to the size of arrays ICN and A.
15512!     It is not altered by MA30CD.
15513! LENR, LENRL are integer arrays of length N which should be
15514!     unchanged since the last call to MA30AD. They are not
15515!     altered by MA30CD.
15516! LENOFF is an integer array of length N. If the matrix PAQ (or
15517!     P1*A*Q1) has more than one diagonal block, then LENOFF(I),
15518!     I=1,...,N should be set to the number of non-zeros in row I of
15519!     the matrix PAQ which are in sub-diagonal blocks. If there is
15520!     only one diagonal block then LENOFF(1) may be set TO -1, in
15521!     which case the other entries of LENOFF are never accessed.
15522!     It is not altered by ma30cd.
15523! IDISP is an integer array of length 2 which should be unchanged
15524!     since the last call to MA30AD. It is not altered by MA30CD.
15525! IP, IQ are integer arrays of length N which should be unchanged
15526!     since the last call to MA30AD. They are not altered by
15527!     MA30CD.
15528! X   is a REAL(KIND=WP) array of length N. It must be set by the
15529!     user to the values of the right hand side vector B for the
15530!     equations being solved. ON exit from MA30CD it will be equal
15531!     to the solution X required.
15532! W   is a REAL(KIND=WP) array of length N which is used as
15533!     workspace by MA30CD.
15534! MTYPE is an integer variable which must be set by the user. If
15535!     MTYPE = 1, then the solution to the system AX = B is returned.
15536!     Any other value for mtype will return the solution to the
15537!     system A TRANSPOSE X = B. It is not altered by MA30CD.
15538! ..
15539     IMPLICIT NONE
15540! ..
15541! .. Scalar Arguments ..
15542        INTEGER :: LICN, MTYPE, N
15543! ..
15544! .. Array Arguments ..
15545        KPP_REAL :: A(LICN), W(N), X(N)
15546        INTEGER :: ICN(LICN), IDISP(2), IP(N), IQ(N), LENOFF(N), LENR(N), &
15547          LENRL(N)
15548! ..
15549! .. Local Scalars ..
15550        KPP_REAL :: WI, WII
15551        INTEGER :: I, IB, IBACK, IBLEND, IBLOCK, IEND, IFIRST, II, III,   &
15552          ILAST, J, J1, J2, J3, JJ, JPIV, JPIVP1, K, LJ1, LJ2, LT, LTEND, &
15553          NUMBLK
15554        LOGICAL :: NEG, NOBLOC
15555! ..
15556! .. Intrinsic Functions ..
15557        INTRINSIC ABS, IABS, MAX
15558! ..
15559! .. FIRST EXECUTABLE STATEMENT MA30CD
15560! ..
15561!       The final value of RESID is the maximum residual for an
15562!       inconsistent set of equations.
15563        RESID = ZERO
15564!       NOBLOC is .TRUE. if subroutine block has been used
15565!       previously and is .FALSE. otherwise. The value .FALSE.
15566!       means that LENOFF will not be subsequently accessed.
15567        NOBLOC = LENOFF(1) < 0
15568        IF (MTYPE/=1) GOTO 140
15569
15570!       We now solve  A * X = B.
15571!       NEG is used to indicate when the last row in a block
15572!       has been reached. It is then set to .TRUE. whereafter
15573!       back substitution is performed on the block.
15574        NEG = .FALSE.
15575!       IP(N) is negated so that the last row of the last
15576!       block can be recognised. It is reset to its positive
15577!       value on exit.
15578        IP(N) = -IP(N)
15579!       Preorder VECTOR ... W(I) = X(IP(I))
15580        DO II = 1, N
15581          I = IP(II)
15582          I = IABS(I)
15583          W(II) = X(I)
15584        END DO
15585!       LT holds the position of the first non-zero in the current
15586!       row of the off-diagonal blocks.
15587        LT = 1
15588!       IFIRST holds the index of the first row in the current block.
15589        IFIRST = 1
15590!       IBLOCK holds the position of the first non-zero in the current
15591!       row of the LU decomposition of the diagonal blocks.
15592        IBLOCK = IDISP(1)
15593!       If I is not the last row of a block, then a pass through this
15594!       loop adds the inner product of row I of the off-diagonal blocks
15595!       and W to W and performs forward elimination using row I of the
15596!       LU decomposition. If I is the last row of a block then, after
15597!       performing these aforementioned operations, back substitution
15598!       is performed using the rows of the block.
15599        DO 120 I = 1, N
15600          WI = W(I)
15601          IF (NOBLOC) GOTO 30
15602          IF (LENOFF(I)==0) GOTO 30
15603!         Operations using lower triangular blocks.
15604!         LTEND is the end of row I in the off-diagonal blocks.
15605          LTEND = LT + LENOFF(I) - 1
15606          DO JJ = LT, LTEND
15607            J = ICN(JJ)
15608            WI = WI - A(JJ)*W(J)
15609          END DO
15610!         LT is set the beginning of the next off-diagonal row.
15611          LT = LTEND + 1
15612!         Set NEG to .TRUE. if we are on the last row of the block.
1561330        IF (IP(I)<0) NEG = .TRUE.
15614          IF (LENRL(I)==0) GOTO 50
15615!         Forward elimination phase.
15616!         IEND is the end of the L part of row I in the LU decomposition.
15617          IEND = IBLOCK + LENRL(I) - 1
15618          DO JJ = IBLOCK, IEND
15619            J = ICN(JJ)
15620            WI = WI + A(JJ)*W(J)
15621          END DO
15622!         IBLOCK is adjusted to point to the start of the next row.
1562350        IBLOCK = IBLOCK + LENR(I)
15624          W(I) = WI
15625          IF (.NOT.NEG) GOTO 120
15626!         Back substitution phase.
15627!         J1 is position in A/ICN after end of block beginning in
15628!         row IFIRST and ending in row I.
15629          J1 = IBLOCK
15630!         Are there any singularities in this block? If not, continue
15631!         with the back substitution.
15632          IB = I
15633          IF (IQ(I)>0) GOTO 70
15634          DO III = IFIRST, I
15635            IB = I - III + IFIRST
15636            IF (IQ(IB)>0) GOTO 70
15637            J1 = J1 - LENR(IB)
15638            RESID = MAX(RESID,ABS(W(IB)))
15639            W(IB) = ZERO
15640          END DO
15641!         Entire block is singular.
15642          GOTO 110
15643!         Each pass through this loop performs the back substitution
15644!         operations for a single row, starting at the end of the
15645!         block and working through it in reverse order.
1564670        DO III = IFIRST, IB
15647            II = IB - III + IFIRST
15648!           J2 is end of row II.
15649            J2 = J1 - 1
15650!           J1 is beginning of row II.
15651            J1 = J1 - LENR(II)
15652!           JPIV is the position of the pivot in row II.
15653            JPIV = J1 + LENRL(II)
15654            JPIVP1 = JPIV + 1
15655!           JUMP if row II of U has no non-zeros.
15656            IF (J2<JPIVP1) GOTO 90
15657            WII = W(II)
15658            DO JJ = JPIVP1, J2
15659              J = ICN(JJ)
15660              WII = WII - A(JJ)*W(J)
15661            END DO
15662            W(II) = WII
1566390          W(II) = W(II)/A(JPIV)
15664          END DO
15665110       IFIRST = I + 1
15666          NEG = .FALSE.
15667120     END DO
15668
15669!       Reorder solution vector, X(I) = W(IQINVERSE(I)).
15670        DO II = 1, N
15671          I = IQ(II)
15672          I = IABS(I)
15673          X(I) = W(II)
15674        END DO
15675        IP(N) = -IP(N)
15676        GOTO 320
15677
15678!       WE now solve ATRANSPOSE * X = B.
15679!       Preorder vector, W(I) = X(IQ(I)).
15680140     DO II = 1, N
15681          I = IQ(II)
15682          I = IABS(I)
15683          W(II) = X(I)
15684        END DO
15685!       LJ1 points to the beginning the current row in the off-diagonal
15686!       blocks.
15687        LJ1 = IDISP(1)
15688!       IBLOCK is initialized to point to the beginning of the block
15689!       after the last one.
15690        IBLOCK = IDISP(2) + 1
15691!       ILAST is the last row in the current block.
15692        ILAST = N
15693!       IBLEND points to the position after the last non-zero in the
15694!       current block.
15695        IBLEND = IBLOCK
15696!       Each pass through this loop operates with one diagonal block and
15697!       the off-diagonal part of the matrix corresponding to the rows
15698!       of this block. The blocks are taken in reverse order and the
15699!       number of times the loop is entered is MIN(N, NO. BLOCKS+1).
15700        DO NUMBLK = 1, N
15701          IF (ILAST==0) GOTO 300
15702          IBLOCK = IBLOCK - LENR(ILAST)
15703!         This loop finds the index of the first row in the current
15704!         block. It is FIRST and IBLOCK is set to the position of
15705!         the beginning of this first row.
15706          DO K = 1, N
15707            II = ILAST - K
15708            IF (II==0) GOTO 170
15709            IF (IP(II)<0) GOTO 170
15710            IBLOCK = IBLOCK - LENR(II)
15711          END DO
15712170       IFIRST = II + 1
15713!         J1 points to the position of the beginning of row I (LT part)
15714!         or pivot.
15715          J1 = IBLOCK
15716!         Forward elimination.
15717!         Each pass through this loop performs the operations for one row
15718!         of the block. If the corresponding entry of W is zero then the
15719!         operations can be avoided.
15720          DO I = IFIRST, ILAST
15721            IF (ABS(W(I))<=ZERO) GOTO 200
15722!           JUMP IF ROW I SINGULAR.
15723            IF (IQ(I)<0) GOTO 220
15724!           J2 first points to the pivot in row I and then is made
15725!           to point to the first non-zero in the U TRANSPOSE part
15726!           of the row.
15727            J2 = J1 + LENRL(I)
15728            WI = W(I)/A(J2)
15729            IF (LENR(I)-LENRL(I)==1) GOTO 190
15730            J2 = J2 + 1
15731!           J3 points to the end of row I.
15732            J3 = J1 + LENR(I) - 1
15733            DO JJ = J2, J3
15734              J = ICN(JJ)
15735              W(J) = W(J) - A(JJ)*WI
15736            END DO
15737190         W(I) = WI
15738200         J1 = J1 + LENR(I)
15739          END DO
15740          GOTO 240
15741!         Deal with rest of block which is singular.
15742220       DO II = I, ILAST
15743            RESID = MAX(RESID,ABS(W(II)))
15744            W(II) = ZERO
15745          END DO
15746!         Back substitution.
15747!         This loop does the back substitution on the rows of the
15748!         block in the reverse order doing it simultaneously on
15749!         the L TRANSPOSE part of the diagonal blocks and the
15750!         off-diagonal blocks.
15751240       J1 = IBLEND
15752          DO 280 IBACK = IFIRST, ILAST
15753            I = ILAST - IBACK + IFIRST
15754!           J1 points to the beginning of row I.
15755            J1 = J1 - LENR(I)
15756            IF (LENRL(I)==0) GOTO 260
15757!           J2 points to the end of the L TRANSPOSE part of row I.
15758            J2 = J1 + LENRL(I) - 1
15759            DO JJ = J1, J2
15760              J = ICN(JJ)
15761              W(J) = W(J) + A(JJ)*W(I)
15762            END DO
15763260         IF (NOBLOC) GOTO 280
15764!           Operations using lower triangular blocks.
15765            IF (LENOFF(I)==0) GOTO 280
15766!           LJ2 points to the end of row I of the off-diagonal blocks.
15767            LJ2 = LJ1 - 1
15768!           LJ1 points to the beginning of row I of the off-diagonal
15769!           blocks.
15770            LJ1 = LJ1 - LENOFF(I)
15771            DO JJ = LJ1, LJ2
15772              J = ICN(JJ)
15773              W(J) = W(J) - A(JJ)*W(I)
15774            END DO
15775280       END DO
15776          IBLEND = J1
15777          ILAST = IFIRST - 1
15778        END DO
15779!       Reorder solution vector, X(I) = W(IPINVERSE(I)).
15780300     DO II = 1, N
15781          I = IP(II)
15782          I = IABS(I)
15783          X(I) = W(II)
15784        END DO
15785
15786320     RETURN
15787
15788      END SUBROUTINE MA30CD
15789!_______________________________________________________________________
15790
15791! Private Variable Information.
15792! Private variables for MA30ED hold control parameters.
15793!     Original : COMMON /MA30ED/ LP,ABORT1,ABORT2,ABORT3
15794! The integer LP is the unit number to which the error messages are
15795!     sent. LP has a default value of 6. This default value can be
15796!     reset by the user, if desired. A value of 0 suppresses all
15797!     messages.
15798! The logical variables ABORT1, ABORT2, ABORT3 are used to control
15799!     the conditions under which the subroutine will terminate.
15800! If ABORT1 iS .TRUE. then the subroutine will exit immediately on
15801!     detecting structural singularity.
15802! If ABORT2 iS .TRUE. then the subroutine will exit immediately on
15803!     detecting numerical singularity.
15804! If ABORT3 iS .TRUE. then the subroutine will exit immediately when
15805!     the available space in A/ICN is filled up by the previously
15806!     decomposed, active, and undecomposed parts of the matrix.
15807! The default values for ABORT1, ABORT2, ABORT3 are set to .TRUE.,
15808!     .TRUE., and .FALSE., respectively.
15809
15810! The private variables for MA30FD are used to provide the user with
15811! information on the decomposition.
15812!     Original : COMMON /MA30FD/ IRNCP,ICNCP,IRANK,MINIRN,MINICN
15813! IRNCP AND ICNCP are integer variables used to monitor the adequacy
15814!     of the allocated space in arrays IRN and A/ICN, respectively,
15815!     by taking account of the number of data management compresses
15816!     required on these arrays. If IRNCP or ICNCP is fairly large (say
15817!     greater than N/10), It may be advantageous to increase the size
15818!     of the corresponding array(s). IRNCP and ICNCP are initialized
15819!     to zero on entry to MA30AD and are incremented each time the
15820!     compressing routine MA30DD is entered.
15821! ICNCP is the number of compresses on A/ICN.
15822! IRNCP is the number of compresses on IRN.
15823! IRANK is an integer variable which gives an estimate (actually an
15824!     upper bound) of the rank of the matrix. On an exit with IFLAG
15825!     equal to 0, this will be equal to N.
15826! MINIRN is an integer variable which, after a successful call to
15827!     MA30AD, indicates the minimum length to which IRN can be
15828!     reduced while still permitting a successful decomposition
15829!     of the same matrix. If, however, the user were to decrease the
15830!     length of IRN to that size, the number of compresses (IRNCP)
15831!     may be very high and quite costly. If LIRN is not large enough
15832!     to begin the decomposition on a diagonal block, MINIRN will be
15833!     equal to the value required to continue the decomposition and
15834!     IFLAG will be set to -3 or -6. A value of LIRN slightly greater
15835!     than this (say about N/2) will usually provide enough space to
15836!     complete the decomposition on that block. In the event of any
15837!     other failure minirn gives the minimum size of IRN required
15838!     for a successful decomposition up to that point.
15839! MINICN is an integer variable which after a successful call to
15840!     MA30AD, indicates the minimum size of LICN required to enable
15841!     a successful decomposition. In the event of failure with
15842!     IFLAG = -5, MINICN will, if ABORT3 is left set to .FALSE.,
15843!     indicate the minimum length that would be sufficient to
15844!     prevent this error in a subsequent run on an identical matrix.
15845!     Again the user may prefer to use a value of icn slightly
15846!     greater than MINICN for subsequent runs to avoid too many
15847!     conpresses (ICNCP). In the event of failure with IFLAG equal
15848!     to any negative value except -4, minicn will give the minimum
15849!     length to which licn could be reduced to enable a successful
15850!     decomposition to the point at which failure occurred. Notice
15851!     that, on a successful entry IDISP(2) gives the amount of space
15852!     in A/ICN required for the decomposition while MINICN will
15853!     usually be slightly greater because of the need for
15854!     "elbow room". If the user is very unsure how large to make
15855!     LICN, the variable MINICN can be used to provide that
15856!     information. A preliminary run should be performed with ABORT3
15857!     left set to .FALSE. and LICN about 3/2 times as big as the
15858!     number of non-zeros in the original matrix. Unless the initial
15859!     problem is very sparse (when the run will be successful) or
15860!     fills in extremely badly (giving an error return with
15861!     IFLAG = -4), an error return with IFLAG = -5 should result and
15862!     MINICN will give the amount of space required for a successful
15863!     decomposition.
15864
15865! The private variables for MA30GD are used by the MA30BD entry only.
15866!     Original : COMMON /MA30GD/ EPS,RMIN
15867! EPS is a REAL(KIND=WP) variable. It is used to test for small
15868!     pivots. Its default value is 1.0D-4 (1.0E-4 in E version).
15869!     If the user sets EPS to any value greater than 1.0, then no
15870!     check is made on the size of the pivots. Although the absence
15871!     of such a check would fail to warn the user of bad instability,
15872!     its absence will enable MA30BD to run slightly faster. An a
15873!     posteriori check on the stability of the factorization can
15874!     be obtained from MC24AD.
15875! RMIN is a REAL(KIND=WP) variable which gives the user some
15876!     information about the stability of the decomposition. At each
15877!     stage of the LU decomposition the magnitude of the pivot APIV
15878!     is compared with the largest off-diagonal entry currently in
15879!     its row (row of U), ROWMAX say. If the ratio
15880!                       MIN(APIV/ROWMAX)
15881!     where the minimum is taken over all the rows, is less than EPS
15882!     then RMIN is set to this minimum value and IFLAG is returned
15883!     with the value +I where I is the row in which this minimum
15884!     occurs. If the user sets EPS greater than one, then this test
15885!     is not performed. In this case, and when there are no small
15886!     pivots rmin will be set equal to EPS.
15887
15888! The private variables for MA30HD are used by MA30CD only.
15889!     Original : COMMON /MA30HD/ RESID
15890! RESID is a REAL(KIND=WP) variable. In the case of singular or
15891!     rectangular matrices its final value will be equal to the
15892!     maximum residual for the unsatisfied equations; otherwise
15893!     its value will be set to zero.
15894
15895!  MA30ID private variables control the use of drop tolerances,
15896!     the modified pivot option and the calculation of the largest
15897!     entry in the factorization process. These private variables
15898!     were added to the MA30 package in February, 1983.
15899!     Original : COMMON /MA30ID/ TOL,BIG,NDROP,NSRCH,LBIG
15900! TOL is a REAL(KIND=WP) variable. If it is set to a positive
15901!     value, then MA30AD will drop from the factors any non-zero
15902!     whose modulus is less than TOL. The factorization will then
15903!     require less storage but will be inaccurate. After a run of
15904!     MA30AD where entries have been dropped, MA30BD should not
15905!     be called. The default value for TOL is 0.0.
15906! BIG is a REAL(KIND=WP) variable. If LBIG has been set to .TRUE.,
15907!     BIG will be set to the largest entry encountered during the
15908!     factorization.
15909! NDROP is an integer variable. If TOL has been set positive, on
15910!     exit from MA30AD, NDROP will hold the number of entries
15911!     dropped from the data structure.
15912! NSRCH is an integer variable. If NSRCH is set to a value less
15913!     than or equal to N, then a different pivot option will be
15914!     employed by MA30AD. This may result in different fill-in
15915!     and execution time for MA30AD. If NSRCH is less than or
15916!     equal to N, the workspace arrays LASTC and NEXTC are not
15917!     referenced by MA30AD. The default value for NSRCH is 32768.
15918! LBIG is a logical variable. If LBIG is set to .TRUE., the value
15919!     of the largest entry encountered in the factorization by
15920!     MA30AD is returned in BIG. Setting LBIG to .TRUE. will
15921!     marginally increase the factorization time for MA30AD and
15922!     will increase that for MA30BD by about 20%. The default
15923!     value for LBIG is .FALSE.
15924!_______________________________________________________________________
15925
15926      SUBROUTINE MC13D(N,ICN,LICN,IP,LENR,IOR,IB,NUM,IW)
15927! ..
15928     IMPLICIT NONE
15929! ..
15930! .. Scalar Arguments ..
15931        INTEGER :: LICN, N, NUM
15932! ..
15933! .. Array Arguments ..
15934        INTEGER :: IB(N), ICN(LICN), IOR(N), IP(N), IW(N,3), LENR(N)
15935! ..
15936! .. FIRST EXECUTABLE STATEMENT MA13D
15937! ..
15938        CALL MC13E(N,ICN,LICN,IP,LENR,IOR,IB,NUM,IW(1,1),IW(1,2),IW(1,3))
15939        RETURN
15940
15941      END SUBROUTINE MC13D
15942!_______________________________________________________________________
15943
15944      SUBROUTINE MC13E(N,ICN,LICN,IP,LENR,ARP,IB,NUM,LOWL,NUMB,PREV)
15945! ..
15946! ARP(I) is one less than the number of unsearched edges leaving
15947!     node I. At the end of the algorithm it is set to a
15948!     permutation which puts the matrix in block lower
15949!     triangular form.
15950! IB(I) is the position in the ordering of the start of the Ith
15951!     block. IB(N+1-I) holds the node number of the Ith node
15952!     on the stack.
15953! LOWL(I) is the smallest stack position of any node to which a
15954!     path from node I has been found. It is set to N+1 when
15955!     node I is removed from the stack.
15956! NUMB(I) is the position of node I in the stack if it is on
15957!     the stack. It is the permuted order of node I for those
15958!     nodes whose final position has been found and is otherwise
15959!     zero.
15960! PREV(I) is the node at the end of the path when node I was
15961!     placed on the stack.
15962! ..
15963     IMPLICIT NONE
15964! ..
15965! .. Scalar Arguments ..
15966        INTEGER :: LICN, N, NUM
15967! ..
15968! .. Array Arguments ..
15969        INTEGER :: ARP(N), IB(N), ICN(LICN), IP(N), LENR(N), LOWL(N),  &
15970          NUMB(N), PREV(N)
15971! ..
15972! .. Local Scalars ..
15973        INTEGER :: DUMMY, I, I1, I2, ICNT, II, ISN, IST, IST1, IV, IW, &
15974          J, K, LCNT, NNM1, STP
15975! ..
15976! .. Intrinsic Functions ..
15977        INTRINSIC MIN
15978! ..
15979! .. FIRST EXECUTABLE STATEMENT MA13E
15980! ..
15981!       ICNT is the number of nodes whose positions in final ordering
15982!       have been found.
15983        ICNT = 0
15984!       NUM is the number of blocks that have been found.
15985        NUM = 0
15986        NNM1 = N + N - 1
15987
15988!       Initialization of arrays.
15989        DO J = 1, N
15990          NUMB(J) = 0
15991          ARP(J) = LENR(J) - 1
15992        END DO
15993
15994        DO 90 ISN = 1, N
15995!         Look for a starting node.
15996          IF (NUMB(ISN)/=0) GOTO 90
15997          IV = ISN
15998!         IST is the number of nodes on the stack. It is the
15999!         stack pointer.
16000          IST = 1
16001!         Put node IV at beginning of stack.
16002          LOWL(IV) = 1
16003          NUMB(IV) = 1
16004          IB(N) = IV
16005
16006!         The body of this loop puts a new node on the stack
16007!         or backtracks.
16008          DO 80 DUMMY = 1, NNM1
16009            I1 = ARP(IV)
16010!           Have all edges leaving node iv been searched?
16011            IF (I1<0) GOTO 30
16012            I2 = IP(IV) + LENR(IV) - 1
16013            I1 = I2 - I1
16014
16015!           Look at edges leaving node iv until one enters a
16016!           new node or all edges are exhausted.
16017            DO 20 II = I1, I2
16018              IW = ICN(II)
16019!             Has node iw been on stack already?
16020              IF (NUMB(IW)==0) GOTO 70
16021!             Update value of LOWL(IV) if necessary.
1602220          LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
16023
16024!           There are no more edges leaving node IV.
16025            ARP(IV) = -1
16026!           Is node IV the root of a block.
1602730          IF (LOWL(IV)<NUMB(IV)) GOTO 60
16028
16029!           Order nodes in a block.
16030            NUM = NUM + 1
16031            IST1 = N + 1 - IST
16032            LCNT = ICNT + 1
16033!           Peel block off the top of the stack starting at the
16034!           top and working down to the root of the block.
16035            DO STP = IST1, N
16036              IW = IB(STP)
16037              LOWL(IW) = N + 1
16038              ICNT = ICNT + 1
16039              NUMB(IW) = ICNT
16040              IF (IW==IV) GOTO 50
16041            END DO
1604250          IST = N - STP
16043            IB(NUM) = LCNT
16044!           Are there any nodes left on the stack?
16045            IF (IST/=0) GOTO 60
16046!           Have all the nodes been ordered?
16047            IF (ICNT<N) GOTO 90
16048            GOTO 100
16049
16050!           Backtrack to previous node on path.
1605160          IW = IV
16052            IV = PREV(IV)
16053!           Update value of LOWL(IV) if necessary.
16054            LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
16055            GOTO 80
16056
16057!           Put new node on the stack.
1605870          ARP(IV) = I2 - II - 1
16059            PREV(IW) = IV
16060            IV = IW
16061            IST = IST + 1
16062            LOWL(IV) = IST
16063            NUMB(IV) = IST
16064            K = N + 1 - IST
16065            IB(K) = IV
1606680        END DO
16067
1606890      END DO
16069
16070!       Put permutation in the required form.
16071100     DO I = 1, N
16072          II = NUMB(I)
16073          ARP(II) = I
16074        END DO
16075        RETURN
16076
16077      END SUBROUTINE MC13E
16078!_______________________________________________________________________
16079
16080      SUBROUTINE MC20AD(NC,MAXA,A,INUM,JPTR,JNUM,JDISP)
16081! ..
16082     IMPLICIT NONE
16083! ..
16084! .. Scalar Arguments ..
16085! ..
16086        INTEGER :: JDISP, MAXA, NC
16087! ..
16088! .. Array Arguments ..
16089        KPP_REAL :: A(MAXA)
16090        INTEGER :: INUM(MAXA), JNUM(MAXA), JPTR(NC)
16091! ..
16092! .. Local Scalars ..
16093        KPP_REAL :: ACE, ACEP
16094        INTEGER :: I, ICE, ICEP, J, JA, JB, JCE, JCEP, K, KR, LOC, MYNULL
16095! ..
16096! .. FIRST EXECUTABLE STATEMENT MA20AD
16097! ..
16098        MYNULL = -JDISP
16099!       CLEAR JPTR
16100        JPTR(1:NC) = 0
16101!       Count the number of elements in each column.
16102        DO K = 1, MAXA
16103          J = JNUM(K) + JDISP
16104          JPTR(J) = JPTR(J) + 1
16105        END DO
16106!       SET THE JPTR ARRAY.
16107        K = 1
16108        DO J = 1, NC
16109          KR = K + JPTR(J)
16110          JPTR(J) = K
16111          K = KR
16112        END DO
16113
16114!       Reorder the elements into column order. The algorithm is an
16115!       in-place sort and is of order MAXA.
16116        DO 50 I = 1, MAXA
16117!         Establish the current entry.
16118          JCE = JNUM(I) + JDISP
16119          IF (JCE==0) GOTO 50
16120          ACE = A(I)
16121          ICE = INUM(I)
16122!         Clear the location vacated.
16123          JNUM(I) = MYNULL
16124!         Chain from current entry to store items.
16125          DO 40 J = 1, MAXA
16126!           Current entry not in correct position. Determine the
16127!           correct position to store entry.
16128            LOC = JPTR(JCE)
16129            JPTR(JCE) = JPTR(JCE) + 1
16130!           Save contents of that location.
16131            ACEP = A(LOC)
16132            ICEP = INUM(LOC)
16133            JCEP = JNUM(LOC)
16134!           Store current entry.
16135            A(LOC) = ACE
16136            INUM(LOC) = ICE
16137            JNUM(LOC) = MYNULL
16138!           Check if next current entry needs to be processed.
16139            IF (JCEP==MYNULL) GOTO 50
16140!           It does. Copy into current entry.
16141            ACE = ACEP
16142            ICE = ICEP
1614340        JCE = JCEP + JDISP
16144
1614550      END DO
16146
16147!       Reset JPTR vector.
16148        JA = 1
16149        DO J = 1, NC
16150          JB = JPTR(J)
16151          JPTR(J) = JA
16152          JA = JB
16153        END DO
16154        RETURN
16155
16156      END SUBROUTINE MC20AD
16157!_______________________________________________________________________
16158
16159      SUBROUTINE MC20BD(NC,MAXA,A,INUM,JPTR)
16160! ..
16161     IMPLICIT NONE
16162! ..
16163! .. Scalar Arguments ..
16164        INTEGER :: MAXA, NC
16165! ..
16166! .. Array Arguments ..
16167        KPP_REAL :: A(MAXA)
16168        INTEGER :: INUM(MAXA), JPTR(NC)
16169! ..
16170! .. Local Scalars ..
16171        KPP_REAL :: ACE
16172        INTEGER :: ICE, IK, J, JJ, K, KDUMMY, KLO, KMAX, KOR
16173! ..
16174! .. Intrinsic Functions ..
16175        INTRINSIC IABS
16176! ..
16177! .. FIRST EXECUTABLE STATEMENT MA20BD
16178! ..
16179        KMAX = MAXA
16180        DO JJ = 1, NC
16181          J = NC + 1 - JJ
16182          KLO = JPTR(J) + 1
16183          IF (KLO>KMAX) GOTO 40
16184          KOR = KMAX
16185          DO KDUMMY = KLO, KMAX
16186!           Items KOR,KOR+1,...,KMAX are in order.
16187            ACE = A(KOR-1)
16188            ICE = INUM(KOR-1)
16189            DO K = KOR, KMAX
16190              IK = INUM(K)
16191              IF (IABS(ICE)<=IABS(IK)) GOTO 20
16192              INUM(K-1) = IK
16193              A(K-1) = A(K)
16194            END DO
16195            K = KMAX + 1
1619620          INUM(K-1) = ICE
16197            A(K-1) = ACE
16198            KOR = KOR - 1
16199          END DO
16200!         Next column.
1620140        KMAX = KLO - 2
16202        END DO
16203        RETURN
16204
16205      END SUBROUTINE MC20BD
16206!_______________________________________________________________________
16207
16208      SUBROUTINE MC21A(N,ICN,LICN,IP,LENR,IPERM,NUMNZ,IW)
16209! ..
16210     IMPLICIT NONE
16211! ..
16212! .. Scalar Arguments ..
16213        INTEGER :: LICN, N, NUMNZ
16214! ..
16215! .. Array Arguments ..
16216        INTEGER :: ICN(LICN), IP(N), IPERM(N), IW(N,4), LENR(N)
16217! ..
16218! .. FIRST EXECUTABLE STATEMENT MA21A
16219! ..
16220        CALL MC21B(N,ICN,LICN,IP,LENR,IPERM,NUMNZ,IW(1,1),IW(1,2), &
16221          IW(1,3),IW(1,4))
16222        RETURN
16223
16224      END SUBROUTINE MC21A
16225!_______________________________________________________________________
16226
16227      SUBROUTINE MC21B(N,ICN,LICN,IP,LENR,IPERM,NUMNZ,PR,ARP,CV,OUT)
16228! ..
16229     IMPLICIT NONE
16230! ..
16231! .. Scalar Arguments ..
16232! ..
16233        INTEGER :: LICN, N, NUMNZ
16234! ..
16235! .. Array Arguments ..
16236        INTEGER :: ARP(N), CV(N), ICN(LICN), IP(N), IPERM(N), LENR(N), &
16237          OUT(N), PR(N)
16238! ..
16239! .. Local Scalars ..
16240        INTEGER :: I, II, IN1, IN2, IOUTK, J, J1, JORD, K, KK
16241! ..
16242! .. FIRST EXECUTABLE STATEMENT MA21B
16243! ..
16244! PR(I) is the previous row to I in the depth first search.
16245!    It is used as a work array in the sorting algorithm.
16246!    Elements (IPERM(I),I) I=1,...,N are non-zero at the
16247!    end of the algorithm unless N assignments have not
16248!    been made, in which case (IPERM(I),I) will be zero
16249!    for N-NUMNZ entries.
16250! CV(I) is the most recent row extension at which column I
16251!    was visited.
16252! ARP(I) is one less than the number of non-zeros in row I
16253!    which have not been scanned when looking for a cheap
16254!    assignment.
16255! OUT(I) is one less than the number of non-zeros in row I
16256!    which have not been scanned during one pass through
16257!    the main loop.
16258
16259!       Initialization of arrays.
16260        DO I = 1, N
16261          ARP(I) = LENR(I) - 1
16262          CV(I) = 0
16263          IPERM(I) = 0
16264        END DO
16265        NUMNZ = 0
16266
16267!       Main loop.
16268!       Each pass round this loop either results in a new
16269!       assignment or gives a row with no assignment.
16270        DO 100 JORD = 1, N
16271          J = JORD
16272          PR(J) = -1
16273          DO 70 K = 1, JORD
16274!           Look for a cheap assignment.
16275            IN1 = ARP(J)
16276            IF (IN1<0) GOTO 30
16277            IN2 = IP(J) + LENR(J) - 1
16278            IN1 = IN2 - IN1
16279            DO II = IN1, IN2
16280              I = ICN(II)
16281              IF (IPERM(I)==0) GOTO 80
16282            END DO
16283!           No cheap assignment in row.
16284            ARP(J) = -1
16285!           Begin looking for assignment chain starting with row J.
1628630          OUT(J) = LENR(J) - 1
16287!           Inner loop. Extends chain by one or backtracks.
16288            DO KK = 1, JORD
16289              IN1 = OUT(J)
16290              IF (IN1<0) GOTO 50
16291              IN2 = IP(J) + LENR(J) - 1
16292              IN1 = IN2 - IN1
16293!             Forward scan.
16294              DO 40 II = IN1, IN2
16295                I = ICN(II)
16296                IF (CV(I)==JORD) GOTO 40
16297!               Column I has not yet been accessed during this pass.
16298                J1 = J
16299                J = IPERM(I)
16300                CV(I) = JORD
16301                PR(J) = J1
16302                OUT(J1) = IN2 - II - 1
16303                GOTO 70
1630440            END DO
16305
16306!             Backtracking step.
1630750            J = PR(J)
16308              IF (J==-1) GOTO 100
16309            END DO
16310
1631170        END DO
16312
16313!         New assignment is made.
1631480        IPERM(I) = J
16315          ARP(J) = IN2 - II - 1
16316          NUMNZ = NUMNZ + 1
16317          DO K = 1, JORD
16318            J = PR(J)
16319            IF (J==-1) GOTO 100
16320            II = IP(J) + LENR(J) - OUT(J) - 2
16321            I = ICN(II)
16322            IPERM(I) = J
16323          END DO
16324
16325100     END DO
16326
16327!       If matrix is structurally singular, we now complete the
16328!       permutation IPERM.
16329        IF (NUMNZ==N) RETURN
16330        ARP(1:N) = 0
16331        K = 0
16332        DO 130 I = 1, N
16333          IF (IPERM(I)/=0) GOTO 120
16334          K = K + 1
16335          OUT(K) = I
16336          GOTO 130
16337120       J = IPERM(I)
16338          ARP(J) = I
16339130     END DO
16340        K = 0
16341        DO 140 I = 1, N
16342          IF (ARP(I)/=0) GOTO 140
16343          K = K + 1
16344          IOUTK = OUT(K)
16345          IPERM(IOUTK) = I
16346140     END DO
16347        RETURN
16348
16349      END SUBROUTINE MC21B
16350!_______________________________________________________________________
16351
16352      SUBROUTINE MC22AD(N,ICN,A,NZ,LENROW,IP,IQ,IW,IW1)
16353! ..
16354     IMPLICIT NONE
16355! ..
16356! .. Scalar Arguments ..
16357        INTEGER :: N, NZ
16358! ..
16359! .. Array Arguments ..
16360        KPP_REAL :: A(NZ)
16361        INTEGER :: ICN(NZ), IP(N), IQ(N), IW(N,2), IW1(NZ), LENROW(N)
16362! ..
16363! .. Local Scalars ..
16364        KPP_REAL :: AVAL
16365        INTEGER :: I, ICHAIN, IOLD, IPOS, J, J2, JJ, JNUM, JVAL, LENGTH, &
16366          NEWPOS
16367! ..
16368! .. Intrinsic Functions ..
16369        INTRINSIC IABS
16370! ..
16371! .. FIRST EXECUTABLE STATEMENT MA22AD
16372! ..
16373        IF (NZ<=0) GOTO 90
16374        IF (N<=0) GOTO 90
16375!       Set start of row I in IW(I,1) and LENROW(I) in IW(I,2)
16376        IW(1,1) = 1
16377        IW(1,2) = LENROW(1)
16378        DO I = 2, N
16379          IW(I,1) = IW(I-1,1) + LENROW(I-1)
16380          IW(I,2) = LENROW(I)
16381        END DO
16382!       Permute LENROW according to IP. Set off-sets for new
16383!       position of row IOLD in IW(IOLD,1) and put old row
16384!       indices in IW1 in positions corresponding to the new
16385!       position of this row in A/ICN.
16386        JJ = 1
16387        DO 30 I = 1, N
16388          IOLD = IP(I)
16389          IOLD = IABS(IOLD)
16390          LENGTH = IW(IOLD,2)
16391          LENROW(I) = LENGTH
16392          IF (LENGTH==0) GOTO 30
16393          IW(IOLD,1) = IW(IOLD,1) - JJ
16394          J2 = JJ + LENGTH - 1
16395          DO 20 J = JJ, J2
1639620        IW1(J) = IOLD
16397          JJ = J2 + 1
1639830      END DO
16399!       Set inverse permutation to IQ in IW(:,2).
16400        DO I = 1, N
16401          IOLD = IQ(I)
16402          IOLD = IABS(IOLD)
16403          IW(IOLD,2) = I
16404        END DO
16405!       Permute A and ICN in place, changing to new column numbers.
16406!       Main loop.
16407!       Each pass through this loop places a closed chain of
16408!       column indices in their new (and final) positions.
16409!       This is recorded by setting the iw1 entry to zero so
16410!       that any which are subsequently encountered during
16411!       this major scan can be bypassed.
16412        DO 80 I = 1, NZ
16413          IOLD = IW1(I)
16414          IF (IOLD==0) GOTO 80
16415          IPOS = I
16416          JVAL = ICN(I)
16417!         If row IOLD is in same positions after permutation,
16418!         GOTO 150.
16419          IF (IW(IOLD,1)==0) GOTO 70
16420          AVAL = A(I)
16421!         Chain loop.
16422!         Each pass through this loop places one(permuted) column
16423!         index in its final position, viz. IPOS.
16424          DO ICHAIN = 1, NZ
16425!           NEWPOS is the original position in A/ICN of the
16426!           element to be placed in position IPOS. It is also
16427!           the position of the next element in the chain.
16428            NEWPOS = IPOS + IW(IOLD,1)
16429!           Is chain complete?
16430            IF (NEWPOS==I) GOTO 60
16431            A(IPOS) = A(NEWPOS)
16432            JNUM = ICN(NEWPOS)
16433            ICN(IPOS) = IW(JNUM,2)
16434            IPOS = NEWPOS
16435            IOLD = IW1(IPOS)
16436            IW1(IPOS) = 0
16437!           End of chain loop.
16438          END DO
1643960        A(IPOS) = AVAL
1644070        ICN(IPOS) = IW(JVAL,2)
16441!         END OF MAIN LOOP
1644280      END DO
1644390      RETURN
16444
16445      END SUBROUTINE MC22AD
16446!_______________________________________________________________________
16447
16448      SUBROUTINE MC23AD(N,ICN,A,LICN,LENR,IDISP,IP,IQ,LENOFF,IW,IW1)
16449! ..
16450     IMPLICIT NONE
16451! ..
16452! .. Scalar Arguments ..
16453        INTEGER :: LICN, N
16454! ..
16455! .. Array Arguments ..
16456        KPP_REAL :: A(LICN)
16457        INTEGER :: ICN(LICN), IDISP(2), IP(N), IQ(N), IW(N,5), IW1(N,2), &
16458          LENOFF(N), LENR(N)
16459! ..
16460! .. Local Scalars ..
16461        INTEGER :: I, I1, I2, IBEG, IBLOCK, IEND, II, ILEND, INEW, IOLD, &
16462          IROWB, IROWE, J, JJ, JNEW, JNPOS, JOLD, K, LENI, NZ
16463! ..
16464! .. Intrinsic Functions ..
16465        INTRINSIC MAX, MIN
16466! ..
16467! .. FIRST EXECUTABLE STATEMENT MA23AD
16468! ..
16469!     Input ... N,ICN ... A,ICN,LENR ...
16470!     Set up pointers IW(:,1) to the beginning of the rows
16471!     and set LENOFF equal to LENR.
16472        IW1(1,1) = 1
16473        LENOFF(1) = LENR(1)
16474        IF (N==1) GOTO 20
16475        DO I = 2, N
16476          LENOFF(I) = LENR(I)
16477          IW1(I,1) = IW1(I-1,1) + LENR(I-1)
16478        END DO
16479!       IDISP(1) points to the first position in A/ICN after
16480!       the off-diagonal blocks and untreated rows.
1648120      IDISP(1) = IW1(N,1) + LENR(N)
16482
16483!       Find row permutation ip to make diagonal zero-free.
16484        CALL MC21A(N,ICN,LICN,IW1(1,1),LENR,IP,NUMNZ,IW(1,1))
16485
16486!       Possible error return for structurally singular matrices.
16487        IF (NUMNZ/=N .AND. ABORT) GOTO 170
16488
16489!       IW1(:,2) and LENR are permutations of IW1(:,1) and
16490!       LENR/LENOFF suitable for entry to MC13D since matrix
16491!       with these row pointer and length arrays has maximum
16492!       number of non-zeros on the diagonal.
16493        DO II = 1, N
16494          I = IP(II)
16495          IW1(II,2) = IW1(I,1)
16496          LENR(II) = LENOFF(I)
16497        END DO
16498
16499!       Find symmetric permutation IQ to block lower triangular form.
16500        CALL MC13D(N,ICN,LICN,IW1(1,2),LENR,IQ,IW(1,4),NUM,IW)
16501
16502        IF (NUM/=1) GOTO 60
16503
16504!       Action taken if matrix is irreducible: The
16505!       whole matrix is just moved to the end of the storage.
16506        DO I = 1, N
16507          LENR(I) = LENOFF(I)
16508          IP(I) = I
16509          IQ(I) = I
16510        END DO
16511        LENOFF(1) = -1
16512!       IDISP(1) is the first position after the last element in
16513!       the off-diagonal blocks and untreated rows.
16514        NZ = IDISP(1) - 1
16515        IDISP(1) = 1
16516!       IDISP(2) Is the position in A/ICN of the first element
16517!       in the diagonal blocks.
16518        IDISP(2) = LICN - NZ + 1
16519        LARGE = N
16520        IF (NZ==LICN) GOTO 200
16521        DO K = 1, NZ
16522          J = NZ - K + 1
16523          JJ = LICN - K + 1
16524          A(JJ) = A(J)
16525          ICN(JJ) = ICN(J)
16526        END DO
16527        GOTO 200
16528
16529!       Data structure reordered.
16530
16531!       Form composite row permutation, IP(I) = IP(IQ(I)).
1653260      DO II = 1, N
16533          I = IQ(II)
16534          IW(II,1) = IP(I)
16535        END DO
16536        DO I = 1, N
16537          IP(I) = IW(I,1)
16538        END DO
16539
16540!       Run through blocks in reverse order separating diagonal
16541!       blocks which are moved to the end of the storage. Elements
16542!       in off-diagonal blocks are left in place unless a compress
16543!       is necessary.
16544
16545!       IBEG indicates the lowest value of J for which ICN(J) has
16546!       been set to zero when element in position J was moved to
16547!       the diagonal block part of storage.
16548        IBEG = LICN + 1
16549!       IEND is the position of the first element of those treated
16550!       rows which are in diagonal blocks.
16551        IEND = LICN + 1
16552!       LARGE is the dimension of the largest block encountered
16553!       so far.
16554        LARGE = 0
16555
16556!       NUM is the number of diagonal blocks.
16557        DO K = 1, NUM
16558          IBLOCK = NUM - K + 1
16559!         I1 is first row (in permuted form) of block IBLOCK.
16560!         I2 is last row (in permuted form) of block IBLOCK.
16561          I1 = IW(IBLOCK,4)
16562          I2 = N
16563          IF (K/=1) I2 = IW(IBLOCK+1,4) - 1
16564          LARGE = MAX(LARGE,I2-I1+1)
16565!         Go through the rows of block IBLOCK in the reverse order.
16566          DO II = I1, I2
16567            INEW = I2 - II + I1
16568!           We now deal with row inew in permuted form (row IOLD
16569!           in original matrix).
16570            IOLD = IP(INEW)
16571!           If there is space to move up diagonal block portion
16572!           of row GOTO 110.
16573            IF (IEND-IDISP(1)>=LENOFF(IOLD)) GOTO 110
16574
16575!           In-line compress.
16576!           Moves separated off-diagonal elements and untreated
16577!           rows to front of storage.
16578            JNPOS = IBEG
16579            ILEND = IDISP(1) - 1
16580            IF (ILEND<IBEG) GOTO 180
16581            DO 90 J = IBEG, ILEND
16582              IF (ICN(J)==0) GOTO 90
16583              ICN(JNPOS) = ICN(J)
16584              A(JNPOS) = A(J)
16585              JNPOS = JNPOS + 1
1658690          END DO
16587            IDISP(1) = JNPOS
16588            IF (IEND-JNPOS<LENOFF(IOLD)) GOTO 180
16589            IBEG = LICN + 1
16590!           Reset pointers to the beginning of the rows.
16591            DO 100 I = 2, N
16592100         IW1(I,1) = IW1(I-1,1) + LENOFF(I-1)
16593
16594!           Row IOLD is now split into diagonal and off-diagonal parts.
16595110         IROWB = IW1(IOLD,1)
16596            LENI = 0
16597            IROWE = IROWB + LENOFF(IOLD) - 1
16598!           Backward scan of whole of row IOLD (in original matrix).
16599            IF (IROWE<IROWB) GOTO 130
16600            DO 120 JJ = IROWB, IROWE
16601              J = IROWE - JJ + IROWB
16602              JOLD = ICN(J)
16603!             IW(:,2) holds the inverse permutation to IQ.
16604!             It was set to this in MC13D.
16605              JNEW = IW(JOLD,2)
16606!             IF (JNEW < I1) THEN ...
16607!             Element is in off-diagonal block and so is
16608!             left in situ.
16609              IF (JNEW<I1) GOTO 120
16610!             Element is in diagonal block and is moved to
16611!             the end of the storage.
16612              IEND = IEND - 1
16613              A(IEND) = A(J)
16614              ICN(IEND) = JNEW
16615              IBEG = MIN(IBEG,J)
16616              ICN(J) = 0
16617              LENI = LENI + 1
16618120         END DO
16619
16620            LENOFF(IOLD) = LENOFF(IOLD) - LENI
16621130         LENR(INEW) = LENI
16622          END DO
16623
16624          IP(I2) = -IP(I2)
16625        END DO
16626!       Resets IP(N) to positive value.
16627        IP(N) = -IP(N)
16628!       IDISP(2) is position of first element in diagonal blocks.
16629        IDISP(2) = IEND
16630
16631!       This compress is used to move all off-diagonal elements
16632!       to the front of the storage.
16633        IF (IBEG>LICN) GOTO 200
16634        JNPOS = IBEG
16635        ILEND = IDISP(1) - 1
16636        DO 160 J = IBEG, ILEND
16637          IF (ICN(J)==0) GOTO 160
16638          ICN(JNPOS) = ICN(J)
16639          A(JNPOS) = A(J)
16640          JNPOS = JNPOS + 1
16641160     END DO
16642!       IDISP(1) is first position after last element of
16643!       off-diagonal blocks.
16644        IDISP(1) = JNPOS
16645        GOTO 200
16646
16647!       Error return
16648170     IF (LP/=0) WRITE (LP,90000) NUMNZ
1664990000   FORMAT (' Matrix is structurally singular, rank = ',I6)
16650        IDISP(1) = -1
16651        GOTO 190
16652180     IF (LP/=0) WRITE (LP,90001) N
1665390001   FORMAT (' LICN is not big enough; increase by ',I6)
16654        IDISP(1) = -2
16655190     IF (LP/=0) WRITE (LP,90002)
1665690002   FORMAT (' + Error return from MC23AD')
16657200     RETURN
16658
16659      END SUBROUTINE MC23AD
16660!_______________________________________________________________________
16661
16662      SUBROUTINE MC24AD(N,ICN,A,LICN,LENR,LENRL,W)
16663! ..
16664     IMPLICIT NONE
16665! ..
16666! .. Scalar Arguments ..
16667        INTEGER :: LICN, N
16668! ..
16669! .. Array Arguments ..
16670        KPP_REAL :: A(LICN), W(N)
16671        INTEGER :: ICN(LICN), LENR(N), LENRL(N)
16672! ..
16673! .. Local Scalars ..
16674        KPP_REAL :: AMAXL, AMAXU, WROWL
16675        INTEGER :: I, J, J0, J1, J2, JJ
16676! ..
16677! .. Intrinsic Functions ..
16678        INTRINSIC ABS, MAX
16679! ..
16680! .. FIRST EXECUTABLE STATEMENT MA24AD
16681! ..
16682        AMAXL = ZERO
16683        W(1:N) = ZERO
16684        J0 = 1
16685        DO 60 I = 1, N
16686          IF (LENR(I)==0) GOTO 60
16687          J2 = J0 + LENR(I) - 1
16688          IF (LENRL(I)==0) GOTO 30
16689!         Calculation of 1-norm of L.
16690          J1 = J0 + LENRL(I) - 1
16691          WROWL = ZERO
16692          DO 20 JJ = J0, J1
1669320        WROWL = WROWL + ABS(A(JJ))
16694!         AMAXL is the maximum norm of columns of L so far found.
16695          AMAXL = MAX(AMAXL,WROWL)
16696          J0 = J1 + 1
16697!         Calculation of norms of columns of U(MAX-NORMS).
1669830        J0 = J0 + 1
16699          IF (J0>J2) GOTO 50
16700          DO 40 JJ = J0, J2
16701            J = ICN(JJ)
1670240        W(J) = MAX(ABS(A(JJ)),W(J))
1670350        J0 = J2 + 1
1670460      END DO
16705!       AMAXU is set to maximum max-norm of columns of U.
16706        AMAXU = ZERO
16707        DO I = 1, N
16708          AMAXU = MAX(AMAXU,W(I))
16709        END DO
16710!       GROFAC is MAX U max-norm times MAX L 1-norm.
16711        W(1) = AMAXL*AMAXU
16712        RETURN
16713
16714      END SUBROUTINE MC24AD
16715!_______________________________________________________________________
16716
16717      SUBROUTINE MC19AD(N,NA,A,IRN,ICN,R,C,W)
16718! ..
16719!     MC19A was altered to use same precision for R, C,
16720!     and W as is used for other variables in program.
16721! ..
16722!     REAL A(NA),R(N),C(N),W(N,5)
16723!     R(I) is used to return log(scaling factor for row I).
16724!     C(J) is used to return log(scaling factor for col J).
16725!     W(I,1), W(I,2) hold row,col non-zero counts.
16726!     W(J,3) holds - COL J LOG during execution.
16727!     W(J,4) holds 2-iteration change in W(J,3).
16728!     W(I,5) is used to save average element log for row I.
16729!     INTEGER*2 IRN(NA), ICN(NA)
16730!     IRN(K) gives row number of element in A(K).
16731!     ICN(K) gives col number of element in A(K).
16732! ..
16733     IMPLICIT NONE
16734! ..
16735! .. Scalar Arguments ..
16736        INTEGER :: N, NA
16737! ..
16738! .. Array Arguments ..
16739        KPP_REAL :: A(NA), C(N), R(N), W(N,5)
16740        INTEGER :: ICN(NA), IRN(NA)
16741! ..
16742! .. Local Scalars ..
16743        KPP_REAL :: E, E1, EM, Q, Q1, QM, S, S1, SM, SMIN, U, V
16744        INTEGER :: I, I1, I2, ITER, J, K, MAXIT
16745! ..
16746! .. Intrinsic Functions ..
16747        INTRINSIC ABS, LOG, REAL
16748! ..
16749! .. Data Statements ..
16750!       MAXIT is the maximal permitted number of iterations.
16751!       SMIN is used in a convergence test on (residual norm)**2.
16752        DATA MAXIT/100/, SMIN/0.1/
16753! ..
16754! .. FIRST EXECUTABLE STATEMENT MA19AD
16755! ..
16756!       Check scalar data.
16757        IFAIL = 1
16758        IF (N<1) GOTO 210
16759        IFAIL = 2
16760!       IF (N > 32767)GOTO 230
16761        IFAIL = 2
16762        IFAIL = 0
16763
16764!       Initialise for accumulation of sums and products.
16765        C(1:N) = ZERO
16766        R(1:N) = ZERO
16767        W(1:N,1:4) = ZERO
16768        IF (NA<=0) GOTO 220
16769        DO 40 K = 1, NA
16770          U = ABS(A(K))
16771!         IF (U == ZERO) GOTO 30
16772          IF (ABS(U-ZERO)<=ZERO) GOTO 40
16773          U = LOG(U)
16774          I1 = IRN(K)
16775          I2 = ICN(K)
16776          IF (I1>=1 .AND. I1<=N .AND. I2>=1 .AND. I2<=N) GOTO 30
16777          IF (LP>0) WRITE (LP,90000) K, I1, I2
1677890000     FORMAT (' MC19 error. Element ',I5,' is in row ',I5,' and column ', &
16779            I5)
16780          IFAIL = 3
16781          GOTO 40
16782!         Count row/col non-zeros and compute rhs vectors.
1678330        W(I1,1) = W(I1,1) + 1.
16784          W(I2,2) = W(I2,2) + 1.
16785          R(I1) = R(I1) + U
16786          W(I2,3) = W(I2,3) + U
1678740      END DO
16788        IF (IFAIL==3) GOTO 210
16789
16790!       Divide rhs by diagonal matrices.
16791        DO I = 1, N
16792!        IF (W(I,1) == ZERO) W(I,1) = 1.
16793          IF (ABS(W(I,1))<=ZERO) W(I,1) = ONE
16794          R(I) = R(I)/W(I,1)
16795!         SAVE R(I) FOR USE AT END.
16796          W(I,5) = R(I)
16797!         IF (W(I,2) == ZERO) W(I,2) = 1.
16798          IF (ABS(W(I,2))<=ZERO) W(I,2) = ONE
16799          W(I,3) = W(I,3)/W(I,2)
16800        END DO
16801!       SM = SMIN*FLOAT(NA)
16802        SM = SMIN*REAL(NA)
16803!       Sweep to compute initial residual vector.
16804        DO 60 K = 1, NA
16805!         IF (A(K) == ZERO) GOTO 80
16806          IF (ABS(A(K))<=ZERO) GOTO 60
16807          I = IRN(K)
16808          J = ICN(K)
16809          R(I) = R(I) - W(J,3)/W(I,1)
1681060      END DO
16811
16812!       Initialise iteration.
16813        E = ZERO
16814        Q = 1.
16815        S = ZERO
16816        DO I = 1, N
16817          S = S + W(I,1)*R(I)**2
16818        END DO
16819        IF (S<=SM) GOTO 160
16820
16821!       Iteration loop.
16822        DO ITER = 1, MAXIT
16823!         Sweep through matrix to update residual vector.
16824          DO 80 K = 1, NA
16825!           IF (A(K) == ZERO) GOTO 130
16826            IF (ABS(A(K))<=ZERO) GOTO 80
16827            I = ICN(K)
16828            J = IRN(K)
16829            C(I) = C(I) + R(J)
1683080        END DO
16831          S1 = S
16832          S = ZERO
16833          DO I = 1, N
16834            V = -C(I)/Q
16835            C(I) = V/W(I,2)
16836            S = S + V*C(I)
16837          END DO
16838          E1 = E
16839          E = Q*S/S1
16840          Q = 1. - E
16841          IF (S<=SM) E = ZERO
16842!         Update residual.
16843          DO I = 1, N
16844            R(I) = R(I)*E*W(I,1)
16845          END DO
16846          IF (S<=SM) GOTO 180
16847          EM = E*E1
16848!         Sweep through matrix to update residual vector.
16849          DO 110 K = 1, NA
16850!           IF (A(K) == ZERO) GOTO 152
16851            IF (ABS(A(K))<=ZERO) GOTO 110
16852            I = IRN(K)
16853            J = ICN(K)
16854            R(I) = R(I) + C(J)
16855110       END DO
16856          S1 = S
16857          S = ZERO
16858          DO I = 1, N
16859            V = -R(I)/Q
16860            R(I) = V/W(I,1)
16861            S = S + V*R(I)
16862          END DO
16863          E1 = E
16864          E = Q*S/S1
16865          Q1 = Q
16866          Q = 1. - E
16867!         Special fixup for last iteration.
16868          IF (S<=SM) Q = 1.
16869!         Update colulm scaling powers.
16870          QM = Q*Q1
16871          DO I = 1, N
16872            W(I,4) = (EM*W(I,4)+C(I))/QM
16873            W(I,3) = W(I,3) + W(I,4)
16874          END DO
16875          IF (S<=SM) GOTO 160
16876!         Update residual.
16877          DO I = 1, N
16878            C(I) = C(I)*E*W(I,2)
16879          END DO
16880        END DO
16881160     DO I = 1, N
16882          R(I) = R(I)*W(I,1)
16883        END DO
16884
16885!       Sweep through matrix to prepare to get row scaling powers.
16886180     DO 190 K = 1, NA
16887!         IF (A(K) == ZERO) GOTO 200
16888          IF (ABS(A(K))<=ZERO) GOTO 190
16889          I = IRN(K)
16890          J = ICN(K)
16891          R(I) = R(I) + W(J,3)
16892190     END DO
16893
16894!       Final conversion to output values.
16895        DO I = 1, N
16896          R(I) = R(I)/W(I,1) - W(I,5)
16897          C(I) = -W(I,3)
16898        END DO
16899        GOTO 220
16900210     IF (LP>0) WRITE (LP,90001) IFAIL
1690190001   FORMAT (' Error return ',I2,' from MC19')
16902220     RETURN
16903      END SUBROUTINE MC19AD
16904! End of  MA28 subroutines.
16905!_______________________________________________________________________
16906! Beginning of JACSP routines.
16907! Change Record:
16908! ST 09-01-05
16909!   Convert to F90 using Metcalf converter
16910!   Trim trailing blanks using trimem.pl
16911!   Convert arithmetic operators to F90
16912!   Replace R1MACH by EPSILON
16913!   Run through nag tools suite
16914! ST 09-17-05
16915!   Delete RDUM and IDUM
16916!   Change FCN argument list
16917! ST 09-18-05
16918!   Add subroutine DGROUPDS to define the IGP and JGP arrays for JACSP
16919! ST 09-20-05
16920!   Modify JACSP to produce JACSPDB for sparse, dense, and
16921!   banded Jacobians
16922!_______________________________________________________________________
16923
16924    SUBROUTINE JACSP(FCN,N,T,Y,F,FJAC,NRFJAC,YSCALE,FAC,IOPT,WK, &
16925      LWK,IWK,LIWK,MAXGRP,NGRP,JPNTR,INDROW)
16926
16927! BEGIN PROLOGUE JACSP
16928! DATE WRITTEN 850415
16929! CATEGORY NO. D4
16930! KEYWORDS NUMERICAL DIFFERENCING, SPARSE JACOBIANS
16931! AUTHOR SALANE, DOUGLAS E., SANDIA NATIONAL LABORATORIES
16932!        NUMERICAL MATHEMATICS DIVISION,1642
16933!        ALBUQUERQUE, NM 87185
16934
16935! SUBROUTINE JACSP USES FINITE DIFFERENCES TO COMPUTE THE JACOBIAN OF
16936! A SPARSE SYSTEM OF N EQUATIONS AND N UNKNOWNS. JACSP IS DESIGNED FOR
16937! USE IN NUMERICAL METHODS FOR SOLVING NONLINEAR PROBLEMS WHERE THE
16938! JACOBIAN IS EVALUATED REPEATEDLY AND OFTEN AT NEIGHBORING ARGUMENTS
16939! (E.G., NEWTON'S METHOD OR A BDF METHOD FOR SOVING STIFF ORDINARY
16940! DIFFERENTIAL EQUATIONS). JACSP IS INTENDED FOR APPLICATIONS IN WHICH
16941! THE REQUIRED JACOBIANS ARE LARGE AND SPARSE.
16942
16943! TAKING ADVANTAGE OF SPARSITY.
16944
16945! SUBROUTINE JACSP TAKES ADVANTAGE OF THE SPARSITY OF A MATRIX TO REDUCE
16946! THE NUMBER OF FUNCTION EVALUATIONS REQUIRED TO COMPUTE THE JACOBIAN.
16947! TO REALIZE THIS ADVANTAGE, THE USER MUST PROVIDE JACSP WITH A COLUMN
16948! GROUPING. THIS MEANS THE USER MUST ASSIGN COLUMNS OF THE JACOBIAN TO
16949! MUTUALLY EXCLUSIVE GROUPS BASED ON THE SPARSITY OF THE COLUMNS.THE
16950! DIFFERENCES REQUIRED TO COMPUTE THE NONZERO ELEMENTS IN ALL COLUMNS IN
16951! A GROUP ARE FORMED USING ONLY ONE ADDITIONAL FUNCTION EVALUATION. FOR
16952! MORE DETAILS, THE USER IS REFERRED TO THE REPORT BY D.E. SALANE AND
16953! L.F. SHAMPINE (REF. 1).
16954
16955! THE SUBROUTINE DVDSM (REF 2.) IS THE WAY MOST USERS WILL DETERMINE A
16956! COLUMN GROUPING FOR JACSP. THE USE OF DSM AND JACSP IS DESCRIBED
16957! LATER IN THE PROLOGUE.
16958
16959! STORAGE.
16960
16961! JACSP REQUIRES THE USER TO PROVIDE A SPARSE DATA STRUCTURE FOR THE
16962! JACOBIAN TO BE COMPUTED. JACSP REQUIRES THE USER TO SPECIFY THE
16963! INDICES OF THE NONZERO ELEMENTS IN A COLUMN PACKED SPARSE DATA
16964! STRUCTURE (SEE REF.1). THE SUBROUTINE DVDSM( REF 2.) CAN BE USED TO
16965! ESTABLISH THE SPARSE DATA STRUCTURE REQUIRED BY JACSP. THE USE OF
16966! JACSP AND DSM IS DESCRIBED LATER IN THE PROLOGUE.
16967
16968! ON OUTPUT, SUBROUTINE JACSP WILL RETURN THE JACOBIAN IN ANY ONE OF
16969! THE FOLLOWING THREE FORMATS SPECIFIED BY THE USER.
16970
16971! (1) FULL STORAGE FORMAT.......THE COMPUTED JACOBIAN IS STORED IN
16972!      AN ARRAY WHOSE ROW AND COLUMN DIMENSIONS ARE THE NUMBER OF
16973!      EQUATIONS.
16974
16975! (2) BANDED STORAGE FORMAT.....THE COMPUTED MATRIX IS STORED IN A TWO
16976!      DIMENSIONAL ARRAY WHOSE ROW DIMENSION IS
16977!      2*(NUMBER OF LOWER DIAGONALS) + (THE NUMBER OF UPPER DIAGONALS)
16978!      + 1. THE COLUMN DIMENSION OF THIS ARRAY IS THE NUMBER OF
16979!      EQUATIONS. THIS STORAGE FORMAT IS COMPATIBLE WITH THE LINPACK
16980!      GENERAL BAND MATRIX EQUATION SOLVER.
16981
16982! (3) SPARSE STORAGE FORMAT.....THE COMPUTED JACOBIAN IS STORED IN A
16983!      ONE DIMENSIONAL ARRAY WHOSE LENGTH IS THE NUMBER OF NONZERO
16984!      ELEMENTS IN THE JACOBIAN.
16985
16986! DESCRIPTION
16987
16988!  SUBROUTINE PARAMETERS
16989
16990!  FCN()......A USER-PROVIDED FUNCTION (SEE SUBROUTINE DESCRIPTION).
16991!  N..........THE NUMBER OF EQUATIONS.
16992!  T..........A SCALAR VARIABLE. T IS PROVIDED SO USERS CAN PASS THE
16993!             VALUE OF AN INDEPENDENT VARIALBE TO THE FUNCTION
16994!             EVALUATION ROUTINE.
16995!  Y(*).......AN ARRAY OF DIMENSION N. THE POINT AT WHICH THE
16996!             JACOBIAN IS TO BE EVALUATED.
16997!  F(*).......AN ARRAY OF DIMENSION N. THE EQUATIONS EVALUATED AT
16998!             THE POINT Y.
16999!  FJAC(*,*)..AN ARRAY OF WHOSE DIMENSIONS DEPEND ON THE STORAGE
17000!      FORMAT SELECTED BY THE USER. THE ROW AND COLUMN DIMENSIONS ARE
17001!      SET BY THE USER. IF THE SPARSE MATRIX FORMAT IS SELECTED, FJAC
17002!      SHOULD BE TREATED AS A ONE DIMENSIONAL ARRAY BY THE CALLING
17003!      PROGRAM. FOR FURTHER DETAILS, SEE THE DESCRIPTION OF THE
17004!      PARAMETER IOPT(1) WHICH CONTROLS THE STORAGE FORMAT.
17005
17006!      NOTE THAT IF THE BANDED OR FULL OPTION IS USED,THE USER SHOULD
17007!      ZERO OUT THOSE POSITIONS OF FJAC THAT WILL NOT BE ACCESSED BY
17008!      JACSP. JACSP DOES NOT ZERO OUT THE MATRIX FJAC BEFORE
17009!      COMPUTING THE JACOBIAN. POSITIONS OF FJAC THAT ARE NOT ASSIGNED
17010!      VALUES BY JACSP WILL BE THE SAME ON EXIT AS ON ENTRY TO JACSP.
17011
17012!  NRFJAC.....THE NUMBER OF ROWS IN FJAC AND THE LEADING DIMENSION
17013!             OF FJAC (SEE IOPT(1)).
17014!  NCFJAC.....THE NUMBER OF COLUMNS IN FJAC AND THE COLUMN DIMENSION
17015!             OF FJAC (SEE IOPT(1)).
17016!  YSCALE(*)..AN ARRAY OF DIMENSION N. YSCALE(I) CONTAINS A
17017!     REPRESENTATIVE MAGNITUDE FOR Y(I). YSCALE(I) MUST BE POSITIVE.
17018!     YSCALE IS AN OPTIONAL FEATURE OF THE ROUTINE. IF THE USER DOES
17019!     NOT WISH TO PROVIDE YSCALE, IT CAN BE TREATED AS A DUMMY SCALAR
17020!     VARIABLE (SEE IOPT(3)).
17021
17022!  FAC(*).....AN ARRAY OF DIMENSION N. FAC CONTAINS A PERCENTAGE FOR
17023!     USE IN COMPUTING THE INCREMENT.
17024
17025!     THE NORMAL WAY TO USE THE CODE IS TO LET JACSP ADJUST FAC VALUES.
17026!     IN THIS CASE FAC IS INITIALIZED BY JACSP. ALSO, THE USER MUST
17027!     NOT ALTER FAC VALUES BETWEEN CALLS TO JACSP.
17028
17029!     THE USER MAY PROVIDE FAC VALUES IF DESIRED (SEE IOPT(4) FOR
17030!     DETAILS). IF THE USER PROVIDES FAC VALUES, FAC(I) SHOULD BE
17031!     SHOULD BE SET TO A VALUE BETWEEN O AND 1. JACSP WILL NOT PERMIT
17032!     FAC(I) TO BE SET TO A VALUE THAT RESULTS IN TOO SMALL AN
17033!     INCREMENT. JACSP ENSURES THAT
17034!                     FACMIN <= FAC(I) <= FACMAX.
17035!     FOR FURTHER DETAILS ON FACMIN AND FACMAX SEE
17036!     THE REPORT(REF.3).
17037
17038!  IOPT(*)....AN INTEGER ARRAY OF LENGTH 5 FOR USER SELECTED OPTIONS.
17039
17040!          IOPT(1) CONTROLS THE STORAGE FORMAT.
17041
17042!             IOPT(1) = 0 INDICATES FULL STORAGE FORMAT. SET BOTH
17043!             NRFJAC = N AMD NCFJAC = N.
17044
17045!             IOPT(1) = 1 INDICATES BANDED STORAGE FORMAT. SET
17046!             NRFJAC = 2 * ML + MU + 1 WHERE
17047!             ML = NUMBER OF SUB-DIAGONALS BELOW THE MAIN DIAGONAL AND
17048!             MU = NUMBER OF SUPER-DIAGONALS ABOVE THE MAIN DIAGONAL.
17049!             SET NCFJAC = N.
17050
17051!             IOPT(1) = 2 INDICATES SPARSE STORAGE FORMAT. SET
17052!             NRFJAC = TO THE NUMBER OF NONZEROS IN THE JACOBIAN AND
17053!             SET NCFJAC = 1.
17054
17055!          IOPT(2) MUST BE SET TO THE BANDWIDTH OF THE MATRIX.
17056!          IOPT(2) NEED ONLY BE PROVIDED IF BANDED STORAGE
17057!          FORMAT IS REQUESTED(I.E., IOPT(1) = 1).
17058
17059!          IOPT(3) ALLOWS THE USER TO PROVIDE TYPICAL VALUES
17060!          TO BE USED IN COMPUTING INCREMENTS FOR DIFFERENCING.
17061
17062!             IOPT(3) = 0 INDICATES Y VALUES ARE USED IN COMPUTING
17063!             INCREMENTS. IF IOPT(3) = 0, NO STORAGE IS REQUIRED FOR
17064!             YSCALE AND IT MAY BE TREATED AS A DUMMY VARIABLE.
17065
17066!             IOPT(3) = 1 INDICATES THAT YSCALE VALUES ARE TO BE USED.
17067!             IF IOPT(3) = 1, THE USER MUST PROVIDE AN ARRAY OF NONZERO
17068!             VALUES IN YSCALE.
17069
17070!          IOPT(4) ALLOWS THE USER TO PROVIDE THE VALUES USED
17071!          IN THE FAC ARRAY TO COMPUTE INCREMENTS FOR DIFFERENCING.
17072
17073!             IF IOPT(4) = 0, EACH COMPONENT OF FAC IS
17074!             SET TO THE SQUARE ROOT OF MACHINE UNIT ROUNDOFF ON THE
17075!             FIRST CALL TO JACSP. IOPT(4) IS SET TO ONE ON RETURN.
17076
17077!             IF IOPT(4) = 1, EACH COMPONENT OF FAC MUST BE SET
17078!             BY THE CALLING ROUTINE. UNLESS THE USER WISHES TO
17079!             INITIALIZE FAC, THE FAC ARRAY SHOULD NOT BE ALTERED
17080!             BETWEEN SUBSEQUENT CALLS TO JACSP. ALSO, THE USER
17081!             SHOULD NOT CHANGE THE VALUE OF IOPT(4) RETURNED BY
17082!             JACSP.
17083
17084!          IOPT(5) IS NOT USED IN JACSP.
17085
17086!  WK(*)......A WORK ARRAY OF DIMENSION AT LEAST 3*N
17087!  LWK........THE LENGTH OF THE WORK ARRAY. LWK IS AT LEAST 3*N.
17088!  IWK(*)...AN INTEGER ARRAY OF LENGTH LIWK = 50 + N WHICH GIVES
17089!      DIAGNOSTIC INFORMATION IN POSITIONS 1 THROUGH 50. POSITIONS 51
17090!      THROUGH 50 + N ARE USED AS INTEGER WORKSPACE.
17091
17092!      IWK(1) GIVES THE NUMBER OF TIMES THE INCREMENT FOR DIFFERENCING
17093!      (DEL) WAS COMPUTED AND HAD TO BE INCREASED BECAUSE (Y(JCOL)+DEL)
17094!      -Y(JCOL)) WAS TOO SMALL RELATIVE TO Y(JCOL) OR YSCALE(JCOL).
17095
17096!      IWK(2) GIVES THE NUMBER OF COLUMNS IN WHICH THREE ATTEMPTS WERE
17097!      MADE TO INCREASE A PERCENTAGE FACTOR FOR DIFFERENCING (I.E., A
17098!      COMPONENT IN THE FAC ARRAY) BUT THE COMPUTED DEL REMAINED
17099!      UNACCEPTABLY SMALL RELATIVE TO Y(JCOL) OR YSCALE(JCOL). IN SUCH
17100!      CASES THE PERCENTAGE FACTOR IS SET TO THE SQUARE ROOT OF THE UNIT
17101!      ROUNDOFF OF THE MACHINE. THE FIRST 10 COLUMNS ARE GIVEN IN
17102!      IWK(21),...,IWK(30).
17103
17104!      IWK(3) GIVES THE NUMBER OF COLUMNS IN WHICH THE COMPUTED DEL WAS
17105!      ZERO TO MACHINE PRECISION BECAUSE Y(JCOL) OR YSCALE(JCOL) WAS
17106!      ZERO. IN SUCH CASES DEL IS SET TO THE SQUARE ROOT OF THE UNIT
17107!      ROUNDOFF.
17108
17109!      IWK(4) GIVES THE NUMBER OF COLUMNS WHICH HAD TO BE RECOMPUTED
17110!      BECAUSE THE LARGEST DIFFERENCE FORMED IN THE COLUMN WAS VERY
17111!      CLOSE TO ZERO RELATIVE TO SCALE WHERE
17112
17113!                    SCALE = MAX(F(Y),F(Y+DEL))
17114!                                 I     I
17115
17116!      AND I DENOTES THE ROW INDEX OF THE LARGEST DIFFERENCE IN THE
17117!      COLUMN CURRENTLY BEING PROCESSED. IWK(31),...,IWK(40) GIVES THE
17118!      FIRST 10 OF THESE COLUMNS.
17119
17120!      IWK(5) GIVES THE NUMBER OF COLUMNS WHOSE LARGEST DIFFERENCE IS
17121!      CLOSE TO ZERO RELATIVE TO SCALE AFTER THE COLUMN HAS BEEN
17122!      RECOMPUTED. THE FIRST 10 OF THESE COLUMNS ARE GIVEN IN POSITIONS
17123!      IWK(41)...IWK(50).
17124!      IWK(6) GIVES THE NUMBER OF TIMES SCALE INFORMATION WAS NOT
17125!      AVAILABLE FOR USE IN THE ROUNDOFF AND TRUNCATION ERROR TESTS.
17126!      THIS OCCURS WHEN
17127!                    MIN(F(Y),F(Y+DEL)) = 0.
17128!                          I     I
17129!      WHERE I IS THE INDEX OF THE LARGEST DIFFERENCE FOR THE COLUMN
17130!      CURRENTLY BEING PROCESSED.
17131!      IWK(7) GIVES THE NUMBER OF TIMES THE FUNCTION EVALUATION ROUTINE
17132!      WAS CALLED.
17133!      IWK(8) GIVES THE NUMBER OF TIMES A COMPONENT OF THE FAC ARRAY WAS
17134!      REDUCED BECAUSE CHANGES IN FUNCTION VALUES WERE LARGE AND EXCESS
17135!      TRUNCATION ERROR WAS SUSPECTED. IWK(11),...,IWK(20) GIVES THE FIRST
17136!      10 OF THESE COLUMNS.
17137!      IWK(9) AND IWK(10) ARE NOT USED IN JACSP.
17138!  LIWK.....THE LENGTH OF THE ARRAY IWK. LIWK = 50 + N.
17139!      THE FOLLOWING PARAMETERS MAY BE PROVIDED BY THE USER OR
17140!      INITIALIZED BY THE SUBROUTINE DVDSM (SEE LONG DESCRIPTION
17141!      SECTION OF THE PROLOGUE).
17142!  PARAMETERS CONTAINING COLUMN GROUPING:
17143!  MAXGRP.....THE NUMBER OF DIFFERENT GROUPS TO WHICH THE COLUMNS
17144!             HAVE BEEN ASSIGNED.
17145!  NGRP(*)....AN ARRAY OF LENGTH N THAT CONTAINS THE COLUMN GROUPING.
17146!             NGRP(I) IS THE GROUP TO WHICH THE I-TH COLUMN HAS BEEN
17147!             ASSIGNED.
17148!             (SEE USE OF DSM AND JACSP FOR DETERMINING MAXGRP AND NGRP)
17149!  PARAMETERS CONTAINING THE SPARSE DATA STRUCTURE:
17150!  JPNTR(*)...AN ARRAY OF LENGTH N+1 THAT CONTAINS POINTERS TO
17151!             THE ROW INDICES IN INDROW (SEE INDROW).
17152!  INDROW(*)..AN ARRAY WHOSE LENGTH IS THE NUMBER OF NONZERO ELEMENTS
17153!             IN THE JACOBIAN. INDROW CONTAINS THE ROW INDICES
17154!             STORED IN COLUMN PACKED FORMAT. IN OTHER WORDS, THE
17155!             ROW INDICES OF THE NONZERO ELEMENTS OF A GIVEN
17156!             COLUMN OF THE JACOBIAN ARE STORED CONTIGUOUSLY IN
17157!             INDROW. JPNTR(JCOL) POINTS TO THE ROW INDEX OF THE FIRST
17158!             NONZERO ELEMENT IN THE COLUMN JCOL. JPNTR(JCOL+1) - 1
17159!             POINTS TO THE ROW INDEX OF THE LAST NONZERO ELEMENT IN
17160!             THE COLUMN JCOL.
17161!             (SEE USE OF DSM AND JACSP FOR DETERMINING INDROW AND JPNTR)
17162!  REQUIRED SUBROUTINES: SUBROUTINE FCN(N,T,Y,F)
17163!     T......AN INDEPENDENT SCALAR VARIABLE WHICH MAY BE USED
17164!           IN EVALUATING F(E.G., F(Y(T),T)).
17165!     Y(*)...AN ARRAY OF DIMENSION N WHICH CONTAINS THE POINT AT
17166!            WHICH THE EQUATIONS ARE TO BE EVALUATED.
17167!     F(*)...AN ARRAY OF DIMENSION N WHICH ON RETURN FROM FCN
17168!            CONTAINS THE EQUATIONS EVALUATED AT Y.
17169
17170! LONG DESCRIPTION
17171
17172! ROUNDOFF AND TRUNCATION ERRORS.
17173! SUBROUTINE JACSP TAKES ADVANTAGE OF THE WAY IN WHICH THE JACOBIAN
17174! IS EVALUATED TO ADJUST INCREMENTS FOR DIFFERENCING TO CONTROL
17175! ROUNDOFF AND TRUNCATION ERRORS. THE ROUTINE SELDOM REQUIRES MORE
17176! THAN ONE ADDITIONAL FUNCTION EVALUATION TO COMPUTE A COLUMN OF THE
17177! JACOBIAN. ALSO, THE ROUTINE RETURNS A VARIETY OF ERROR DIAGNOSTICS
17178! TO WARN USERS WHEN COMPUTED DERIVATIVES MAY NOT BE ACCURATE.
17179! WARNING: JACSP CAN NOT GUARANTEE THE ACCURACY OF THE COMPUTED
17180! DERIVATIVES. IN ORDER O SAVE ON FUNCTION EVALUATIONS, HEURISTIC
17181! TECNIQUES FOR INCREMENT ADJUSTMENT AND SAFEGUARDING INCREMENTS ARE
17182! USED. THESE USUALLY WORK WELL.
17183
17184! WARNING: SOME OF THE DIAGNOSTICS RETURNED CAN ONLY BE INTERPRETED
17185! WITH A DETAILED KNOWLEDGE OF THE ROUTINE. NEVERTHELESS, THEY ARE
17186! PROVIDED TO GIVE USERS FULL ACCESS TO THE INFORMATION PRODUCED BY
17187! THE SUBROUTINE.
17188! USE OF DSM AND JACSP.
17189! SUBROUTINE DVDSM CAN BE USED TO DETERMINE THE COLUMN GROUPING (MAXGRP
17190! AND NGRP(*)) AND THE SPARSE DATA STRUCTURE VARIABLES (JPNTR(*) AND
17191! INDROW(*)). THE USER CAN CALL DVDSM ONCE TO INITIALIZE
17192! MAXGRP,NGRP,JPNTR AND INDROW. JACSP MAY THEN BE CALLED REPEATEDLY TO
17193! EVALUATE THE JACOBIAN. THE FOLLOWING ARE THE IMPORTANT VARIABLES IN
17194! THE DSM CALLING SEQUENCE.
17195! SUBROUTINE DVDSM(...,INDROW,INDCOL,NGRP,MAXGRP,..,JPNTR,...)
17196! ON INPUT, THE USER MUST PROVIDE DSM WITH THE INTEGER ARRAYS INDROW AND
17197! INDCOL. THE PAIR
17198!                  (INDROW(I),INDCOL(I))
17199! PROVIDES THE INDEX OF A NONZERO ELEMENT OF THE JACOBIAN. THE LENGTH OF
17200! INDROW AND INDCOL IS THE NUMBER OF NONZERO ELEMENTS IN THE JACOBIAN.
17201! NO ORDERING OF THE INDICES FOR NONZERO ELEMENTS IS REQUIRED IN THE
17202! ARRAYS INDROW AND INDCOL.
17203! ON RETURN FROM DSM, MAXGRP,NGRP,INDROW,JPNTR ARE INITIALIZED
17204! FOR INPUT TO JACSP. THE USER MUST NOT CHANGE MAXGRP,NGRP,JPNTR OR
17205! INDROW AFTER CALLING DSM.
17206! WE REFER THE READER TO THE IN CODE DOCUMENTATION FOR DSM OR THE REPORT
17207! BY MORE AND COLEMAN (REF 2.) FOR FURTHER DETAILS.
17208! REFERENCES
17209!  (1) D.E. SALANE AND L. F. SHAMPINE
17210!      "AN ECONOMICAL AND EFFICIENT ROUTINE FOR COMPUTING
17211!      SPARSE JACOBIANS", REPORT NO. SAND85-0977, SANDIA NATIONAL
17212!      LABORATORIES, ALBUQUERQUE,NM,87185.
17213!  (2) T.F. COLEMAN AND J.J. MORE
17214!      "SOFTWARE FOR ESTIMATING SPARSE JACOBIAN MATRICES" ACM TOMS,
17215!      V10.,N0.3,SEPT. 1984.
17216!  (3) D.E. SALANE AND L. F. SHAMPINE
17217!      "THREE ADAPTIVE ROUTINES FOR FORMING JACOBIANS NUMERICALLY,"
17218!       REPORT NO. SAND86- ****, SANDIA NATIONAL LABORATORIES,
17219!       ALBUQUERQUE, NM, 87185.
17220!  REQUIRED FORTRAN INTRINSIC FUNCTIONS: MAX,MIN,ABS,SIGN
17221!  MACHINE DEPENDENT CONSTANT: U (MACHINE UNIT ROUNDOFF)
17222!  JACSP SETS THE REQUIRED MACHINE CONSTANT USING THE F90
17223!  INTRINSIC EPSILON.
17224!  END PROLOGUE JACSP
17225
17226     IMPLICIT NONE
17227
17228! .. Parameters ..
17229      INTEGER, PARAMETER :: WP = KIND(0.0D0)
17230! ..
17231! .. Scalar Arguments ..
17232      KPP_REAL :: T
17233      INTEGER :: LIWK, LWK, MAXGRP, N, NRFJAC
17234! ..
17235! .. Array Arguments ..
17236      KPP_REAL :: F(N), FAC(N), FJAC(NRFJAC,*), WK(LWK), Y(N), YSCALE(*)
17237      INTEGER :: INDROW(*), IOPT(5), IWK(LIWK), JPNTR(*), NGRP(N)
17238! ..
17239! .. Subroutine Arguments ..
17240      EXTERNAL FCN
17241! ..
17242! .. Local Scalars ..
17243      KPP_REAL :: ADIFF, AY, DEL, DELM, DFMJ, DIFF, DMAX, EXPFMN, FACMAX, &
17244        FACMIN, FJACL, FMJ, ONE, P125, P25, P75, P875, PERT, RDEL, RMNFDF, &
17245        RMXFDF, SDF, SF, SGN, T1, T2, U, U3QRT, U7EGT, UEGT, UMEGT, UQRT, &
17246        USQT, ZERO
17247      INTEGER :: IDXL, IDXU, IFLAG1, IFLAG2, IRCMP, IRDEL, IROW, IROWB, &
17248        IROWMX, ITRY, J, JCOL, KT1, KT2, KT3, KT4, KT5, L, NID1, NID2, NID3, &
17249        NID4, NID5, NID6, NIFAC, NT2, NUMGRP
17250! ..
17251! .. Intrinsic Functions ..
17252!     INTRINSIC ABS, EPSILON, KIND, MAX, MIN, SIGN, SQRT
17253      INTRINSIC ABS, EPSILON, MAX, MIN, SIGN, SQRT
17254! ..
17255! .. Data Statements ..
17256      DATA PERT/2.0E+0_dp/, FACMAX/1.E-1_dp/, EXPFMN/.75E+0_dp/
17257      DATA ONE/1.0E0_dp/, ZERO/0.0E0_dp/
17258      DATA P125/.125E+0_dp/, P25/.25E+0_dp/, P75/.75E+0_dp/, P875/.875E+0_dp/
17259      DATA NIFAC/3/, NID1/10/, NID2/20/, NID3/30/, NID4/40/, NID5/50/
17260! ..
17261!     COMPUTE ALGORITHM AND MACHINE CONSTANTS.
17262! ..
17263! ..  FIRST EXECUTABLE STATEMENT JACSP
17264! ..
17265      U = EPSILON(ONE)
17266      USQT = SQRT(U)
17267      UEGT = U**P125
17268      UMEGT = ONE/UEGT
17269      UQRT = U**P25
17270      U3QRT = U**P75
17271      U7EGT = U**P875
17272      FACMIN = U**EXPFMN
17273
17274      IF (IOPT(4) == 0) THEN
17275        IOPT(4) = 1
17276        DO 10 J = 1, N
17277          FAC(J) = USQT
1727810      CONTINUE
17279      END IF
17280      DO 20 J = 1, 50
17281        IWK(J) = 0
1728220    CONTINUE
17283      KT1 = NID1
17284      KT2 = NID2
17285      KT3 = NID3
17286      KT4 = NID4
17287      KT5 = NID5
17288      NID6 = LIWK
17289      NT2 = 2*N
17290      DO NUMGRP = 1, MAXGRP
17291!       COMPUTE AND SAVE THE INCREMENTS FOR THE COLUMNS IN GROUP NUMGRP.
17292        IRCMP = 0
17293        ITRY = 0
17294        DO 30 J = NID5 + 1, NID6
17295          IWK(J) = 0
1729630      CONTINUE
1729740      CONTINUE
17298        DO JCOL = 1, N
17299          IF (NGRP(JCOL) == NUMGRP) THEN
17300            WK(N+JCOL) = Y(JCOL)
17301!           COMPUTE DEL. IF DEL IS TOO SMALL INCREASE FAC(JCOL) AND RECOMPUTE
17302!           DEL. NIFAC ATTEMPTS ARE MADE TO INCREASE FAC(JCOL) AND FIND AN
17303!           APPROPRIATE DEL. IF DEL CANT BE FOUND IN THIS MANNER, DEL IS COMPUTED
17304!           WITH FAC(JCOL) SET TO THE SQUARE ROOT OF THE MACHINE PRECISION (USQT).
17305!           IF DEL IS ZERO TO MACHINE PRECISION BECAUSE Y(JCOL) IS ZERO OR
17306!           YSCALE(JCOL) IS ZERO, DEL IS SET TO USQT.
17307            SGN = SIGN(ONE,F(JCOL))
17308            IRDEL = 0
17309            IF (IOPT(3) == 1) THEN
17310              AY = ABS(YSCALE(JCOL))
17311            ELSE
17312              AY = ABS(Y(JCOL))
17313            END IF
17314            DELM = U7EGT*AY
17315
17316            DO 50 J = 1, NIFAC
17317              DEL = FAC(JCOL)*AY*SGN
17318!             IF (DEL == ZERO) THEN
17319              IF (ABS(DEL) <= ZERO) THEN
17320
17321                DEL = USQT*SGN
17322                IF (ITRY == 0) IWK(3) = IWK(3) + 1
17323              END IF
17324              T1 = Y(JCOL) + DEL
17325              DEL = T1 - Y(JCOL)
17326              IF (ABS(DEL) < DELM) THEN
17327                IF (J >= NIFAC) GOTO 50
17328                IF (IRDEL == 0) THEN
17329                  IRDEL = 1
17330                  IWK(1) = IWK(1) + 1
17331                END IF
17332                T1 = FAC(JCOL)*UMEGT
17333                FAC(JCOL) = MIN(T1,FACMAX)
17334              ELSE
17335                GOTO 60
17336              END IF
1733750          END DO
17338
17339            FAC(JCOL) = USQT
17340            DEL = USQT*AY*SGN
17341            IWK(2) = IWK(2) + 1
17342            IF (KT2 < NID3) THEN
17343              KT2 = KT2 + 1
17344              IWK(KT2) = JCOL
17345            END IF
17346
1734760          CONTINUE
17348            WK(NT2+JCOL) = DEL
17349            Y(JCOL) = Y(JCOL) + DEL
17350          END IF
17351        END DO
17352
17353        IWK(7) = IWK(7) + 1
17354        CALL FCN(N,T,Y,WK)
17355        DO JCOL = 1, N
17356          IF (NGRP(JCOL) == NUMGRP) Y(JCOL) = WK(N+JCOL)
17357        END DO
17358
17359!       COMPUTE THE JACOBIAN ENTRIES FOR ALL COLUMNS IN NUMGRP.
17360!       STORE ENTRIES ACCORDING TO SELECTED STORAGE FORMAT.
17361!       USE LARGEST ELEMENTS IN A COLUMN TO DETERMINE SCALING
17362!       INFORMATION FOR ROUNDOFF AND TRUNCATION ERROR TESTS.
17363        DO JCOL = 1, N
17364          IF (NGRP(JCOL) == NUMGRP) THEN
17365            IDXL = JPNTR(JCOL)
17366            IDXU = JPNTR(JCOL+1) - 1
17367            DMAX = ZERO
17368            RDEL = ONE/WK(NT2+JCOL)
17369            IROWMX = 1
17370            DO L = IDXL, IDXU
17371              IROW = INDROW(L)
17372              DIFF = WK(IROW) - F(IROW)
17373              ADIFF = ABS(DIFF)
17374              IF (ADIFF >= DMAX) THEN
17375                IROWMX = IROW
17376                DMAX = ADIFF
17377                SF = F(IROW)
17378                SDF = WK(IROW)
17379              END IF
17380              FJACL = DIFF*RDEL
17381              IF (ITRY == 1) WK(IROW) = FJACL
17382
17383              IF (IOPT(1) == 0) THEN
17384                IF (ITRY == 1) WK(IROW+N) = FJAC(IROW,JCOL)
17385                FJAC(IROW,JCOL) = FJACL
17386              END IF
17387              IF (IOPT(1) == 1) THEN
17388                IROWB = IROW - JCOL + IOPT(2)
17389                IF (ITRY == 1) WK(IROW+N) = FJAC(IROWB,JCOL)
17390                FJAC(IROWB,JCOL) = FJACL
17391              END IF
17392              IF (IOPT(1) == 2) THEN
17393                IF (ITRY == 1) WK(IROW+N) = FJAC(L,1)
17394                FJAC(L,1) = FJACL
17395              END IF
17396            END DO
17397
17398!           IF A COLUMN IS BEING RECOMPUTED (ITRY=1),THIS SECTION OF THE
17399!           CODE PERFORMS AN EXTRAPOLATION TEST TO ENABLE THE CODE TO
17400!           COMPUTE SMALL DERIVATIVES MORE ACCURATELY. THIS TEST IS ONLY
17401!           PERFORMED ON THOSE COLUMNS WHOSE LARGEST DIFFERENCE IS CLOSE
17402!           TO ZERO RELATIVE TO SCALE.
17403            IF (ITRY == 1) THEN
17404              IFLAG1 = 0
17405              IFLAG2 = 0
17406              DO 100 J = NID5 + 1, NID6
17407                IF (IWK(J) == JCOL) IFLAG1 = 1
17408100           CONTINUE
17409              IF (IFLAG1 == 1) THEN
17410                IFLAG1 = 0
17411                T1 = WK(IROWMX+N)
17412                T2 = WK(IROWMX)*FAC(JCOL)
17413                IF (ABS(T2) < ABS(T1)*PERT) IFLAG2 = 1
17414              END IF
17415
17416              IF (IFLAG2 == 1) THEN
17417                IFLAG2 = 0
17418                T1 = FAC(JCOL)*FAC(JCOL)
17419                FAC(JCOL) = MAX(T1,FACMIN)
17420                DO L = IDXL, IDXU
17421                  IROW = INDROW(L)
17422                  FJACL = WK(IROW+N)
17423                  IF (IOPT(1) == 0) FJAC(IROW,JCOL) = FJACL
17424                  IF (IOPT(1) == 1) THEN
17425                    IROWB = IROW - JCOL + IOPT(2)
17426                    FJAC(IROWB,JCOL) = FJACL
17427                  END IF
17428                  IF (IOPT(1) == 2) FJAC(L,1) = FJACL
17429                END DO
17430              END IF
17431            END IF
17432
17433            FMJ = ABS(SF)
17434            DFMJ = ABS(SDF)
17435            RMXFDF = MAX(FMJ,DFMJ)
17436            RMNFDF = MIN(FMJ,DFMJ)
17437
17438!           IF SCALE INFORMATION IS NOT AVAILABLE, PERFORM NO ROUNDOFF
17439!           OR TRUNCATION ERROR TESTS. IF THE EXTRAPOLATION TEST HAS
17440!           CAUSED FAC(JCOL) TO BE RESET TO ITS PREVIOUS VALUE (IAJAC=1)
17441!           THEN NO FURTHER ROUNDOFF OR TRUNCATION ERROR TESTS ARE
17442!           PERFORMED.
17443!           IF (RMNFDF/=ZERO) THEN
17444            IF (ABS(RMNFDF) > ZERO) THEN
17445!             TEST FOR POSSIBLE ROUNDOFF ERROR (FIRST TEST)
17446!             AND ALSO FOR POSSIBLE SERIOUS ROUNDOFF ERROR (SECOND TEST).
17447              IF (DMAX <= (U3QRT*RMXFDF)) THEN
17448                IF (DMAX <= (U7EGT*RMXFDF)) THEN
17449                  IF (ITRY == 0) THEN
17450                    T1 = SQRT(FAC(JCOL))
17451                    FAC(JCOL) = MIN(T1,FACMAX)
17452                    IRCMP = 1
17453                    IF (KT5 < NID6) THEN
17454                      KT5 = KT5 + 1
17455                      IWK(KT5) = JCOL
17456                    END IF
17457                    IWK(4) = IWK(4) + 1
17458                    IF (KT3 < NID4) THEN
17459                      KT3 = KT3 + 1
17460                      IWK(KT3) = JCOL
17461                    END IF
17462                  ELSE
17463                    IWK(5) = IWK(5) + 1
17464                    IF (KT4 < NID5) THEN
17465                      KT4 = KT4 + 1
17466                      IWK(KT4) = JCOL
17467                    END IF
17468                  END IF
17469                ELSE
17470                  T1 = UMEGT*FAC(JCOL)
17471                  FAC(JCOL) = MIN(T1,FACMAX)
17472                END IF
17473              END IF
17474!             TEST FOR POSSIBLE TRUNCATION ERROR.
17475              IF (DMAX > UQRT*RMXFDF) THEN
17476                T1 = FAC(JCOL)*UEGT
17477                FAC(JCOL) = MAX(T1,FACMIN)
17478                IWK(8) = IWK(8) + 1
17479                IF (KT1 < NID2) THEN
17480                  KT1 = KT1 + 1
17481                  IWK(KT1) = JCOL
17482                END IF
17483              END IF
17484            ELSE
17485              IWK(6) = IWK(6) + 1
17486            END IF
17487          END IF
17488        END DO
17489
17490!       IF SERIOUS ROUNDOFF ERROR IS SUSPECTED, RECOMPUTE ALL
17491!       COLUMNS IN GROUP NUMGRP.
17492        IF (IRCMP == 1) THEN
17493          IRCMP = 0
17494          ITRY = 1
17495          GOTO 40
17496        END IF
17497        ITRY = 0
17498      END DO
17499      RETURN
17500
17501    END SUBROUTINE JACSP
17502!_______________________________________________________________________
17503
17504    SUBROUTINE DEGR(N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,IWA)
17505
17506!     GIVEN THE SPARSITY PATTERN OF AN M BY N MATRIX A,
17507!     THIS SUBROUTINE DETERMINES THE DEGREE SEQUENCE FOR
17508!     THE INTERSECTION GRAPH OF THE COLUMNS OF A.
17509!     IN GRAPH-THEORY TERMINOLOGY, THE INTERSECTION GRAPH OF
17510!     THE COLUMNS OF A IS THE LOOPLESS GRAPH G WITH VERTICES
17511!     A(J), J = 1,2,...,N WHERE A(J) IS THE J-TH COLUMN OF A
17512!     AND WITH EDGE (A(I),A(J)) IF AND ONLY IF COLUMNS I AND J
17513!     HAVE A NON-ZERO IN THE SAME ROW POSITION.
17514!     NOTE THAT THE VALUE OF M IS NOT NEEDED BY DEGR AND IS
17515!     THEREFORE NOT PRESENT IN THE SUBROUTINE STATEMENT.
17516!     THE SUBROUTINE STATEMENT IS
17517!       SUBROUTINE DEGR(N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,IWA)
17518!     WHERE
17519!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
17520!         OF COLUMNS OF A.
17521!       INDROW IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
17522!         INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17523!       JPNTR IS AN INTEGER INPUT ARRAY OF LENGTH N + 1 WHICH
17524!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
17525!         THE ROW INDICES FOR COLUMN J ARE
17526!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
17527!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
17528!         ELEMENTS OF THE MATRIX A.
17529!       INDCOL IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE
17530!         COLUMN INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17531!       IPNTR IS AN INTEGER INPUT ARRAY OF LENGTH M + 1 WHICH
17532!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
17533!         THE COLUMN INDICES FOR ROW I ARE
17534!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
17535!         NOTE THAT IPNTR(M+1)-1 IS THEN THE NUMBER OF NON-ZERO
17536!         ELEMENTS OF THE MATRIX A.
17537!       NDEG IS AN INTEGER OUTPUT ARRAY OF LENGTH N WHICH
17538!         SPECIFIES THE DEGREE SEQUENCE. THE DEGREE OF THE
17539!         J-TH COLUMN OF A IS NDEG(J).
17540!       IWA IS AN INTEGER WORK ARRAY OF LENGTH N.
17541!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
17542!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
17543
17544     IMPLICIT NONE
17545
17546! .. Scalar Arguments ..
17547      INTEGER :: N
17548! ..
17549! .. Array Arguments ..
17550      INTEGER :: INDCOL(*), INDROW(*), IPNTR(*), IWA(N), JPNTR(N+1), NDEG(N)
17551! ..
17552! .. Local Scalars ..
17553      INTEGER :: IC, IP, IR, JCOL, JP
17554! ..
17555! ..  FIRST EXECUTABLE STATEMENT DEGR
17556! ..
17557!     INITIALIZATION BLOCK.
17558      NDEG(1:N) = 0
17559      IWA(1:N) = 0
17560
17561!     COMPUTE THE DEGREE SEQUENCE BY DETERMINING THE CONTRIBUTIONS
17562!     TO THE DEGREES FROM THE CURRENT (JCOL) COLUMN AND FURTHER
17563!     COLUMNS WHICH HAVE NOT YET BEEN CONSIDERED.
17564      DO JCOL = 2, N
17565        IWA(JCOL) = N
17566!       DETERMINE ALL POSITIONS (IR,JCOL) WHICH CORRESPOND
17567!       TO NON-ZEROES IN THE MATRIX.
17568        DO JP = JPNTR(JCOL), JPNTR(JCOL+1) - 1
17569          IR = INDROW(JP)
17570!         FOR EACH ROW IR, DETERMINE ALL POSITIONS (IR,IC)
17571!         WHICH CORRESPOND TO NON-ZEROES IN THE MATRIX.
17572          DO IP = IPNTR(IR), IPNTR(IR+1) - 1
17573            IC = INDCOL(IP)
17574!           ARRAY IWA MARKS COLUMNS WHICH HAVE CONTRIBUTED TO
17575!           THE DEGREE COUNT OF COLUMN JCOL. UPDATE THE DEGREE
17576!           COUNTS OF THESE COLUMNS AS WELL AS COLUMN JCOL.
17577            IF (IWA(IC) < JCOL) THEN
17578              IWA(IC) = JCOL
17579              NDEG(IC) = NDEG(IC) + 1
17580              NDEG(JCOL) = NDEG(JCOL) + 1
17581            END IF
17582          END DO
17583        END DO
17584      END DO
17585      RETURN
17586
17587    END SUBROUTINE DEGR
17588!_______________________________________________________________________
17589
17590    SUBROUTINE IDO(M,N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,LIST,MAXCLQ, &
17591      IWA1,IWA2,IWA3,IWA4)
17592
17593!     SUBROUTINE IDO
17594!     GIVEN THE SPARSITY PATTERN OF AN M BY N MATRIX A, THIS
17595!     SUBROUTINE DETERMINES AN INCIDENCE-DEGREE ORDERING OF THE
17596!     COLUMNS OF A.
17597!     THE INCIDENCE-DEGREE ORDERING IS DEFINED FOR THE LOOPLESS
17598!     GRAPH G WITH VERTICES A(J), J = 1,2,...,N WHERE A(J) IS THE
17599!     J-TH COLUMN OF A AND WITH EDGE (A(I),A(J)) IF AND ONLY IF
17600!     COLUMNS I AND J HAVE A NON-ZERO IN THE SAME ROW POSITION.
17601!     THE INCIDENCE-DEGREE ORDERING IS DETERMINED RECURSIVELY BY
17602!     LETTING LIST(K), K = 1,...,N BE A COLUMN WITH MAXIMAL
17603!     INCIDENCE TO THE SUBGRAPH SPANNED BY THE ORDERED COLUMNS.
17604!     AMONG ALL THE COLUMNS OF MAXIMAL INCIDENCE, IDO CHOOSES A
17605!     COLUMN OF MAXIMAL DEGREE.
17606!     THE SUBROUTINE STATEMENT IS
17607!       SUBROUTINE IDO(M,N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,LIST,
17608!                      MAXCLQ,IWA1,IWA2,IWA3,IWA4)
17609!     WHERE
17610!       M IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
17611!         OF ROWS OF A.
17612!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
17613!         OF COLUMNS OF A.
17614!       INDROW IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
17615!         INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17616!       JPNTR IS AN INTEGER INPUT ARRAY OF LENGTH N + 1 WHICH
17617!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
17618!         THE ROW INDICES FOR COLUMN J ARE
17619!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
17620!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
17621!         ELEMENTS OF THE MATRIX A.
17622!       INDCOL IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE
17623!         COLUMN INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17624!       IPNTR IS AN INTEGER INPUT ARRAY OF LENGTH M + 1 WHICH
17625!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
17626!         THE COLUMN INDICES FOR ROW I ARE
17627!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
17628!         NOTE THAT IPNTR(M+1)-1 IS THEN THE NUMBER OF NON-ZERO
17629!         ELEMENTS OF THE MATRIX A.
17630!       NDEG IS AN INTEGER INPUT ARRAY OF LENGTH N WHICH SPECIFIES
17631!         THE DEGREE SEQUENCE. THE DEGREE OF THE J-TH COLUMN
17632!         OF A IS NDEG(J).
17633!       LIST IS AN INTEGER OUTPUT ARRAY OF LENGTH N WHICH SPECIFIES
17634!         THE INCIDENCE-DEGREE ORDERING OF THE COLUMNS OF A. THE J-TH
17635!         COLUMN IN THIS ORDER IS LIST(J).
17636!       MAXCLQ IS AN INTEGER OUTPUT VARIABLE SET TO THE SIZE
17637!         OF THE LARGEST CLIQUE FOUND DURING THE ORDERING.
17638!       IWA1,IWA2,IWA3, AND IWA4 ARE INTEGER WORK ARRAYS OF LENGTH N.
17639!     SUBPROGRAMS CALLED
17640!       MINPACK-SUPPLIED ... NUMSRT
17641!       INTRINSIC ... MAX
17642!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
17643!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
17644
17645     IMPLICIT NONE
17646
17647! .. Scalar Arguments ..
17648      INTEGER :: M, MAXCLQ, N
17649! ..
17650! .. Array Arguments ..
17651      INTEGER :: INDCOL(*), INDROW(*), IPNTR(M+1), IWA1(0:N-1), IWA2(N), &
17652        IWA3(N), IWA4(N), JPNTR(N+1), LIST(N), NDEG(N)
17653! ..
17654! .. Local Scalars ..
17655      INTEGER :: IC, IP, IR, JCOL, JP, MAXINC, MAXLST, NCOMP, NUMINC, NUMLST, &
17656        NUMORD, NUMWGT
17657! ..
17658! .. External Subroutines ..
17659!     EXTERNAL NUMSRT
17660! ..
17661! .. Intrinsic Functions ..
17662      INTRINSIC MAX
17663! ..
17664! ..  FIRST EXECUTABLE STATEMENT IDO
17665! ..
17666!     SORT THE DEGREE SEQUENCE.
17667      CALL NUMSRT(N,N-1,NDEG,-1,IWA4,IWA2,IWA3)
17668
17669!     INITIALIZATION BLOCK.
17670
17671!     CREATE A DOUBLY-LINKED LIST TO ACCESS THE INCIDENCES OF THE
17672!     COLUMNS. THE POINTERS FOR THE LINKED LIST ARE AS FOLLOWS.
17673
17674!     EACH UNORDERED COLUMN IC IS IN A LIST (THE INCIDENCE LIST)
17675!     OF COLUMNS WITH THE SAME INCIDENCE.
17676
17677!     IWA1(NUMINC) IS THE FIRST COLUMN IN THE NUMINC LIST
17678!     UNLESS IWA1(NUMINC) = 0. IN THIS CASE THERE ARE
17679!     NO COLUMNS IN THE NUMINC LIST.
17680
17681!     IWA2(IC) IS THE COLUMN BEFORE IC IN THE INCIDENCE LIST
17682!     UNLESS IWA2(IC) = 0. IN THIS CASE IC IS THE FIRST
17683!     COLUMN IN THIS INCIDENCE LIST.
17684
17685!     IWA3(IC) IS THE COLUMN AFTER IC IN THE INCIDENCE LIST
17686!     UNLESS IWA3(IC) = 0. IN THIS CASE IC IS THE LAST
17687!     COLUMN IN THIS INCIDENCE LIST.
17688
17689!     IF IC IS AN UN-ORDERED COLUMN, THEN LIST(IC) IS THE
17690!     INCIDENCE OF IC TO THE GRAPH INDUCED BY THE ORDERED
17691!     COLUMNS. IF JCOL IS AN ORDERED COLUMN, THEN LIST(JCOL)
17692!     IS THE INCIDENCE-DEGREE ORDER OF COLUMN JCOL.
17693
17694      MAXINC = 0
17695      DO JP = N, 1, -1
17696        IC = IWA4(JP)
17697        IWA1(N-JP) = 0
17698        IWA2(IC) = 0
17699        IWA3(IC) = IWA1(0)
17700        IF (IWA1(0) > 0) IWA2(IWA1(0)) = IC
17701        IWA1(0) = IC
17702        IWA4(JP) = 0
17703        LIST(JP) = 0
17704      END DO
17705
17706!     DETERMINE THE MAXIMAL SEARCH LENGTH FOR THE LIST
17707!     OF COLUMNS OF MAXIMAL INCIDENCE.
17708      MAXLST = 0
17709      DO IR = 1, M
17710        MAXLST = MAXLST + (IPNTR(IR+1)-IPNTR(IR))**2
17711      END DO
17712      MAXLST = MAXLST/N
17713      MAXCLQ = 0
17714      NUMORD = 1
17715
17716!     BEGINNING OF ITERATION LOOP.
17717
1771830    CONTINUE
17719
17720!     UPDATE THE SIZE OF THE LARGEST CLIQUE
17721!     FOUND DURING THE ORDERING.
17722      IF (MAXINC == 0) NCOMP = 0
17723      NCOMP = NCOMP + 1
17724      IF (MAXINC+1 == NCOMP) MAXCLQ = MAX(MAXCLQ,NCOMP)
17725
17726!     CHOOSE A COLUMN JCOL OF MAXIMAL DEGREE AMONG THE
17727!     COLUMNS OF MAXIMAL INCIDENCE MAXINC.
1772840    CONTINUE
17729      JP = IWA1(MAXINC)
17730      IF (JP > 0) GOTO 50
17731      MAXINC = MAXINC - 1
17732      GOTO 40
1773350    CONTINUE
17734      NUMWGT = -1
17735      DO NUMLST = 1, MAXLST
17736        IF (NDEG(JP) > NUMWGT) THEN
17737          NUMWGT = NDEG(JP)
17738          JCOL = JP
17739        END IF
17740        JP = IWA3(JP)
17741        IF (JP <= 0) GOTO 70
17742      END DO
1774370    CONTINUE
17744      LIST(JCOL) = NUMORD
17745      NUMORD = NUMORD + 1
17746
17747!     TERMINATION TEST.
17748      IF (NUMORD > N) GOTO 100
17749
17750!     DELETE COLUMN JCOL FROM THE MAXINC LIST.
17751      IF (IWA2(JCOL) == 0) THEN
17752        IWA1(MAXINC) = IWA3(JCOL)
17753      ELSE
17754        IWA3(IWA2(JCOL)) = IWA3(JCOL)
17755      END IF
17756      IF (IWA3(JCOL) > 0) IWA2(IWA3(JCOL)) = IWA2(JCOL)
17757
17758!     FIND ALL COLUMNS ADJACENT TO COLUMN JCOL.
17759      IWA4(JCOL) = N
17760
17761!     DETERMINE ALL POSITIONS(IR,JCOL) WHICH CORRESPOND
17762!     TO NON-ZEROES IN THE MATRIX.
17763      DO JP = JPNTR(JCOL), JPNTR(JCOL+1) - 1
17764        IR = INDROW(JP)
17765!       FOR EACH ROW IR, DETERMINE ALL POSITIONS(IR,IC)
17766!       WHICH CORRESPOND TO NON-ZEROES IN THE MATRIX.
17767        DO IP = IPNTR(IR), IPNTR(IR+1) - 1
17768          IC = INDCOL(IP)
17769!         ARRAY IWA4 MARKS COLUMNS WHICH ARE ADJACENT TO
17770!         COLUMN JCOL.
17771          IF (IWA4(IC) < NUMORD) THEN
17772            IWA4(IC) = NUMORD
17773!           UPDATE THE POINTERS TO THE CURRENT INCIDENCE LISTS.
17774            NUMINC = LIST(IC)
17775            LIST(IC) = LIST(IC) + 1
17776            MAXINC = MAX(MAXINC,LIST(IC))
17777!           DELETE COLUMN IC FROM THE NUMINC LIST.
17778            IF (IWA2(IC) == 0) THEN
17779              IWA1(NUMINC) = IWA3(IC)
17780            ELSE
17781              IWA3(IWA2(IC)) = IWA3(IC)
17782            END IF
17783            IF (IWA3(IC) > 0) IWA2(IWA3(IC)) = IWA2(IC)
17784!           ADD COLUMN IC TO THE NUMINC+1 LIST.
17785            IWA2(IC) = 0
17786            IWA3(IC) = IWA1(NUMINC+1)
17787            IF (IWA1(NUMINC+1) > 0) IWA2(IWA1(NUMINC+1)) = IC
17788            IWA1(NUMINC+1) = IC
17789          END IF
17790        END DO
17791      END DO
17792!     END OF ITERATION LOOP.
17793      GOTO 30
17794100   CONTINUE
17795!     INVERT THE ARRAY LIST.
17796      DO JCOL = 1, N
17797        IWA2(LIST(JCOL)) = JCOL
17798      END DO
17799      LIST(1:N) = IWA2(1:N)
17800      RETURN
17801
17802    END SUBROUTINE IDO
17803!_______________________________________________________________________
17804
17805    SUBROUTINE NUMSRT(N,NMAX,NUM,MODE,INDEX,LAST,NEXT)
17806
17807!     GIVEN A SEQUENCE OF INTEGERS, THIS SUBROUTINE GROUPS TOGETHER THOSE
17808!     INDICES WITH THE SAME SEQUENCE VALUE AND, OPTIONALLY, SORTS THE
17809!     SEQUENCE INTO EITHER ASCENDING OR DESCENDING ORDER. THE SEQUENCE
17810!     OF INTEGERS IS DEFINED BY THE ARRAY NUM, AND IT IS ASSUMED THAT THE
17811!     INTEGERS ARE EACH FROM THE SET 0,1,...,NMAX. ON OUTPUT THE INDICES
17812!     K SUCH THAT NUM(K) = L FOR ANY L = 0,1,...,NMAX CAN BE OBTAINED
17813!     FROM THE ARRAYS LAST AND NEXT AS FOLLOWS.
17814!           K = LAST(L)
17815!           WHILE(K /= 0) K = NEXT(K)
17816!     OPTIONALLY, THE SUBROUTINE PRODUCES AN ARRAY INDEX SO THAT
17817!     THE SEQUENCE NUM(INDEX(I)), I = 1,2,...,N IS SORTED.
17818!     THE SUBROUTINE STATEMENT IS
17819!       SUBROUTINE NUMSRT(N,NMAX,NUM,MODE,INDEX,LAST,NEXT)
17820!     WHERE
17821!       N IS A POSITIVE INTEGER INPUT VARIABLE.
17822!       NMAX IS A POSITIVE INTEGER INPUT VARIABLE.
17823!       NUM IS AN INPUT ARRAY OF LENGTH N WHICH CONTAINS THE
17824!         SEQUENCE OF INTEGERS TO BE GROUPED AND SORTED. IT
17825!         IS ASSUMED THAT THE INTEGERS ARE EACH FROM THE SET
17826!         0,1,...,NMAX.
17827!       MODE IS AN INTEGER INPUT VARIABLE. THE SEQUENCE NUM IS
17828!         SORTED IN ASCENDING ORDER IF MODE IS POSITIVE AND IN
17829!         DESCENDING ORDER IF MODE IS NEGATIVE. IF MODE IS 0,
17830!         NO SORTING IS DONE.
17831!       INDEX IS AN INTEGER OUTPUT ARRAY OF LENGTH N SET SO
17832!         THAT THE SEQUENCE
17833!               NUM(INDEX(I)), I = 1,2,...,N
17834!         IS SORTED ACCORDING TO THE SETTING OF MODE. IF MODE
17835!         IS 0, INDEX IS NOT REFERENCED.
17836!       LAST IS AN INTEGER OUTPUT ARRAY OF LENGTH NMAX + 1. THE
17837!         INDEX OF NUM FOR THE LAST OCCURRENCE OF L IS LAST(L)
17838!         FOR ANY L = 0,1,...,NMAX UNLESS LAST(L) = 0. IN
17839!         THIS CASE L DOES NOT APPEAR IN NUM.
17840!       NEXT IS AN INTEGER OUTPUT ARRAY OF LENGTH N. IF
17841!         NUM(K) = L, THEN THE INDEX OF NUM FOR THE PREVIOUS
17842!         OCCURRENCE OF L IS NEXT(K) FOR ANY L = 0,1,...,NMAX
17843!         UNLESS NEXT(K) = 0. IN THIS CASE THERE IS NO PREVIOUS
17844!         OCCURRENCE OF L IN NUM.
17845!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
17846!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
17847
17848      IMPLICIT NONE
17849
17850! .. Scalar Arguments ..
17851      INTEGER :: MODE, N, NMAX
17852! ..
17853! .. Array Arguments ..
17854      INTEGER :: INDEX(N), LAST(0:NMAX), NEXT(N), NUM(N)
17855! ..
17856! .. Local Scalars ..
17857      INTEGER :: I, J, JINC, JL, JU, K, L
17858! ..
17859! ..  FIRST EXECUTABLE STATEMENT NUMSRT
17860! ..
17861!     DETERMINE THE ARRAYS NEXT AND LAST.
17862      LAST(0:NMAX) = 0
17863      DO K = 1, N
17864        L = NUM(K)
17865        NEXT(K) = LAST(L)
17866        LAST(L) = K
17867      END DO
17868      IF (MODE == 0) RETURN
17869
17870!     STORE THE POINTERS TO THE SORTED ARRAY IN INDEX.
17871      I = 1
17872      IF (MODE > 0) THEN
17873        JL = 0
17874        JU = NMAX
17875        JINC = 1
17876      ELSE
17877        JL = NMAX
17878        JU = 0
17879        JINC = -1
17880      END IF
17881      DO J = JL, JU, JINC
17882        K = LAST(J)
1788330      CONTINUE
17884        IF (K == 0) GOTO 40
17885        INDEX(I) = K
17886        I = I + 1
17887        K = NEXT(K)
17888        GOTO 30
1788940      CONTINUE
17890      END DO
17891      RETURN
17892
17893    END SUBROUTINE NUMSRT
17894!_______________________________________________________________________
17895
17896    SUBROUTINE SEQ(N,INDROW,JPNTR,INDCOL,IPNTR,LIST,NGRP,MAXGRP,IWA)
17897
17898!     GIVEN THE SPARSITY PATTERN OF AN M BY N MATRIX A, THIS
17899!     SUBROUTINE DETERMINES A CONSISTENT PARTITION OF THE
17900!     COLUMNS OF A BY A SEQUENTIAL ALGORITHM.
17901!     A CONSISTENT PARTITION IS DEFINED IN TERMS OF THE LOOPLESS
17902!     GRAPH G WITH VERTICES A(J), J = 1,2,...,N WHERE A(J) IS THE
17903!     J-TH COLUMN OF A AND WITH EDGE(A(I),A(J)) IF AND ONLY IF
17904!     COLUMNS I AND J HAVE A NON-ZERO IN THE SAME ROW POSITION.
17905!     A PARTITION OF THE COLUMNS OF A INTO GROUPS IS CONSISTENT
17906!     IF THE COLUMNS IN ANY GROUP ARE NOT ADJACENT IN THE GRAPH G.
17907!     IN GRAPH-THEORY TERMINOLOGY, A CONSISTENT PARTITION OF THE
17908!     COLUMNS OF A CORRESPONDS TO A COLORING OF THE GRAPH G.
17909!     THE SUBROUTINE EXAMINES THE COLUMNS IN THE ORDER SPECIFIED
17910!     BY THE ARRAY LIST, AND ASSIGNS THE CURRENT COLUMN TO THE
17911!     GROUP WITH THE SMALLEST POSSIBLE NUMBER.
17912!     NOTE THAT THE VALUE OF M IS NOT NEEDED BY SEQ AND IS
17913!     THEREFORE NOT PRESENT IN THE SUBROUTINE STATEMENT.
17914!     THE SUBROUTINE STATEMENT IS
17915!     SUBROUTINE SEQ(N,INDROW,JPNTR,INDCOL,IPNTR,LIST,NGRP,MAXGRP,IWA)
17916!     WHERE
17917!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
17918!         OF COLUMNS OF A.
17919!       INDROW IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
17920!         INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17921!       JPNTR IS AN INTEGER INPUT ARRAY OF LENGTH N + 1 WHICH
17922!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
17923!         THE ROW INDICES FOR COLUMN J ARE
17924!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
17925!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
17926!         ELEMENTS OF THE MATRIX A.
17927!       INDCOL IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE
17928!         COLUMN INDICES FOR THE NON-ZEROES IN THE MATRIX A.
17929!       IPNTR IS AN INTEGER INPUT ARRAY OF LENGTH M + 1 WHICH
17930!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
17931!         THE COLUMN INDICES FOR ROW I ARE
17932!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
17933!         NOTE THAT IPNTR(M+1)-1 IS THEN THE NUMBER OF NON-ZERO
17934!         ELEMENTS OF THE MATRIX A.
17935!       LIST IS AN INTEGER INPUT ARRAY OF LENGTH N WHICH SPECIFIES
17936!         THE ORDER TO BE USED BY THE SEQUENTIAL ALGORITHM.
17937!         THE J-TH COLUMN IN THIS ORDER IS LIST(J).
17938!       NGRP IS AN INTEGER OUTPUT ARRAY OF LENGTH N WHICH SPECIFIES
17939!         THE PARTITION OF THE COLUMNS OF A. COLUMN JCOL BELONGS
17940!         TO GROUP NGRP(JCOL).
17941!       MAXGRP IS AN INTEGER OUTPUT VARIABLE WHICH SPECIFIES THE
17942!         NUMBER OF GROUPS IN THE PARTITION OF THE COLUMNS OF A.
17943!       IWA IS AN INTEGER WORK ARRAY OF LENGTH N.
17944!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
17945!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
17946
17947     IMPLICIT NONE
17948
17949! .. Scalar Arguments ..
17950      INTEGER :: MAXGRP, N
17951! ..
17952! .. Array Arguments ..
17953      INTEGER :: INDCOL(*), INDROW(*), IPNTR(*), IWA(N), JPNTR(N+1), &
17954        LIST(N), NGRP(N)
17955! ..
17956! .. Local Scalars ..
17957      INTEGER :: IC, IP, IR, J, JCOL, JP
17958! ..
17959! ..  FIRST EXECUTABLE STATEMENT SEQ
17960! ..
17961!     INITIALIZATION BLOCK.
17962      MAXGRP = 0
17963      NGRP(1:N) = N
17964      IWA(1:N) = 0
17965
17966!     BEGINNING OF ITERATION LOOP.
17967
17968      DO J = 1, N
17969        JCOL = LIST(J)
17970!       FIND ALL COLUMNS ADJACENT TO COLUMN JCOL.
17971!       DETERMINE ALL POSITIONS (IR,JCOL) WHICH CORRESPOND
17972!       TO NON-ZEROES IN THE MATRIX.
17973        DO JP = JPNTR(JCOL), JPNTR(JCOL+1) - 1
17974          IR = INDROW(JP)
17975!         FOR EACH ROW IR, DETERMINE ALL POSITIONS (IR,IC)
17976!         WHICH CORRESPOND TO NON-ZEROES IN THE MATRIX.
17977          DO IP = IPNTR(IR), IPNTR(IR+1) - 1
17978            IC = INDCOL(IP)
17979!           ARRAY IWA MARKS THE GROUP NUMBERS OF THE
17980!           COLUMNS WHICH ARE ADJACENT TO COLUMN JCOL.
17981            IWA(NGRP(IC)) = J
17982          END DO
17983        END DO
17984!       ASSIGN THE SMALLEST UN-MARKED GROUP NUMBER TO JCOL.
17985        DO JP = 1, MAXGRP
17986          IF (IWA(JP)/=J) GOTO 50
17987        END DO
17988        MAXGRP = MAXGRP + 1
1798950      CONTINUE
17990        NGRP(JCOL) = JP
17991      END DO
17992
17993!     END OF ITERATION LOOP.
17994
17995      RETURN
17996
17997    END SUBROUTINE SEQ
17998!_______________________________________________________________________
17999
18000    SUBROUTINE SETR(M,N,INDROW,JPNTR,INDCOL,IPNTR,IWA)
18001
18002!     GIVEN A COLUMN-ORIENTED DEFINITION OF THE SPARSITY PATTERN
18003!     OF AN M BY N MATRIX A, THIS SUBROUTINE DETERMINES A
18004!     ROW-ORIENTED DEFINITION OF THE SPARSITY PATTERN OF A.
18005!     ON INPUT THE COLUMN-ORIENTED DEFINITION IS SPECIFIED BY
18006!     THE ARRAYS INDROW AND JPNTR. ON OUTPUT THE ROW-ORIENTED
18007!     DEFINITION IS SPECIFIED BY THE ARRAYS INDCOL AND IPNTR.
18008!     THE SUBROUTINE STATEMENT IS
18009!       SUBROUTINE SETR(M,N,INDROW,JPNTR,INDCOL,IPNTR,IWA)
18010!     WHERE
18011!       M IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18012!         OF ROWS OF A.
18013!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18014!         OF COLUMNS OF A.
18015!       INDROW IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
18016!         INDICES FOR THE NON-ZEROES IN THE MATRIX A.
18017!       JPNTR IS AN INTEGER INPUT ARRAY OF LENGTH N + 1 WHICH
18018!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
18019!         THE ROW INDICES FOR COLUMN J ARE
18020!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
18021!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
18022!         ELEMENTS OF THE MATRIX A.
18023!       INDCOL IS AN INTEGER OUTPUT ARRAY WHICH CONTAINS THE
18024!         COLUMN INDICES FOR THE NON-ZEROES IN THE MATRIX A.
18025!       IPNTR IS AN INTEGER OUTPUT ARRAY OF LENGTH M + 1 WHICH
18026!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
18027!         THE COLUMN INDICES FOR ROW I ARE
18028!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
18029!         NOTE THAT IPNTR(1) IS SET TO 1 AND THAT IPNTR(M+1)-1 IS
18030!         THEN THE NUMBER OF NON-ZERO ELEMENTS OF THE MATRIX A.
18031!       IWA IS AN INTEGER WORK ARRAY OF LENGTH M.
18032!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
18033!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
18034
18035     IMPLICIT NONE
18036
18037! .. Scalar Arguments ..
18038      INTEGER :: M, N
18039! ..
18040! .. Array Arguments ..
18041      INTEGER :: INDCOL(*), INDROW(*), IPNTR(M+1), IWA(M), JPNTR(N+1)
18042! ..
18043! .. Local Scalars ..
18044      INTEGER :: IR, JCOL, JP
18045! ..
18046! ..  FIRST EXECUTABLE STATEMENT SETR
18047! ..
18048!     STORE IN ARRAY IWA THE COUNTS OF NON-ZEROES IN THE ROWS.
18049      IWA(1:M) = 0
18050      DO JP = 1, JPNTR(N+1) - 1
18051        IWA(INDROW(JP)) = IWA(INDROW(JP)) + 1
18052      END DO
18053
18054!     SET POINTERS TO THE START OF THE ROWS IN INDCOL.
18055      IPNTR(1) = 1
18056      DO IR = 1, M
18057        IPNTR(IR+1) = IPNTR(IR) + IWA(IR)
18058        IWA(IR) = IPNTR(IR)
18059      END DO
18060
18061!     FILL INDCOL.
18062      DO JCOL = 1, N
18063        DO JP = JPNTR(JCOL), JPNTR(JCOL+1) - 1
18064          IR = INDROW(JP)
18065          INDCOL(IWA(IR)) = JCOL
18066          IWA(IR) = IWA(IR) + 1
18067        END DO
18068      END DO
18069      RETURN
18070
18071    END SUBROUTINE SETR
18072!_______________________________________________________________________
18073
18074    SUBROUTINE SLO(N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,LIST,MAXCLQ,IWA1,IWA2, &
18075        IWA3,IWA4)
18076
18077!     GIVEN THE SPARSITY PATTERN OF AN M BY N MATRIX A, THIS
18078!     SUBROUTINE DETERMINES THE SMALLEST-LAST ORDERING OF THE
18079!     COLUMNS OF A.
18080!     THE SMALLEST-LAST ORDERING IS DEFINED FOR THE LOOPLESS
18081!     GRAPH G WITH VERTICES A(J), J = 1,2,...,N WHERE A(J) IS THE
18082!     J-TH COLUMN OF A AND WITH EDGE(A(I),A(J)) IF AND ONLY IF
18083!     COLUMNS I AND J HAVE A NON-ZERO IN THE SAME ROW POSITION.
18084!     THE SMALLEST-LAST ORDERING IS DETERMINED RECURSIVELY BY
18085!     LETTING LIST(K), K = N,...,1 BE A COLUMN WITH LEAST DEGREE
18086!     IN THE SUBGRAPH SPANNED BY THE UN-ORDERED COLUMNS.
18087!     NOTE THAT THE VALUE OF M IS NOT NEEDED BY SLO AND IS
18088!     THEREFORE NOT PRESENT IN THE SUBROUTINE STATEMENT.
18089!     THE SUBROUTINE STATEMENT IS
18090!     SUBROUTINE SLO(N,INDROW,JPNTR,INDCOL,IPNTR,NDEG,LIST, &
18091!                    MAXCLQ,IWA1,IWA2,IWA3,IWA4)
18092!     WHERE
18093!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18094!         OF COLUMNS OF A.
18095!       INDROW IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
18096!         INDICES FOR THE NON-ZEROES IN THE MATRIX A.
18097!       JPNTR IS AN INTEGER INPUT ARRAY OF LENGTH N + 1 WHICH
18098!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
18099!         THE ROW INDICES FOR COLUMN J ARE
18100!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
18101!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
18102!         ELEMENTS OF THE MATRIX A.
18103!       INDCOL IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE
18104!         COLUMN INDICES FOR THE NON-ZEROES IN THE MATRIX A.
18105!       IPNTR IS AN INTEGER INPUT ARRAY OF LENGTH M + 1 WHICH
18106!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
18107!         THE COLUMN INDICES FOR ROW I ARE
18108!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
18109!         NOTE THAT IPNTR(M+1)-1 IS THEN THE NUMBER OF NON-ZERO
18110!         ELEMENTS OF THE MATRIX A.
18111!       NDEG IS AN INTEGER INPUT ARRAY OF LENGTH N WHICH SPECIFIES
18112!         THE DEGREE SEQUENCE. THE DEGREE OF THE J-TH COLUMN
18113!         OF A IS NDEG(J).
18114!       LIST IS AN INTEGER OUTPUT ARRAY OF LENGTH N WHICH SPECIFIES
18115!         THE SMALLEST-LAST ORDERING OF THE COLUMNS OF A. THE J-TH
18116!         COLUMN IN THIS ORDER IS LIST(J).
18117!       MAXCLQ IS AN INTEGER OUTPUT VARIABLE SET TO THE SIZE
18118!         OF THE LARGEST CLIQUE FOUND DURING THE ORDERING.
18119!       IWA1,IWA2,IWA3, AND IWA4 ARE INTEGER WORK ARRAYS OF LENGTH N.
18120!     SUBPROGRAMS CALLED
18121!       INTRINSIC ... MIN
18122!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
18123!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
18124
18125     IMPLICIT NONE
18126
18127! .. Scalar Arguments ..
18128      INTEGER :: MAXCLQ, N
18129! ..
18130! .. Array Arguments ..
18131      INTEGER :: INDCOL(*), INDROW(*), IPNTR(*), IWA1(0:N-1), IWA2(N), &
18132        IWA3(N), IWA4(N), JPNTR(N+1), LIST(N), NDEG(N)
18133! ..
18134! .. Local Scalars ..
18135      INTEGER :: IC, IP, IR, JCOL, JP, MINDEG, NUMDEG, NUMORD
18136! ..
18137! .. Intrinsic Functions ..
18138      INTRINSIC MIN
18139! ..
18140! ..  FIRST EXECUTABLE STATEMENT SLO
18141! ..
18142!     INITIALIZATION BLOCK.
18143      MINDEG = N
18144      DO JP = 1, N
18145        IWA1(JP-1) = 0
18146        IWA4(JP) = N
18147        LIST(JP) = NDEG(JP)
18148        MINDEG = MIN(MINDEG,NDEG(JP))
18149      END DO
18150
18151!     CREATE A DOUBLY-LINKED LIST TO ACCESS THE DEGREES OF THE
18152!     COLUMNS. THE POINTERS FOR THE LINKED LIST ARE AS FOLLOWS.
18153
18154!     EACH UN-ORDERED COLUMN IC IS IN A LIST (THE DEGREE LIST)
18155!     OF COLUMNS WITH THE SAME DEGREE.
18156
18157!     IWA1(NUMDEG) IS THE FIRST COLUMN IN THE NUMDEG LIST
18158!     UNLESS IWA1(NUMDEG) = 0. IN THIS CASE THERE ARE
18159!     NO COLUMNS IN THE NUMDEG LIST.
18160
18161!     IWA2(IC) IS THE COLUMN BEFORE IC IN THE DEGREE LIST
18162!     UNLESS IWA2(IC) = 0. IN THIS CASE IC IS THE FIRST
18163!     COLUMN IN THIS DEGREE LIST.
18164
18165!     IWA3(IC) IS THE COLUMN AFTER IC IN THE DEGREE LIST
18166!     UNLESS IWA3(IC) = 0. IN THIS CASE IC IS THE LAST
18167!     COLUMN IN THIS DEGREE LIST.
18168
18169!     IF IC IS AN UN-ORDERED COLUMN, THEN LIST(IC) IS THE
18170!     DEGREE OF IC IN THE GRAPH INDUCED BY THE UN-ORDERED
18171!     COLUMNS. IF JCOL IS AN ORDERED COLUMN, THEN LIST(JCOL)
18172!     IS THE SMALLEST-LAST ORDER OF COLUMN JCOL.
18173
18174      DO JP = 1, N
18175        NUMDEG = NDEG(JP)
18176        IWA2(JP) = 0
18177        IWA3(JP) = IWA1(NUMDEG)
18178        IF (IWA1(NUMDEG) > 0) IWA2(IWA1(NUMDEG)) = JP
18179        IWA1(NUMDEG) = JP
18180      END DO
18181      MAXCLQ = 0
18182      NUMORD = N
18183
18184!     BEGINNING OF ITERATION LOOP.
18185
1818630    CONTINUE
18187
18188!     MARK THE SIZE OF THE LARGEST CLIQUE
18189!     FOUND DURING THE ORDERING.
18190      IF (MINDEG+1 == NUMORD .AND. MAXCLQ == 0) MAXCLQ = NUMORD
18191
18192!     CHOOSE A COLUMN JCOL OF MINIMAL DEGREE MINDEG.
1819340    CONTINUE
18194      JCOL = IWA1(MINDEG)
18195      IF (JCOL > 0) GOTO 50
18196      MINDEG = MINDEG + 1
18197      GOTO 40
1819850    CONTINUE
18199      LIST(JCOL) = NUMORD
18200      NUMORD = NUMORD - 1
18201
18202!     TERMINATION TEST.
18203      IF (NUMORD == 0) GOTO 80
18204
18205!     DELETE COLUMN JCOL FROM THE MINDEG LIST.
18206      IWA1(MINDEG) = IWA3(JCOL)
18207      IF (IWA3(JCOL) > 0) IWA2(IWA3(JCOL)) = 0
18208
18209!     FIND ALL COLUMNS ADJACENT TO COLUMN JCOL.
18210      IWA4(JCOL) = 0
18211
18212!     DETERMINE ALL POSITIONS (IR,JCOL) WHICH CORRESPOND
18213!     TO NON-ZEROES IN THE MATRIX.
18214      DO JP = JPNTR(JCOL), JPNTR(JCOL+1) - 1
18215        IR = INDROW(JP)
18216!       FOR EACH ROW IR, DETERMINE ALL POSITIONS (IR,IC)
18217!       WHICH CORRESPOND TO NON-ZEROES IN THE MATRIX.
18218        DO IP = IPNTR(IR), IPNTR(IR+1) - 1
18219          IC = INDCOL(IP)
18220!         ARRAY IWA4 MARKS COLUMNS WHICH ARE ADJACENT TO
18221!         COLUMN JCOL.
18222
18223          IF (IWA4(IC) > NUMORD) THEN
18224            IWA4(IC) = NUMORD
18225!           UPDATE THE POINTERS TO THE CURRENT DEGREE LISTS.
18226            NUMDEG = LIST(IC)
18227            LIST(IC) = LIST(IC) - 1
18228            MINDEG = MIN(MINDEG,LIST(IC))
18229!           DELETE COLUMN IC FROM THE NUMDEG LIST.
18230            IF (IWA2(IC) == 0) THEN
18231              IWA1(NUMDEG) = IWA3(IC)
18232            ELSE
18233              IWA3(IWA2(IC)) = IWA3(IC)
18234            END IF
18235            IF (IWA3(IC) > 0) IWA2(IWA3(IC)) = IWA2(IC)
18236!           ADD COLUMN IC TO THE NUMDEG-1 LIST.
18237            IWA2(IC) = 0
18238            IWA3(IC) = IWA1(NUMDEG-1)
18239            IF (IWA1(NUMDEG-1) > 0) IWA2(IWA1(NUMDEG-1)) = IC
18240            IWA1(NUMDEG-1) = IC
18241          END IF
18242        END DO
18243      END DO
18244!     END OF ITERATION LOOP.
18245
18246      GOTO 30
1824780    CONTINUE
18248
18249!     INVERT THE ARRAY LIST.
18250      DO JCOL = 1, N
18251        IWA2(LIST(JCOL)) = JCOL
18252      END DO
18253      LIST(1:N) = IWA2(1:N)
18254      RETURN
18255
18256    END SUBROUTINE SLO
18257!_______________________________________________________________________
18258
18259    SUBROUTINE SRTDAT(N,NNZ,INDROW,INDCOL,JPNTR,IWA)
18260
18261!     GIVEN THE NON-ZERO ELEMENTS OF AN M BY N MATRIX A IN ARBITRARY
18262!     ORDER AS SPECIFIED BY THEIR ROW AND COLUMN INDICES, THIS SUBROUTINE
18263!     PERMUTES THESE ELEMENTS SO THAT THEIR COLUMN INDICES ARE IN
18264!     NON-DECREASING ORDER. ON INPUT IT IS ASSUMED THAT THE ELEMENTS ARE
18265!     SPECIFIED IN
18266!           INDROW(K),INDCOL(K), K = 1,...,NNZ.
18267!     ON OUTPUT THE ELEMENTS ARE PERMUTED SO THAT INDCOL IS IN
18268!     NON-DECREASING ORDER. IN ADDITION, THE ARRAY JPNTR IS SET SO THAT
18269!     THE ROW INDICES FOR COLUMN J ARE
18270!           INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
18271!     NOTE THAT THE VALUE OF M IS NOT NEEDED BY SRTDAT AND IS THEREFORE
18272!     NOT PRESENT IN THE SUBROUTINE STATEMENT.
18273!     THE SUBROUTINE STATEMENT IS
18274!       SUBROUTINE SRTDAT(N,NNZ,INDROW,INDCOL,JPNTR,IWA)
18275!     WHERE
18276!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18277!         OF COLUMNS OF A.
18278!       NNZ IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18279!         OF NON-ZERO ELEMENTS OF A.
18280!       INDROW IS AN INTEGER ARRAY OF LENGTH NNZ. ON INPUT INDROW
18281!         MUST CONTAIN THE ROW INDICES OF THE NON-ZERO ELEMENTS OF A.
18282!         ON OUTPUT INDROW IS PERMUTED SO THAT THE CORRESPONDING
18283!         COLUMN INDICES OF INDCOL ARE IN NON-DECREASING ORDER.
18284!       INDCOL IS AN INTEGER ARRAY OF LENGTH NNZ. ON INPUT INDCOL
18285!         MUST CONTAIN THE COLUMN INDICES OF THE NON-ZERO ELEMENTS
18286!         OF A. ON OUTPUT INDCOL IS PERMUTED SO THAT THESE INDICES
18287!         ARE IN NON-DECREASING ORDER.
18288!       JPNTR IS AN INTEGER OUTPUT ARRAY OF LENGTH N + 1 WHICH
18289!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN THE OUTPUT
18290!         INDROW. THE ROW INDICES FOR COLUMN J ARE
18291!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
18292!         NOTE THAT JPNTR(1) IS SET TO 1 AND THAT JPNTR(N+1)-1
18293!         IS THEN NNZ.
18294!       IWA IS AN INTEGER WORK ARRAY OF LENGTH N.
18295!     SUBPROGRAMS CALLED - NONE
18296!     INTRINSIC - MAX
18297!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
18298!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
18299
18300     IMPLICIT NONE
18301
18302! .. Scalar Arguments ..
18303      INTEGER :: N, NNZ
18304! ..
18305! .. Array Arguments ..
18306      INTEGER :: INDCOL(NNZ), INDROW(NNZ), IWA(N), JPNTR(N+1)
18307! ..
18308! .. Local Scalars ..
18309      INTEGER :: I, J, K, L
18310! ..
18311! .. Intrinsic Functions ..
18312      INTRINSIC MAX
18313! ..
18314! ..  FIRST EXECUTABLE STATEMENT SRTDAT
18315! ..
18316!     STORE IN ARRAY IWA THE COUNTS OF NON-ZEROES IN THE COLUMNS.
18317      IWA(1:N) = 0
18318      DO K = 1, NNZ
18319        IWA(INDCOL(K)) = IWA(INDCOL(K)) + 1
18320      END DO
18321
18322!     SET POINTERS TO THE START OF THE COLUMNS IN INDROW.
18323      JPNTR(1) = 1
18324      DO J = 1, N
18325        JPNTR(J+1) = JPNTR(J) + IWA(J)
18326        IWA(J) = JPNTR(J)
18327      END DO
18328      K = 1
18329
18330!     BEGIN IN-PLACE SORT.
1833140    CONTINUE
18332      J = INDCOL(K)
18333      IF (K >= JPNTR(J)) THEN
18334!        CURRENT ELEMENT IS IN POSITION. NOW EXAMINE THE
18335!        NEXT ELEMENT OR THE FIRST UN-SORTED ELEMENT IN
18336!        THE J-TH GROUP.
18337        K = MAX(K+1,IWA(J))
18338      ELSE
18339!       CURRENT ELEMENT IS NOT IN POSITION. PLACE ELEMENT
18340!       IN POSITION AND MAKE THE DISPLACED ELEMENT THE
18341!       CURRENT ELEMENT.
18342        L = IWA(J)
18343        IWA(J) = IWA(J) + 1
18344        I = INDROW(K)
18345        INDROW(K) = INDROW(L)
18346        INDCOL(K) = INDCOL(L)
18347        INDROW(L) = I
18348        INDCOL(L) = J
18349      END IF
18350      IF (K <= NNZ) GOTO 40
18351      RETURN
18352
18353    END SUBROUTINE SRTDAT
18354!_______________________________________________________________________
18355
18356    SUBROUTINE FDJS(M,N,COL,IND,NPNTR,NGRP,NUMGRP,D,FJACD,FJAC)
18357
18358!     GIVEN A CONSISTENT PARTITION OF THE COLUMNS OF AN M BY N
18359!     JACOBIAN MATRIX INTO GROUPS, THIS SUBROUTINE COMPUTES
18360!     APPROXIMATIONS TO THOSE COLUMNS IN A GIVEN GROUP. THE
18361!     APPROXIMATIONS ARE STORED INTO EITHER A COLUMN-ORIENTED
18362!     OR A ROW-ORIENTED PATTERN.
18363!     A PARTITION IS CONSISTENT IF THE COLUMNS IN ANY GROUP
18364!     DO NOT HAVE A NON-ZERO IN THE SAME ROW POSITION.
18365!     APPROXIMATIONS TO THE COLUMNS OF THE JACOBIAN MATRIX IN A
18366!     GIVEN GROUP CAN BE OBTAINED BY SPECIFYING A DIFFERENCE
18367!     PARAMETER ARRAY D WITH D(JCOL) NON-ZERO IF AND ONLY IF
18368!     JCOL IS A COLUMN IN THE GROUP, AND AN APPROXIMATION TO
18369!     JAC*D WHERE JAC DENOTES THE JACOBIAN MATRIX OF A MAPPING F.
18370!     D CAN BE DEFINED WITH THE FOLLOWING SEGMENT OF CODE.
18371!           DO 10 JCOL = 1, N
18372!             D(JCOL) = 0.0
18373!             IF (NGRP(JCOL) == NUMGRP) D(JCOL) = ETA(JCOL)
18374!        10 CONTINUE
18375!     IN THE ABOVE CODE NUMGRP IS THE GIVEN GROUP NUMBER,
18376!     NGRP(JCOL) IS THE GROUP NUMBER OF COLUMN JCOL, AND
18377!     ETA(JCOL) IS THE DIFFERENCE PARAMETER USED TO
18378!     APPROXIMATE COLUMN JCOL OF THE JACOBIAN MATRIX.
18379!     SUITABLE VALUES FOR THE ARRAY ETA MUST BE PROVIDED.
18380!     AS MENTIONED ABOVE, AN APPROXIMATION TO JAC*D MUST
18381!     ALSO BE PROVIDED. FOR EXAMPLE, THE APPROXIMATION
18382!           F(X+D) - F(X)
18383!     CORRESPONDS TO THE FORWARD DIFFERENCE FORMULA AT X.
18384!     THE SUBROUTINE STATEMENT IS
18385!       SUBROUTINE FDJS(M,N,COL,IND,NPNTR,NGRP,NUMGRP,D,FJACD,FJAC)
18386!     WHERE
18387!       M IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18388!         OF ROWS OF THE JACOBIAN MATRIX.
18389!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18390!         OF COLUMNS OF THE JACOBIAN MATRIX.
18391!       COL IS A LOGICAL INPUT VARIABLE. IF COL IS SET TRUE, THEN THE
18392!         JACOBIAN APPROXIMATIONS ARE STORED INTO A COLUMN-ORIENTED
18393!         PATTERN. IF COL IS SET FALSE, THEN THE JACOBIAN
18394!         APPROXIMATIONS ARE STORED INTO A ROW-ORIENTED PATTERN.
18395!       IND IS AN INTEGER INPUT ARRAY WHICH CONTAINS THE ROW
18396!         INDICES FOR THE NON-ZEROES IN THE JACOBIAN MATRIX
18397!         IF COL IS TRUE, AND CONTAINS THE COLUMN INDICES FOR
18398!         THE NON-ZEROES IN THE JACOBIAN MATRIX IF COL IS FALSE.
18399!       NPNTR IS AN INTEGER INPUT ARRAY WHICH SPECIFIES THE
18400!         LOCATIONS OF THE ROW INDICES IN IND IF COL IS TRUE, AND
18401!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN IND IF
18402!         COL IS FALSE. IF COL IS TRUE, THE INDICES FOR COLUMN J ARE
18403!               IND(K), K = NPNTR(J),...,NPNTR(J+1)-1.
18404!         IF COL IS FALSE, THE INDICES FOR ROW I ARE
18405!               IND(K), K = NPNTR(I),...,NPNTR(I+1)-1.
18406!         NOTE THAT NPNTR(N+1)-1 IF COL IS TRUE, OR NPNTR(M+1)-1
18407!         IF COL IS FALSE, IS THEN THE NUMBER OF NON-ZERO ELEMENTS
18408!         OF THE JACOBIAN MATRIX.
18409!       NGRP IS AN INTEGER INPUT ARRAY OF LENGTH N WHICH SPECIFIES
18410!         THE PARTITION OF THE COLUMNS OF THE JACOBIAN MATRIX.
18411!         COLUMN JCOL BELONGS TO GROUP NGRP(JCOL).
18412!       NUMGRP IS A POSITIVE INTEGER INPUT VARIABLE SET TO A GROUP
18413!         NUMBER IN THE PARTITION. THE COLUMNS OF THE JACOBIAN
18414!         MATRIX IN THIS GROUP ARE TO BE ESTIMATED ON THIS CALL.
18415!       D IS AN INPUT ARRAY OF LENGTH N WHICH CONTAINS THE
18416!         DIFFERENCE PARAMETER VECTOR FOR THE ESTIMATE OF
18417!         THE JACOBIAN MATRIX COLUMNS IN GROUP NUMGRP.
18418!       FJACD IS AN INPUT ARRAY OF LENGTH M WHICH CONTAINS
18419!         AN APPROXIMATION TO THE DIFFERENCE VECTOR JAC*D,
18420!         WHERE JAC DENOTES THE JACOBIAN MATRIX.
18421!       FJAC IS AN OUTPUT ARRAY OF LENGTH NNZ, WHERE NNZ IS THE
18422!         NUMBER OF ITS NON-ZERO ELEMENTS. AT EACH CALL OF FDJS,
18423!         FJAC IS UPDATED TO INCLUDE THE NON-ZERO ELEMENTS OF THE
18424!         JACOBIAN MATRIX FOR THOSE COLUMNS IN GROUP NUMGRP. FJAC
18425!         SHOULD NOT BE ALTERED BETWEEN SUCCESSIVE CALLS TO FDJS.
18426!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
18427!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
18428
18429     IMPLICIT NONE
18430
18431! .. Parameters ..
18432      INTEGER, PARAMETER :: WP = KIND(0.0D0)
18433! ..
18434! .. Scalar Arguments ..
18435      INTEGER :: M, N, NUMGRP
18436      LOGICAL :: COL
18437! ..
18438! .. Array Arguments ..
18439      KPP_REAL :: D(N), FJAC(*), FJACD(M)
18440      INTEGER :: IND(*), NGRP(N), NPNTR(*)
18441! ..
18442! .. Local Scalars ..
18443      INTEGER :: IP, IROW, JCOL, JP
18444! ..
18445! .. Intrinsic Functions ..
18446!     INTRINSIC KIND
18447! ..
18448! ..  FIRST EXECUTABLE STATEMENT FDJS
18449! ..
18450!     COMPUTE ESTIMATES OF JACOBIAN MATRIX COLUMNS IN GROUP
18451!     NUMGRP. THE ARRAY FJACD MUST CONTAIN AN APPROXIMATION
18452!     TO JAC*D, WHERE JAC DENOTES THE JACOBIAN MATRIX AND D
18453!     IS A DIFFERENCE PARAMETER VECTOR WITH D(JCOL) NON-ZERO
18454!     IF AND ONLY IF JCOL IS A COLUMN IN GROUP NUMGRP.
18455      IF (COL) THEN
18456!       COLUMN ORIENTATION.
18457        DO JCOL = 1, N
18458          IF (NGRP(JCOL) == NUMGRP) THEN
18459            DO JP = NPNTR(JCOL), NPNTR(JCOL+1) - 1
18460              IROW = IND(JP)
18461              FJAC(JP) = FJACD(IROW)/D(JCOL)
18462            END DO
18463          END IF
18464        END DO
18465      ELSE
18466!       ROW ORIENTATION.
18467        DO IROW = 1, M
18468          DO IP = NPNTR(IROW), NPNTR(IROW+1) - 1
18469            JCOL = IND(IP)
18470            IF (NGRP(JCOL) == NUMGRP) THEN
18471              FJAC(IP) = FJACD(IROW)/D(JCOL)
18472              GOTO 40
18473            END IF
18474          END DO
1847540        CONTINUE
18476        END DO
18477      END IF
18478      RETURN
18479
18480    END SUBROUTINE FDJS
18481!_______________________________________________________________________
18482
18483    SUBROUTINE DVDSM(M,N,NPAIRS,INDROW,INDCOL,NGRP,MAXGRP,MINGRP,INFO, &
18484        IPNTR, JPNTR,IWA,LIWA)
18485
18486!     THE PURPOSE OF DSM IS TO DETERMINE AN OPTIMAL OR NEAR-
18487!     OPTIMAL CONSISTENT PARTITION OF THE COLUMNS OF A SPARSE
18488!     M BY N MATRIX A.
18489!     THE SPARSITY PATTERN OF THE MATRIX A IS SPECIFIED BY
18490!     THE ARRAYS INDROW AND INDCOL. ON INPUT THE INDICES
18491!     FOR THE NON-ZERO ELEMENTS OF A ARE
18492!           INDROW(K),INDCOL(K), K = 1,2,...,NPAIRS.
18493!     THE(INDROW,INDCOL) PAIRS MAY BE SPECIFIED IN ANY ORDER.
18494!     DUPLICATE INPUT PAIRS ARE PERMITTED, BUT THE SUBROUTINE
18495!     ELIMINATES THEM.
18496!     THE SUBROUTINE PARTITIONS THE COLUMNS OF A INTO GROUPS
18497!     SUCH THAT COLUMNS IN THE SAME GROUP DO NOT HAVE A
18498!     NON-ZERO IN THE SAME ROW POSITION. A PARTITION OF THE
18499!     COLUMNS OF A WITH THIS PROPERTY IS CONSISTENT WITH THE
18500!     DIRECT DETERMINATION OF A.
18501!     THE SUBROUTINE STATEMENT IS
18502!       SUBROUTINE DVDSM(M,N,NPAIRS,INDROW,INDCOL,NGRP,MAXGRP,MINGRP,
18503!                      INFO,IPNTR,JPNTR,IWA,LIWA)
18504!     WHERE
18505!       M IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18506!         OF ROWS OF A.
18507!       N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER
18508!         OF COLUMNS OF A.
18509!       NPAIRS IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE
18510!         NUMBER OF (INDROW,INDCOL) PAIRS USED TO DESCRIBE THE
18511!         SPARSITY PATTERN OF A.
18512!       INDROW IS AN INTEGER ARRAY OF LENGTH NPAIRS. ON INPUT INDROW
18513!         MUST CONTAIN THE ROW INDICES OF THE NON-ZERO ELEMENTS OF A.
18514!         ON OUTPUT INDROW IS PERMUTED SO THAT THE CORRESPONDING
18515!         COLUMN INDICES ARE IN NON-DECREASING ORDER. THE COLUMN
18516!         INDICES CAN BE RECOVERED FROM THE ARRAY JPNTR.
18517!       INDCOL IS AN INTEGER ARRAY OF LENGTH NPAIRS. ON INPUT INDCOL
18518!         MUST CONTAIN THE COLUMN INDICES OF THE NON-ZERO ELEMENTS OF
18519!         A. ON OUTPUT INDCOL IS PERMUTED SO THAT THE CORRESPONDING
18520!         ROW INDICES ARE IN NON-DECREASING ORDER. THE ROW INDICES
18521!         CAN BE RECOVERED FROM THE ARRAY IPNTR.
18522!       NGRP IS AN INTEGER OUTPUT ARRAY OF LENGTH N WHICH SPECIFIES
18523!         THE PARTITION OF THE COLUMNS OF A. COLUMN JCOL BELONGS
18524!         TO GROUP NGRP(JCOL).
18525!       MAXGRP IS AN INTEGER OUTPUT VARIABLE WHICH SPECIFIES THE
18526!         NUMBER OF GROUPS IN THE PARTITION OF THE COLUMNS OF A.
18527!       MINGRP IS AN INTEGER OUTPUT VARIABLE WHICH SPECIFIES A LOWER
18528!         BOUND FOR THE NUMBER OF GROUPS IN ANY CONSISTENT PARTITION
18529!         OF THE COLUMNS OF A.
18530!       INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS. FOR
18531!         NORMAL TERMINATION INFO = 1. IF M, N, OR NPAIRS IS NOT
18532!         POSITIVE OR LIWA IS LESS THAN MAX(M,6*N), THEN INFO = 0.
18533!         IF THE K-TH ELEMENT OF INDROW IS NOT AN INTEGER BETWEEN
18534!         1 AND M OR THE K-TH ELEMENT OF INDCOL IS NOT AN INTEGER
18535!         BETWEEN 1 AND N, THEN INFO = -K.
18536!       IPNTR IS AN INTEGER OUTPUT ARRAY OF LENGTH M + 1 WHICH
18537!         SPECIFIES THE LOCATIONS OF THE COLUMN INDICES IN INDCOL.
18538!         THE COLUMN INDICES FOR ROW I ARE
18539!               INDCOL(K), K = IPNTR(I),...,IPNTR(I+1)-1.
18540!         NOTE THAT IPNTR(M+1)-1 IS THEN THE NUMBER OF NON-ZERO
18541!         ELEMENTS OF THE MATRIX A.
18542!       JPNTR IS AN INTEGER OUTPUT ARRAY OF LENGTH N + 1 WHICH
18543!         SPECIFIES THE LOCATIONS OF THE ROW INDICES IN INDROW.
18544!         THE ROW INDICES FOR COLUMN J ARE
18545!               INDROW(K), K = JPNTR(J),...,JPNTR(J+1)-1.
18546!         NOTE THAT JPNTR(N+1)-1 IS THEN THE NUMBER OF NON-ZERO
18547!         ELEMENTS OF THE MATRIX A.
18548!       IWA IS AN INTEGER WORK ARRAY OF LENGTH LIWA.
18549!       LIWA IS A POSITIVE INTEGER INPUT VARIABLE NOT LESS THAN
18550!         MAX(M,6*N).
18551!       MINPACK-SUPPLIED ... DEGR,IDO,NUMSRT,SEQ,SETR,SLO,SRTDAT
18552!       INTRINSIC - MAX
18553!     ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JULY 1983.
18554!     THOMAS F. COLEMAN, BURTON S. GARBOW, JORGE J. MORE'
18555
18556     IMPLICIT NONE
18557
18558! .. Scalar Arguments ..
18559      INTEGER :: INFO, LIWA, M, MAXGRP, MINGRP, N, NPAIRS
18560! ..
18561! .. Array Arguments ..
18562      INTEGER :: INDCOL(NPAIRS), INDROW(NPAIRS), IPNTR(M+1), IWA(LIWA), &
18563        JPNTR(N+1), NGRP(N)
18564! ..
18565! .. Local Scalars ..
18566      INTEGER :: I, IR, J, JP, K, MAXCLQ, NNZ, NUMGRP
18567! ..
18568! .. External Subroutines ..
18569!     EXTERNAL DEGR, IDO, NUMSRT, SEQ, SETR, SLO, SRTDAT
18570! ..
18571! .. Intrinsic Functions ..
18572      INTRINSIC MAX
18573! ..
18574! ..  FIRST EXECUTABLE STATEMENT DSM
18575! ..
18576!     CHECK THE INPUT DATA.
18577      INFO = 0
18578      IF (M<1 .OR. N<1 .OR. NPAIRS<1 .OR. LIWA<MAX(M,6*N)) RETURN
18579      DO K = 1, NPAIRS
18580        INFO = -K
18581        IF (INDROW(K)<1 .OR. INDROW(K)>M .OR. INDCOL(K)<1 .OR. INDCOL(K)>N) &
18582          RETURN
18583      END DO
18584      INFO = 1
18585
18586!     SORT THE DATA STRUCTURE BY COLUMNS.
18587      CALL SRTDAT(N,NPAIRS,INDROW,INDCOL,JPNTR,IWA)
18588
18589!     COMPRESS THE DATA AND DETERMINE THE NUMBER OF
18590!     NON-ZERO ELEMENTS OF A.
18591      IWA(1:M) =  0
18592      NNZ = 1
18593      DO J = 1, N
18594        K = NNZ
18595        DO JP = JPNTR(J), JPNTR(J+1) - 1
18596          IR = INDROW(JP)
18597          IF (IWA(IR)/=J) THEN
18598            INDROW(NNZ) = IR
18599            NNZ = NNZ + 1
18600            IWA(IR) = J
18601          END IF
18602        END DO
18603        JPNTR(J) = K
18604      END DO
18605      JPNTR(N+1) = NNZ
18606
18607!     EXTEND THE DATA STRUCTURE TO ROWS.
18608      CALL SETR(M,N,INDROW,JPNTR,INDCOL,IPNTR,IWA)
18609
18610!     DETERMINE A LOWER BOUND FOR THE NUMBER OF GROUPS.
18611      MINGRP = 0
18612      DO I = 1, M
18613        MINGRP = MAX(MINGRP,IPNTR(I+1)-IPNTR(I))
18614      END DO
18615
18616!     DETERMINE THE DEGREE SEQUENCE FOR THE INTERSECTION
18617!     GRAPH OF THE COLUMNS OF A.
18618      CALL DEGR(N,INDROW,JPNTR,INDCOL,IPNTR,IWA(5*N+1),IWA(N+1))
18619
18620!     COLOR THE INTERSECTION GRAPH OF THE COLUMNS OF A
18621!     WITH THE SMALLEST-LAST (SL) ORDERING.
18622      CALL SLO(N,INDROW,JPNTR,INDCOL,IPNTR,IWA(5*N+1),IWA(4*N+1),MAXCLQ, &
18623        IWA(1),IWA(N+1),IWA(2*N+1),IWA(3*N+1))
18624      CALL SEQ(N,INDROW,JPNTR,INDCOL,IPNTR,IWA(4*N+1),NGRP,MAXGRP,IWA(N+1))
18625      MINGRP = MAX(MINGRP,MAXCLQ)
18626
18627!     EXIT IF THE SMALLEST-LAST ORDERING IS OPTIMAL.
18628
18629      IF (MAXGRP == MINGRP) RETURN
18630
18631!     COLOR THE INTERSECTION GRAPH OF THE COLUMNS OF A
18632!     WITH THE INCIDENCE-DEGREE(ID) ORDERING.
18633      CALL IDO(M,N,INDROW,JPNTR,INDCOL,IPNTR,IWA(5*N+1),IWA(4*N+1),MAXCLQ, &
18634        IWA(1),IWA(N+1),IWA(2*N+1),IWA(3*N+1))
18635      CALL SEQ(N,INDROW,JPNTR,INDCOL,IPNTR,IWA(4*N+1),IWA(1),NUMGRP,IWA(N+1))
18636      MINGRP = MAX(MINGRP,MAXCLQ)
18637
18638!     RETAIN THE BETTER OF THE TWO ORDERINGS SO FAR.
18639      IF (NUMGRP < MAXGRP) THEN
18640        MAXGRP = NUMGRP
18641        NGRP(1:N) = IWA(1:N)
18642
18643!       EXIT IF THE INCIDENCE-DEGREE ORDERING IS OPTIMAL.
18644        IF (MAXGRP == MINGRP) RETURN
18645      END IF
18646
18647!     COLOR THE INTERSECTION GRAPH OF THE COLUMNS OF A
18648!     WITH THE LARGEST-FIRST (LF) ORDERING.
18649      CALL NUMSRT(N,N-1,IWA(5*N+1),-1,IWA(4*N+1),IWA(2*N+1),IWA(N+1))
18650      CALL SEQ(N,INDROW,JPNTR,INDCOL,IPNTR,IWA(4*N+1),IWA(1),NUMGRP,IWA(N+1))
18651
18652!     RETAIN THE BEST OF THE THREE ORDERINGS AND EXIT.
18653      IF (NUMGRP < MAXGRP) THEN
18654        MAXGRP = NUMGRP
18655        NGRP(1:N) = IWA(1:N)
18656      END IF
18657      RETURN
18658
18659    END SUBROUTINE DVDSM
18660!_______________________________________________________________________
18661
18662      SUBROUTINE DGROUPDS(N,MAXGRPDS,NGRPDS,IGP,JGP)
18663! ..
18664! Construct the column grouping arrays IGP anf JGP needed by DVJACS28
18665! from the DSM array NGRPDS.
18666! ..
18667!     Input:
18668!
18669!     N        = the order of the matrix
18670!     MAXGRPDS = number of groups (from DSM)
18671!     NGRPDS   = DSM output array
18672!     Output:
18673!     JGP      = array of length N containing the column
18674!                indices by groups
18675!     IGP      = pointer array of length NGRP + 1 to the
18676!                locations in JGP of the beginning of
18677!                each group
18678! ..
18679     IMPLICIT NONE
18680! ..
18681! .. Scalar Arguments ..
18682        INTEGER, INTENT (IN) :: N, MAXGRPDS
18683! ..
18684! .. Array Arguments ..
18685        INTEGER, INTENT (IN) :: NGRPDS(MAXGRPDS)
18686        INTEGER, INTENT (OUT) :: IGP(MAXGRPDS+1), JGP(N)
18687! ..
18688! .. Local Scalars ..
18689        INTEGER :: IGRP, INDEX, JCOL
18690! ..
18691! .. FIRST EXECUTABLE STATEMENT DGROUPDS
18692! ..
18693        IGP(1) = 1
18694        INDEX =  0
18695        DO IGRP = 1, MAXGRPDS
18696           IGP(IGRP+1) = IGP(IGRP)
18697           DO JCOL = 1, N
18698              IF (NGRPDS(JCOL) == IGRP) THEN
18699                 IGP(IGRP+1) = IGP(IGRP+1) + 1
18700                 INDEX = INDEX + 1
18701                 JGP(INDEX) = JCOL
18702              END IF
18703           END DO
18704        END DO
18705        RETURN
18706
18707      END SUBROUTINE DGROUPDS
18708!_______________________________________________________________________
18709
18710    SUBROUTINE JACSPDB(FCN,N,T,Y,F,FJAC,NRFJAC,YSCALE,FAC,IOPT, &
18711      WK,LWK,IWK,LIWK,MAXGRP,NGRP,JPNTR,INDROW)
18712
18713! This is a modified version of JACSP which does not require the NGRP,
18714! JPNTR and INDROW sparse pointer arrays in the event a dense or a
18715! banded matrix is being processed.
18716
18717! Refer to the documentation for JACSP for a description of the
18718! parameters. If the banded option is used, IOPT(5) is used to
18719! input the lower bandwidth ML in this version.
18720
18721     IMPLICIT NONE
18722
18723! .. Parameters ..
18724      INTEGER, PARAMETER :: WP = KIND(0.0D0)
18725! ..
18726! .. Scalar Arguments ..
18727      KPP_REAL :: T
18728      INTEGER :: LIWK, LWK, MAXGRP, N, NRFJAC
18729! ..
18730! .. Array Arguments ..
18731      KPP_REAL :: F(N), FAC(N), FJAC(NRFJAC,*), WK(LWK), Y(N), YSCALE(*)
18732      INTEGER :: INDROW(*), IOPT(5), IWK(LIWK), JPNTR(*), NGRP(N)
18733! ..
18734! .. Subroutine Arguments ..
18735      EXTERNAL FCN
18736! ..
18737! .. Local Scalars ..
18738      KPP_REAL :: ADIFF, AY, DEL, DELM, DFMJ, DIFF, DMAX, EXPFMN, FACMAX, &
18739        FACMIN, FJACL, FMJ, ONE, P125, P25, P75, P875, PERT, RDEL, RMNFDF, &
18740        RMXFDF, SDF, SF, SGN, T1, T2, U, U3QRT, U7EGT, UEGT, UMEGT, UQRT,  &
18741        USQT, ZERO
18742      INTEGER :: IDXL, IDXU, IFLAG1, IFLAG2, IRCMP, IRDEL, IROW, IROWB,    &
18743        IROWMX, ITRY, J, JCOL, JFIRST, JINC, JLAST, KT1, KT2, KT3, KT4,    &
18744        KT5, L, MBAND, ML, MU, NID1, NID2, NID3, NID4, NID5, NID6,         &
18745        NIFAC, NT2, NUMGRP
18746!       KT5, L, MBAND, MEB1, ML, MU, NID1, NID2, NID3, NID4, NID5, NID6,   &
18747      LOGICAL :: DOTHISBLOCK
18748      CHARACTER (80) :: MSG
18749! ..
18750! .. Intrinsic Functions ..
18751!     INTRINSIC ABS, EPSILON, KIND, MAX, MIN, SIGN, SQRT
18752      INTRINSIC ABS, EPSILON, MAX, MIN, SIGN, SQRT
18753! ..
18754! .. Data Statements ..
18755      DATA PERT/2.0E+0_dp/, FACMAX/1.E-1_dp/, EXPFMN/.75E+0_dp/
18756      DATA ONE/1.0E0_dp/, ZERO/0.0E0_dp/
18757      DATA P125/.125E+0_dp/, P25/.25E+0_dp/, P75/.75E+0_dp/, P875/.875E+0_dp/
18758      DATA NIFAC/3/, NID1/10/, NID2/20/, NID3/30/, NID4/40/, NID5/50/
18759! ..
18760!     COMPUTE ALGORITHM AND MACHINE CONSTANTS.
18761! ..
18762! ..  FIRST EXECUTABLE STATEMENT JACSPDB
18763! ..
18764      IF (IOPT(1) == 0 .AND. MAXGRP /= N) THEN
18765         MSG = 'JACSPDB requires that MAXGRP=N for a dense matrix.'
18766         CALL XERRDV(MSG,1800,2,0,0,0,0,ZERO,ZERO)
18767      END IF
18768
18769      IF (IOPT(1) == 1) THEN
18770         MBAND = IOPT(2)
18771         ML = IOPT(5)
18772         MU = MBAND - ML - 1
18773!        MEB1 = 2*ML + MU
18774      END IF
18775
18776      U = EPSILON(ONE)
18777      USQT = SQRT(U)
18778      UEGT = U**P125
18779      UMEGT = ONE/UEGT
18780      UQRT = U**P25
18781      U3QRT = U**P75
18782      U7EGT = U**P875
18783      FACMIN = U**EXPFMN
18784
18785      IF (IOPT(4) == 0) THEN
18786        IOPT(4) = 1
18787        DO 10 J = 1, N
18788          FAC(J) = USQT
1878910      CONTINUE
18790      END IF
18791      DO 20 J = 1, 50
18792        IWK(J) = 0
1879320    CONTINUE
18794      KT1 = NID1
18795      KT2 = NID2
18796      KT3 = NID3
18797      KT4 = NID4
18798      KT5 = NID5
18799      NID6 = LIWK
18800      NT2 = 2*N
18801
18802      DO NUMGRP = 1, MAXGRP
18803!       COMPUTE AND SAVE THE INCREMENTS FOR THE COLUMNS IN GROUP NUMGRP.
18804        IRCMP = 0
18805        ITRY = 0
18806        DO 30 J = NID5 + 1, NID6
18807          IWK(J) = 0
1880830      CONTINUE
1880940      CONTINUE
18810
18811!       Note: For banded in DVJAC:
18812!       mba = min(mband,n)
18813!          Groups: j=1,...,mba
18814!             Columns in group j: jj=j,...,n by mband
18815!                Rows in column jj: i1=max(jj-mu,1),...,i2=min(jj+ml,n)       
18816
18817        IF (IOPT(1) == 0 .OR. IOPT(1) == 2) THEN
18818          JFIRST = 1
18819          JLAST = N
18820          JINC = 1
18821        ELSE
18822          JFIRST = NUMGRP
18823          JLAST = N
18824          JINC = MBAND
18825        END IF
18826        DO JCOL = JFIRST, JLAST, JINC
18827          DOTHISBLOCK = .FALSE.
18828          IF (IOPT(1) == 2) THEN
18829            IF (NGRP(JCOL) == NUMGRP) DOTHISBLOCK = .TRUE.
18830          ELSE
18831            IF (IOPT(1) == 0) THEN
18832              IF (JCOL == NUMGRP) DOTHISBLOCK = .TRUE.
18833            ELSE
18834              IF (IOPT(1) == 1) THEN
18835                DOTHISBLOCK = .TRUE.
18836              END IF
18837            END IF
18838          END IF
18839
18840          IF (DOTHISBLOCK) THEN
18841            WK(N+JCOL) = Y(JCOL)
18842!           COMPUTE DEL. IF DEL IS TOO SMALL INCREASE FAC(JCOL) AND RECOMPUTE
18843!           DEL. NIFAC ATTEMPTS ARE MADE TO INCREASE FAC(JCOL) AND FIND AN
18844!           APPROPRIATE DEL. IF DEL CANT BE FOUND IN THIS MANNER, DEL IS COMPUTED
18845!           WITH FAC(JCOL) SET TO THE SQUARE ROOT OF THE MACHINE PRECISION (USQT).
18846!           IF DEL IS ZERO TO MACHINE PRECISION BECAUSE Y(JCOL) IS ZERO OR
18847!           YSCALE(JCOL) IS ZERO, DEL IS SET TO USQT.
18848            SGN = SIGN(ONE,F(JCOL))
18849            IRDEL = 0
18850            IF (IOPT(3) == 1) THEN
18851              AY = ABS(YSCALE(JCOL))
18852            ELSE
18853              AY = ABS(Y(JCOL))
18854            END IF
18855            DELM = U7EGT*AY
18856
18857            DO 50 J = 1, NIFAC
18858              DEL = FAC(JCOL)*AY*SGN
18859              IF (ABS(DEL) <= ZERO) THEN
18860                DEL = USQT*SGN
18861                IF (ITRY == 0) IWK(3) = IWK(3) + 1
18862              END IF
18863              T1 = Y(JCOL) + DEL
18864              DEL = T1 - Y(JCOL)
18865              IF (ABS(DEL) < DELM) THEN
18866                IF (J >= NIFAC) GOTO 50
18867                IF (IRDEL == 0) THEN
18868                  IRDEL = 1
18869                  IWK(1) = IWK(1) + 1
18870                END IF
18871                T1 = FAC(JCOL)*UMEGT
18872                FAC(JCOL) = MIN(T1,FACMAX)
18873              ELSE
18874                GOTO 60
18875              END IF
1887650          END DO
18877
18878            FAC(JCOL) = USQT
18879            DEL = USQT*AY*SGN
18880            IWK(2) = IWK(2) + 1
18881            IF (KT2 < NID3) THEN
18882              KT2 = KT2 + 1
18883              IWK(KT2) = JCOL
18884            END IF
18885
1888660          CONTINUE
18887            WK(NT2+JCOL) = DEL
18888            Y(JCOL) = Y(JCOL) + DEL
18889          END IF
18890        END DO
18891
18892        IWK(7) = IWK(7) + 1
18893        CALL FCN(N,T,Y,WK)
18894
18895        DO JCOL = JFIRST, JLAST, JINC
18896          IF (IOPT(1) == 2) THEN
18897             IF (NGRP(JCOL) == NUMGRP) Y(JCOL) = WK(N+JCOL)
18898          ELSE
18899             IF (IOPT(1) == 0) THEN
18900                IF (JCOL == NUMGRP) Y(JCOL) = WK(N+JCOL)
18901             ELSE
18902                IF (IOPT(1) == 1) Y(JCOL) = WK(N+JCOL)
18903             END IF
18904          END IF
18905        END DO
18906
18907!       COMPUTE THE JACOBIAN ENTRIES FOR ALL COLUMNS IN NUMGRP.
18908!       STORE ENTRIES ACCORDING TO SELECTED STORAGE FORMAT.
18909!       USE LARGEST ELEMENTS IN A COLUMN TO DETERMINE SCALING
18910!       INFORMATION FOR ROUNDOFF AND TRUNCATION ERROR TESTS.
18911
18912        DO JCOL = JFIRST, JLAST, JINC
18913          DOTHISBLOCK = .FALSE.
18914          IF (IOPT(1) == 2) THEN
18915             IF (NGRP(JCOL) == NUMGRP) DOTHISBLOCK = .TRUE.
18916          ELSE
18917             IF (IOPT(1) == 0) THEN
18918                IF (JCOL == NUMGRP) DOTHISBLOCK = .TRUE.
18919             ELSE
18920                IF(IOPT(1) == 1) DOTHISBLOCK = .TRUE.
18921             END IF
18922          END IF
18923          IF (DOTHISBLOCK) THEN
18924            IF (IOPT(1) == 2) THEN
18925              IDXL = JPNTR(JCOL)
18926              IDXU = JPNTR(JCOL+1) - 1
18927            ELSE
18928              IF (IOPT(1) == 0) THEN
18929                IDXL = 1
18930                IDXU = N
18931              ELSE
18932                IF (IOPT(1) == 1) THEN
18933                  IDXL = MAX(JCOL-MU,1)
18934                  IDXU = MIN(JCOL+ML,N)
18935                END IF
18936              END IF
18937            END IF
18938            DMAX = ZERO
18939            RDEL = ONE/WK(NT2+JCOL)
18940            IROWMX = 1
18941            DO L = IDXL, IDXU
18942              IF (IOPT(1) == 2) THEN
18943                 IROW = INDROW(L)
18944              ELSE
18945                 IF (IOPT(1)==0 .OR. IOPT(1)==1) IROW = L
18946              END IF
18947              DIFF = WK(IROW) - F(IROW)
18948              ADIFF = ABS(DIFF)
18949              IF (ADIFF >= DMAX) THEN
18950                IROWMX = IROW
18951                DMAX = ADIFF
18952                SF = F(IROW)
18953                SDF = WK(IROW)
18954              END IF
18955              FJACL = DIFF*RDEL
18956              IF (ITRY == 1) WK(IROW) = FJACL
18957
18958              IF (IOPT(1) == 0) THEN
18959                IF (ITRY == 1) WK(IROW+N) = FJAC(IROW,JCOL)
18960                FJAC(IROW,JCOL) = FJACL
18961              END IF
18962              IF (IOPT(1) == 1) THEN
18963                IROWB = IROW - JCOL + IOPT(2)
18964                IF (ITRY == 1) WK(IROW+N) = FJAC(IROWB,JCOL)
18965                FJAC(IROWB,JCOL) = FJACL
18966!               IROWB = JCOL * MEB1 - ML + L
18967!               IF (ITRY == 1) WK(IROW+N) = FJAC(IROWB,1)
18968!               FJAC(IROWB,1) = FJACL
18969              END IF
18970              IF (IOPT(1) == 2) THEN
18971                IF (ITRY == 1) WK(IROW+N) = FJAC(L,1)
18972                FJAC(L,1) = FJACL
18973              END IF
18974            END DO
18975
18976!           IF A COLUMN IS BEING RECOMPUTED (ITRY=1),THIS SECTION OF THE
18977!           CODE PERFORMS AN EXTRAPOLATION TEST TO ENABLE THE CODE TO
18978!           COMPUTE SMALL DERIVATIVES MORE ACCURATELY. THIS TEST IS ONLY
18979!           PERFORMED ON THOSE COLUMNS WHOSE LARGEST DIFFERENCE IS CLOSE
18980!           TO ZERO RELATIVE TO SCALE.
18981            IF (ITRY == 1) THEN
18982              IFLAG1 = 0
18983              IFLAG2 = 0
18984              DO 100 J = NID5 + 1, NID6
18985                IF (IWK(J) == JCOL) IFLAG1 = 1
18986100           CONTINUE
18987              IF (IFLAG1 == 1) THEN
18988                IFLAG1 = 0
18989                T1 = WK(IROWMX+N)
18990                T2 = WK(IROWMX)*FAC(JCOL)
18991                IF (ABS(T2) < ABS(T1)*PERT) IFLAG2 = 1
18992              END IF
18993
18994              IF (IFLAG2 == 1) THEN
18995                IFLAG2 = 0
18996                T1 = FAC(JCOL)*FAC(JCOL)
18997                FAC(JCOL) = MAX(T1,FACMIN)
18998                DO L = IDXL, IDXU
18999                  IF (IOPT(1) == 2) THEN
19000                     IROW = INDROW(L)
19001                  ELSE
19002                     IF (IOPT(1)==0 .OR. IOPT(1)==1) IROW = L
19003                  END IF
19004                  FJACL = WK(IROW+N)
19005                  IF (IOPT(1) == 0) FJAC(IROW,JCOL) = FJACL
19006                  IF (IOPT(1) == 1) THEN
19007                    IROWB = IROW - JCOL + IOPT(2)
19008                    FJAC(IROWB,JCOL) = FJACL
19009!                   IROWB = JCOL * MEB1 - ML + L
19010!                   FJAC(IROWB,1) = FJACL
19011                  END IF
19012                  IF (IOPT(1) == 2) FJAC(L,1) = FJACL
19013              END DO
19014              END IF
19015            END IF
19016
19017            FMJ = ABS(SF)
19018            DFMJ = ABS(SDF)
19019            RMXFDF = MAX(FMJ,DFMJ)
19020            RMNFDF = MIN(FMJ,DFMJ)
19021
19022!           IF SCALE INFORMATION IS NOT AVAILABLE, PERFORM NO ROUNDOFF
19023!           OR TRUNCATION ERROR TESTS. IF THE EXTRAPOLATION TEST HAS
19024!           CAUSED FAC(JCOL) TO BE RESET TO ITS PREVIOUS VALUE (IAJAC=1)
19025!           THEN NO FURTHER ROUNDOFF OR TRUNCATION ERROR TESTS ARE
19026!           PERFORMED.
19027!           IF (RMNFDF/=ZERO) THEN
19028            IF (ABS(RMNFDF) > ZERO) THEN
19029!             TEST FOR POSSIBLE ROUNDOFF ERROR (FIRST TEST)
19030!             AND ALSO FOR POSSIBLE SERIOUS ROUNDOFF ERROR (SECOND TEST).
19031              IF (DMAX <= (U3QRT*RMXFDF)) THEN
19032                IF (DMAX <= (U7EGT*RMXFDF)) THEN
19033                  IF (ITRY == 0) THEN
19034                    T1 = SQRT(FAC(JCOL))
19035                    FAC(JCOL) = MIN(T1,FACMAX)
19036                    IRCMP = 1
19037                    IF (KT5 < NID6) THEN
19038                      KT5 = KT5 + 1
19039                      IWK(KT5) = JCOL
19040                    END IF
19041                    IWK(4) = IWK(4) + 1
19042                    IF (KT3 < NID4) THEN
19043                      KT3 = KT3 + 1
19044                      IWK(KT3) = JCOL
19045                    END IF
19046                  ELSE
19047                    IWK(5) = IWK(5) + 1
19048                    IF (KT4 < NID5) THEN
19049                      KT4 = KT4 + 1
19050                      IWK(KT4) = JCOL
19051                    END IF
19052                  END IF
19053                ELSE
19054                  T1 = UMEGT*FAC(JCOL)
19055                  FAC(JCOL) = MIN(T1,FACMAX)
19056                END IF
19057              END IF
19058!             TEST FOR POSSIBLE TRUNCATION ERROR.
19059              IF (DMAX > UQRT*RMXFDF) THEN
19060                T1 = FAC(JCOL)*UEGT
19061                FAC(JCOL) = MAX(T1,FACMIN)
19062                IWK(8) = IWK(8) + 1
19063                IF (KT1 < NID2) THEN
19064                  KT1 = KT1 + 1
19065                  IWK(KT1) = JCOL
19066                END IF
19067              END IF
19068            ELSE
19069              IWK(6) = IWK(6) + 1
19070            END IF
19071          END IF
19072        END DO
19073
19074!       IF SERIOUS ROUNDOFF ERROR IS SUSPECTED, RECOMPUTE ALL
19075!       COLUMNS IN GROUP NUMGRP.
19076        IF (IRCMP == 1) THEN
19077          IRCMP = 0
19078          ITRY = 1
19079          GOTO 40
19080        END IF
19081        ITRY = 0
19082      END DO
19083      RETURN
19084
19085    END SUBROUTINE JACSPDB
19086
19087! End of JACSP routines.
19088!_______________________________________________________________________
19089! *****MA48 build change point. Insert the MA48 Jacobian related
19090! routines DVNLSS48, DVSOLS48, DVPREPS48, and DVJACS48 here.
19091! filename = jacobian_for_ma48.f90. Insert the following line
19092! after the first line of this file:
19093! USE hsl_ma48_double
19094!_______________________________________________________________________
19095
19096! *****LAPACK build change point. Insert the following line after the
19097! first line of this file:
19098! USE lapackd_f90_m
19099! Include the module lapackd_f90_m.f90 at the beginning of this file
19100! or as an external module.
19101!_______________________________________________________________________
19102
19103    END MODULE DVODE
19104
19105
19106    END MODULE KPP_ROOT_Integrator
19107!_______________________________________________________________________
Note: See TracBrowser for help on using the repository browser.