1 | MODULE 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 | |
---|
31 | CONTAINS |
---|
32 | |
---|
33 | SUBROUTINE 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. |
---|
5709 | 10 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 |
---|
5756 | 20 CONTINUE |
---|
5757 | JP1 = J + 1 |
---|
5758 | IA(JP1) = K |
---|
5759 | Y(J) = YJSAVE |
---|
5760 | END DO |
---|
5761 | GOTO 40 |
---|
5762 | 30 CONTINUE |
---|
5763 | MSG = 'An error occurred in subroutine SET_IAJA.' |
---|
5764 | CALL XERRDV(MSG,890,2,0,0,0,0,ZERO,ZERO) |
---|
5765 | |
---|
5766 | 40 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 |
---|
6139 | 10 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 | |
---|
6154 | 20 IF (NEQ<=0) GOTO 450 |
---|
6155 | IF (ISTATE==1) GOTO 30 |
---|
6156 | IF (NEQ>N) GOTO 460 |
---|
6157 | IF (NEQ/=N) GOTO 465 |
---|
6158 | 30 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 |
---|
6175 | 40 CONTINUE |
---|
6176 | IF (NG<0) GOTO 700 |
---|
6177 | IF (ISTATE==1) GOTO 50 |
---|
6178 | IF (IRFND==0 .AND. NG/=NGC) GOTO 710 |
---|
6179 | 50 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 |
---|
6189 | 60 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 |
---|
6202 | 70 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 | |
---|
6281 | 80 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. |
---|
6339 | 90 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 | |
---|
6351 | 100 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 |
---|
6362 | 110 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. |
---|
6411 | 120 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 | |
---|
6429 | 130 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 |
---|
6439 | 140 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 |
---|
6444 | 150 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 |
---|
6455 | 160 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 |
---|
6459 | 170 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 |
---|
6473 | 180 TCRIT = RWORK(1) |
---|
6474 | IF ((TN-TCRIT)*H>ZERO) GOTO 650 |
---|
6475 | 190 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 | |
---|
6491 | 200 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 |
---|
6498 | 210 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 |
---|
6504 | 220 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) |
---|
6531 | 230 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 | |
---|
6591 | 240 INIT = 1 |
---|
6592 | KUTH = 0 |
---|
6593 | GOTO (250,310,270,280,300) ITASK |
---|
6594 | ! ITASK = 1. If TOUT has been reached, interpolate. |
---|
6595 | 250 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 |
---|
6603 | 260 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. |
---|
6615 | 270 IF ((TN-TOUT)*H>=ZERO) GOTO 310 |
---|
6616 | GOTO 200 |
---|
6617 | ! ITASK = 4. See if TOUT or TCRIT was reached. Adjust H if necessary. |
---|
6618 | 280 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 |
---|
6628 | 290 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. |
---|
6637 | 300 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 | |
---|
6646 | 310 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 |
---|
6651 | 320 ISTATE = 2 |
---|
6652 | 330 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. |
---|
6696 | 340 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). |
---|
6703 | 350 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. |
---|
6709 | 360 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. |
---|
6717 | 370 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. |
---|
6724 | 380 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. |
---|
6732 | 390 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 |
---|
6739 | 400 END DO |
---|
6740 | IWORK(16) = IMXER |
---|
6741 | ! Set Y vector, T, and optional output. |
---|
6742 | 410 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 | |
---|
6769 | 420 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 |
---|
6773 | 430 MSG = 'ITASK(=I1) is illegal.' |
---|
6774 | CALL XERRDV(MSG,1030,1,1,ITASK,0,0,ZERO,ZERO) |
---|
6775 | GOTO 740 |
---|
6776 | 440 MSG = 'ISTATE(=I1) > 1 but DVODE is not initialized.' |
---|
6777 | CALL XERRDV(MSG,1040,1,1,ISTATE,0,0,ZERO,ZERO) |
---|
6778 | GOTO 740 |
---|
6779 | 450 MSG = 'NEQ (=I1) < 1.' |
---|
6780 | CALL XERRDV(MSG,1050,1,1,NEQ,0,0,ZERO,ZERO) |
---|
6781 | GOTO 740 |
---|
6782 | 460 MSG = 'ISTATE = 3 and NEQ increased (I1 to I2).' |
---|
6783 | CALL XERRDV(MSG,1060,1,2,N,NEQ,0,ZERO,ZERO) |
---|
6784 | GOTO 740 |
---|
6785 | 465 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 |
---|
6788 | 470 MSG = 'ITOL(=I1) is illegal.' |
---|
6789 | CALL XERRDV(MSG,1080,1,1,ITOL,0,0,ZERO,ZERO) |
---|
6790 | GOTO 740 |
---|
6791 | 480 MSG = 'IOPT(=I1) is illegal.' |
---|
6792 | CALL XERRDV(MSG,1090,1,1,IOPT,0,0,ZERO,ZERO) |
---|
6793 | GOTO 740 |
---|
6794 | 490 MSG = 'MF(=I1) is illegal.' |
---|
6795 | CALL XERRDV(MSG,1100,1,1,MF,0,0,ZERO,ZERO) |
---|
6796 | GOTO 740 |
---|
6797 | 500 MSG = 'ML(=I1) illegal: < 0 or >= NEQ (=I2)' |
---|
6798 | CALL XERRDV(MSG,1110,1,2,ML,NEQ,0,ZERO,ZERO) |
---|
6799 | GOTO 740 |
---|
6800 | 510 MSG = 'MU(=I1) illegal: < 0 or >= NEQ (=I2)' |
---|
6801 | CALL XERRDV(MSG,1120,1,2,MU,NEQ,0,ZERO,ZERO) |
---|
6802 | GOTO 740 |
---|
6803 | 520 MSG = 'MAXORD(=I1) < 0.' |
---|
6804 | CALL XERRDV(MSG,1130,1,1,MAXORD,0,0,ZERO,ZERO) |
---|
6805 | GOTO 740 |
---|
6806 | 530 MSG = 'MXSTEP(=I1) < 0.' |
---|
6807 | CALL XERRDV(MSG,1140,1,1,MXSTEP,0,0,ZERO,ZERO) |
---|
6808 | GOTO 740 |
---|
6809 | 540 MSG = 'MXHNIL(=I1) < 0.' |
---|
6810 | CALL XERRDV(MSG,1150,1,1,MXHNIL,0,0,ZERO,ZERO) |
---|
6811 | GOTO 740 |
---|
6812 | 550 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 |
---|
6817 | 560 MSG = 'HMAX(=R1) < 0.' |
---|
6818 | CALL XERRDV(MSG,1170,1,0,0,0,1,HMAX,ZERO) |
---|
6819 | GOTO 740 |
---|
6820 | 570 MSG = 'HMIN(=R1) < 0.' |
---|
6821 | CALL XERRDV(MSG,1180,1,0,0,0,1,HMIN,ZERO) |
---|
6822 | GOTO 740 |
---|
6823 | 580 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 |
---|
6827 | 590 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 |
---|
6831 | 600 MSG = 'RTOL(I1) is R1 < 0.' |
---|
6832 | CALL XERRDV(MSG,1210,1,1,I,0,1,RTOLI,ZERO) |
---|
6833 | GOTO 740 |
---|
6834 | 610 MSG = 'ATOL(I1) is R1 < 0.' |
---|
6835 | CALL XERRDV(MSG,1220,1,1,I,0,1,ATOLI,ZERO) |
---|
6836 | GOTO 740 |
---|
6837 | 620 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 |
---|
6841 | 630 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 |
---|
6845 | 640 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 |
---|
6849 | 650 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 |
---|
6853 | 660 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 |
---|
6857 | 670 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 |
---|
6865 | 680 MSG = 'Trouble from DVINDY. ITASK = I1, TOUT = R1.' |
---|
6866 | CALL XERRDV(MSG,1290,1,1,ITASK,0,1,TOUT,ZERO) |
---|
6867 | GOTO 740 |
---|
6868 | 690 MSG = 'SETH must be nonnegative.' |
---|
6869 | CALL XERRDV(MSG,1300,1,0,0,0,0,ZERO,ZERO) |
---|
6870 | GOTO 740 |
---|
6871 | 700 MSG = 'NG(=I1) < 0.' |
---|
6872 | CALL XERRDV(MSG,1310,0,1,NG,0,0,ZERO,ZERO) |
---|
6873 | GOTO 740 |
---|
6874 | 710 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 |
---|
6879 | 720 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 |
---|
6884 | 730 CONTINUE |
---|
6885 | MSG = 'WM length needed, LENWM(=I1) > LWMDIM(=I2)' |
---|
6886 | CALL XERRDV(MSG,1340,1,2,LENWM,LWMDIM,0,ZERO,ZERO) |
---|
6887 | |
---|
6888 | 740 CONTINUE |
---|
6889 | ISTATE = -3 |
---|
6890 | RUSER(1:LRWUSER) = RWORK(1:LRWUSER) |
---|
6891 | IUSER(1:LIWUSER) = IWORK(1:LIWUSER) |
---|
6892 | RETURN |
---|
6893 | |
---|
6894 | 750 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. |
---|
6988 | 10 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. |
---|
7022 | 20 H0 = HNEW*HALF |
---|
7023 | IF (H0<HLB) H0 = HLB |
---|
7024 | IF (H0>HUB) H0 = HUB |
---|
7025 | 30 H0 = SIGN(H0,TOUT-T0) |
---|
7026 | NITER = ITER |
---|
7027 | IER = 0 |
---|
7028 | RETURN |
---|
7029 | ! Error return for TOUT - T0 too small. |
---|
7030 | 40 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 |
---|
7094 | 10 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 |
---|
7107 | 20 C = REAL(IC) |
---|
7108 | DKY(1:N) = C*YH(1:N,JP1) + S*DKY(1:N) |
---|
7109 | END DO |
---|
7110 | 30 R = H**(-K) |
---|
7111 | CALL DSCAL_F90(N,R,DKY,1) |
---|
7112 | RETURN |
---|
7113 | 40 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 |
---|
7117 | 50 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 |
---|
7192 | 10 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 |
---|
7211 | 20 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 |
---|
7220 | 30 R = H**(-K) |
---|
7221 | CALL DSCAL_F90(N,R,DKY,1) |
---|
7222 | RETURN |
---|
7223 | 40 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 |
---|
7227 | 50 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 |
---|
7231 | 60 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 | |
---|
7417 | 10 CONTINUE |
---|
7418 | IF (KUTH==1) THEN |
---|
7419 | ETA = MIN(ETA,H/HSCAL) |
---|
7420 | NEWH = 1 |
---|
7421 | END IF |
---|
7422 | 20 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 | |
---|
7449 | 30 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 |
---|
7456 | 40 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 |
---|
7475 | 50 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. |
---|
7482 | 60 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 | |
---|
7500 | 70 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 | |
---|
7548 | 80 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) |
---|
7604 | 90 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 | |
---|
7618 | 100 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 |
---|
7647 | 110 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 |
---|
7655 | 120 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. |
---|
7682 | 130 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) |
---|
7694 | 140 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) |
---|
7701 | 150 IF (ETAQ>=ETAQP1) GOTO 160 |
---|
7702 | IF (ETAQP1>ETAQM1) GOTO 190 |
---|
7703 | GOTO 180 |
---|
7704 | 160 IF (ETAQ<ETAQM1) GOTO 180 |
---|
7705 | 170 ETA = ETAQ |
---|
7706 | NEWQ = NQ |
---|
7707 | GOTO 200 |
---|
7708 | 180 ETA = ETAQM1 |
---|
7709 | NEWQ = NQ - 1 |
---|
7710 | GOTO 200 |
---|
7711 | 190 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. |
---|
7718 | 200 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 |
---|
7724 | 210 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 | |
---|
7733 | 220 KFLAG = -1 |
---|
7734 | GOTO 260 |
---|
7735 | 230 KFLAG = -2 |
---|
7736 | GOTO 260 |
---|
7737 | 240 IF (NFLAG==-2) KFLAG = -3 |
---|
7738 | IF (NFLAG==-3) KFLAG = -4 |
---|
7739 | GOTO 260 |
---|
7740 | 250 ETAMAX = ETAMX3 |
---|
7741 | IF (NST<=10) ETAMAX = ETAMX2 |
---|
7742 | R = ONE/TQ(2) |
---|
7743 | |
---|
7744 | CALL DSCAL_F90(N,R,ACOR,1) |
---|
7745 | 260 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. |
---|
7808 | 10 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 |
---|
7816 | 20 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) |
---|
7829 | 30 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. |
---|
7874 | 40 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 |
---|
7903 | 50 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) |
---|
7919 | 60 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. |
---|
7963 | 10 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. |
---|
7992 | 20 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. |
---|
8000 | 30 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. |
---|
8022 | 40 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 |
---|
8044 | 50 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 | |
---|
8154 | 10 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 |
---|
8185 | 20 ACOR(1:N) = ZERO |
---|
8186 | ! This is a looping point for the corrector iteration. |
---|
8187 | 30 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 | |
---|
8204 | 40 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 | |
---|
8219 | 50 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 | |
---|
8238 | 60 IF (MITER==0 .OR. JCUR==1) GOTO 70 |
---|
8239 | ICF = 1 |
---|
8240 | IPUP = MITER |
---|
8241 | GOTO 10 |
---|
8242 | |
---|
8243 | 70 CONTINUE |
---|
8244 | NFLAG = -1 |
---|
8245 | ICF = 2 |
---|
8246 | IPUP = MITER |
---|
8247 | RETURN |
---|
8248 | |
---|
8249 | ! Return for successful step. |
---|
8250 | 80 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 |
---|
8557 | 10 END DO |
---|
8558 | RETURN |
---|
8559 | 20 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 | |
---|
8884 | 10 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 | |
---|
8906 | 20 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 | |
---|
8919 | 30 DO I = 1, N |
---|
8920 | ! X(I) = WM(I+2)*X(I) |
---|
8921 | X(I) = WM(I)*X(I) |
---|
8922 | END DO |
---|
8923 | RETURN |
---|
8924 | 40 IERSL = 1 |
---|
8925 | RETURN |
---|
8926 | |
---|
8927 | 50 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 |
---|
9137 | 10 CONTINUE |
---|
9138 | EWT(1:N) = RTOL(1)*ABS(YCUR(1:N)) + ATOL(1) |
---|
9139 | RETURN |
---|
9140 | 20 CONTINUE |
---|
9141 | EWT(1:N) = RTOL(1)*ABS(YCUR(1:N)) + ATOL(1:N) |
---|
9142 | RETURN |
---|
9143 | 30 CONTINUE |
---|
9144 | EWT(1:N) = RTOL(1:N)*ABS(YCUR(1:N)) + ATOL(1) |
---|
9145 | RETURN |
---|
9146 | 40 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 |
---|
9251 | 90000 FORMAT (1X,A) |
---|
9252 | IF (NI==1) WRITE (LUNIT,90001) I1 |
---|
9253 | 90001 FORMAT ('In the above message, I1 = ',I10) |
---|
9254 | IF (NI==2) WRITE (LUNIT,90002) I1, I2 |
---|
9255 | 90002 FORMAT ('In the above message, I1 = ',I10,3X,'I2 = ',I10) |
---|
9256 | IF (NR==1) WRITE (LUNIT,90003) R1 |
---|
9257 | 90003 FORMAT ('In the above message, R1 = ',D21.13) |
---|
9258 | IF (NR==2) WRITE (LUNIT,90004) R1, R2 |
---|
9259 | 90004 FORMAT ('In the above message, R1 = ',D21.13,3X,'R2 = ',D21.13) |
---|
9260 | |
---|
9261 | ! Abort the run if LEVEL = 2. |
---|
9262 | 10 IF (LEVEL/=2) RETURN |
---|
9263 | WRITE (LUNIT,90005) |
---|
9264 | 90005 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 |
---|
9459 | 10 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 | |
---|
9500 | 20 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: |
---|
9510 | 30 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 |
---|
9543 | 40 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 |
---|
9554 | 50 IAN(J+1) = KNEW |
---|
9555 | KMIN = KMAX + 1 |
---|
9556 | END DO |
---|
9557 | GOTO 90 |
---|
9558 | |
---|
9559 | 60 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. |
---|
9587 | 70 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 |
---|
9619 | 80 END DO |
---|
9620 | IAN(J+1) = K |
---|
9621 | END DO |
---|
9622 | 90 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) |
---|
9626 | 100 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 | |
---|
9805 | 10 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 |
---|
9884 | 80 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 |
---|
9981 | 10 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 |
---|
9990 | 20 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 |
---|
9997 | 30 NGRP = NG - 1 |
---|
9998 | RETURN |
---|
9999 | 40 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 |
---|
10346 | 10 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 |
---|
10444 | 10 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 | |
---|
10555 | 10 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 |
---|
10586 | 20 ACOR(1:N) = ZERO |
---|
10587 | ! This is a looping point for the corrector iteration. |
---|
10588 | 30 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 | |
---|
10606 | 40 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 | |
---|
10621 | 50 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 | |
---|
10640 | 60 IF (MITER==0 .OR. JCUR==1) GOTO 70 |
---|
10641 | ICF = 1 |
---|
10642 | IPUP = MITER |
---|
10643 | GOTO 10 |
---|
10644 | |
---|
10645 | 70 CONTINUE |
---|
10646 | NFLAG = -1 |
---|
10647 | ICF = 2 |
---|
10648 | IPUP = MITER |
---|
10649 | RETURN |
---|
10650 | |
---|
10651 | ! Return for successful step. |
---|
10652 | 80 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 |
---|
10821 | 10 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. |
---|
10960 | 17 JVECT(K) = I |
---|
10961 | ! Define the column pointers for MA28AD. |
---|
10962 | ICN(K) = J |
---|
10963 | GOTO 19 |
---|
10964 | ! Define the column pointers for MA28AD. |
---|
10965 | 18 JVECT(K) = J |
---|
10966 | 19 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. |
---|
11000 | 20 JVECT(K) = I |
---|
11001 | ! Define column pointers for MA28AD. |
---|
11002 | ICN(K) = J |
---|
11003 | GOTO 40 |
---|
11004 | ! Define column pointers for MA28AD. |
---|
11005 | 30 JVECT(K) = J |
---|
11006 | 40 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. |
---|
11030 | 50 JVECT(K) = I |
---|
11031 | ! Define column pointers for MA28AD. |
---|
11032 | ICN(K) = J |
---|
11033 | GOTO 70 |
---|
11034 | ! Define column pointers for MA28AD. |
---|
11035 | 60 JVECT(K) = J |
---|
11036 | 70 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 | |
---|
11051 | 80 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 | |
---|
11152 | 90 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) |
---|
11252 | 10 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. |
---|
11326 | 10 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 | |
---|
11354 | 20 CONTINUE |
---|
11355 | RETURN |
---|
11356 | |
---|
11357 | 30 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 |
---|
11381 | 40 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 |
---|
11388 | 50 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. |
---|
11395 | 60 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. |
---|
11401 | 70 IF (ABS(TN-TLAST)<=ZERO) GOTO 130 |
---|
11402 | |
---|
11403 | 80 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 |
---|
11417 | 90 T1 = TN |
---|
11418 | DO I = 1, N |
---|
11419 | Y(I) = YH(I,1) |
---|
11420 | END DO |
---|
11421 | 100 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 |
---|
11425 | 110 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 |
---|
11438 | 120 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 |
---|
11451 | 130 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. |
---|
11566 | 10 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 |
---|
11571 | 20 END DO |
---|
11572 | IF (IMAX>0) GOTO 30 |
---|
11573 | SGNCHG = .FALSE. |
---|
11574 | GOTO 40 |
---|
11575 | 30 SGNCHG = .TRUE. |
---|
11576 | 40 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. |
---|
11583 | 50 CONTINUE |
---|
11584 | IF (XROOT) GOTO 170 |
---|
11585 | IF (NXLAST==LAST) GOTO 60 |
---|
11586 | ALPHA = ONE |
---|
11587 | GOTO 80 |
---|
11588 | 60 IF (LAST==0) GOTO 70 |
---|
11589 | ALPHA = HALF*ALPHA |
---|
11590 | GOTO 80 |
---|
11591 | 70 ALPHA = TWO*ALPHA |
---|
11592 | 80 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. |
---|
11616 | 90 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. |
---|
11625 | 100 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 |
---|
11630 | 110 END DO |
---|
11631 | IF (IMAX>0) GOTO 120 |
---|
11632 | SGNCHG = .FALSE. |
---|
11633 | IMAX = IMXOLD |
---|
11634 | GOTO 130 |
---|
11635 | 120 SGNCHG = .TRUE. |
---|
11636 | 130 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 |
---|
11644 | 140 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. |
---|
11651 | 150 CONTINUE |
---|
11652 | CALL DCOPY_F90(NG,GX,1,G0,1) |
---|
11653 | X0 = X2 |
---|
11654 | LAST = 0 |
---|
11655 | XROOT = .FALSE. |
---|
11656 | 160 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. |
---|
11660 | 170 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 |
---|
11668 | 180 IF (ABS(SIGN(ONE,G0(I))-SIGN(ONE,G1(I)))>ZERO) JROOT(I) = 1 |
---|
11669 | 190 END DO |
---|
11670 | RETURN |
---|
11671 | |
---|
11672 | ! No sign change in the interval. Check for zero at right endpoint. |
---|
11673 | 200 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. |
---|
11686 | 210 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 |
---|
12189 | 10 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 |
---|
12205 | 20 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 |
---|
12211 | 30 CONTINUE |
---|
12212 | INFO = K |
---|
12213 | 40 CONTINUE |
---|
12214 | END DO |
---|
12215 | 50 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 |
---|
12293 | 10 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 |
---|
12298 | 20 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 |
---|
12311 | 30 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 |
---|
12332 | 40 CONTINUE |
---|
12333 | END DO |
---|
12334 | 50 CONTINUE |
---|
12335 | 60 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 |
---|
12434 | 10 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 |
---|
12451 | 20 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 |
---|
12473 | 30 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 |
---|
12494 | 40 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 |
---|
12499 | 50 CONTINUE |
---|
12500 | GOTO 70 |
---|
12501 | 60 CONTINUE |
---|
12502 | INFO = K |
---|
12503 | 70 CONTINUE |
---|
12504 | END DO |
---|
12505 | 80 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 |
---|
12592 | 10 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 |
---|
12597 | 20 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 |
---|
12613 | 30 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 |
---|
12644 | 40 CONTINUE |
---|
12645 | END DO |
---|
12646 | 50 CONTINUE |
---|
12647 | 60 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 | |
---|
12706 | 10 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 | |
---|
12721 | 20 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 |
---|
12725 | 30 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 | |
---|
12736 | 40 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 | |
---|
12794 | 10 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 | |
---|
12809 | 20 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 |
---|
12815 | 30 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 | |
---|
12829 | 40 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 | |
---|
12890 | 10 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 | |
---|
12905 | 20 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 |
---|
12911 | 30 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 | |
---|
12920 | 40 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 | |
---|
12979 | 10 M = MOD(N,5) |
---|
12980 | IF (M==0) GOTO 20 |
---|
12981 | DX(1:M) = DA*DX(1:M) |
---|
12982 | IF (N<5) RETURN |
---|
12983 | 20 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 | |
---|
13058 | 10 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 |
---|
13341 | 10 IF (NZ>0) GOTO 20 |
---|
13342 | IFLAG = -9 |
---|
13343 | IF (LP/=0) WRITE (LP,90001) NZ |
---|
13344 | GOTO 170 |
---|
13345 | 20 IF (LICN>=NZ) GOTO 30 |
---|
13346 | IFLAG = -10 |
---|
13347 | IF (LP/=0) WRITE (LP,90002) LICN |
---|
13348 | GOTO 170 |
---|
13349 | 30 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. |
---|
13355 | 40 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) |
---|
13361 | 50 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. |
---|
13402 | 70 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))) |
---|
13408 | 80 END DO |
---|
13409 | IKEEP(I,1) = LENGTH |
---|
13410 | J1 = IEND |
---|
13411 | 90 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. |
---|
13430 | 100 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 |
---|
13443 | 130 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. |
---|
13453 | 140 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) |
---|
13460 | 150 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. |
---|
13472 | 160 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 |
---|
13486 | 170 IF (LP/=0) WRITE (LP,90009) |
---|
13487 | 180 RETURN |
---|
13488 | 90000 FORMAT (' N is out of range = ',I10) |
---|
13489 | 90001 FORMAT (' NZ is non positive = ',I10) |
---|
13490 | 90002 FORMAT (' LICN is too small = ',I10) |
---|
13491 | 90003 FORMAT (' LIRN is too small = ',I10) |
---|
13492 | 90004 FORMAT (' Error return from MA28AD because indices found out', & |
---|
13493 | ' of range') |
---|
13494 | 90005 FORMAT (1X,I6,'The element with value ',1P,D22.14, & |
---|
13495 | ' is out of range with indices ',I8,',',I8) |
---|
13496 | 90006 FORMAT (' Duplicate element in position ',I8,',',I8,' with value ',1P, & |
---|
13497 | D22.14) |
---|
13498 | 90007 FORMAT (' Error return from MC23AD') |
---|
13499 | 90008 FORMAT (' Error return from MA30AD') |
---|
13500 | 90009 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 |
---|
13570 | 10 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 |
---|
13578 | 20 IF (NZ>0) GOTO 30 |
---|
13579 | IFLAG = -10 |
---|
13580 | IF (LP/=0) WRITE (LP,90002) NZ |
---|
13581 | GOTO 60 |
---|
13582 | 30 IF (LICN>=NZ) GOTO 40 |
---|
13583 | IFLAG = -9 |
---|
13584 | IF (LP/=0) WRITE (LP,90003) LICN |
---|
13585 | GOTO 60 |
---|
13586 | |
---|
13587 | 40 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. |
---|
13610 | 50 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 |
---|
13619 | 60 IF (LP/=0) WRITE (LP,90005) |
---|
13620 | 70 RETURN |
---|
13621 | 90000 FORMAT (' Error return from MA28BD with IFLAG = ',I4/I7, & |
---|
13622 | ' Entries dropped from structure by MA28AD') |
---|
13623 | 90001 FORMAT (' N is out of range = ',I10) |
---|
13624 | 90002 FORMAT (' NZ is non positive = ',I10) |
---|
13625 | 90003 FORMAT (' LICN is too small = ',I10) |
---|
13626 | 90004 FORMAT (' Error return from MA30BD') |
---|
13627 | 90005 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) |
---|
13685 | 10 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 |
---|
13693 | 20 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 |
---|
13704 | 30 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 |
---|
13714 | 50 J1 = IW(INEW,1) |
---|
13715 | J2 = J1 + LENOFF(INEW) - 1 |
---|
13716 | GOTO 110 |
---|
13717 | ! Element is in diagonal block. |
---|
13718 | 60 J1 = IW(INEW,2) |
---|
13719 | IF (INEW>JNEW) GOTO 70 |
---|
13720 | J2 = J1 + LENR(INEW) - 1 |
---|
13721 | J1 = J1 + LENRL(INEW) |
---|
13722 | GOTO 110 |
---|
13723 | 70 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 |
---|
13735 | 90 J1 = MIDPT |
---|
13736 | 100 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. |
---|
13741 | 110 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. |
---|
13749 | 130 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 |
---|
13758 | 150 A(MIDPT) = AA |
---|
13759 | ICN(MIDPT) = -ICN(MIDPT) |
---|
13760 | GOTO 170 |
---|
13761 | 160 A(MIDPT) = A(MIDPT) + AA |
---|
13762 | ! Set flag for duplicate elements. |
---|
13763 | iflag = n + 1 |
---|
13764 | 170 END DO |
---|
13765 | ! Reset ICN array and zero elements in LU but not in A. |
---|
13766 | ! Also calculate the maximum element of A. |
---|
13767 | 180 W1 = ZERO |
---|
13768 | DO 200 I = 1, IDISP2 |
---|
13769 | IF (ICN(I)<0) GOTO 190 |
---|
13770 | A(I) = ZERO |
---|
13771 | GOTO 200 |
---|
13772 | 190 ICN(I) = -ICN(I) |
---|
13773 | W1 = MAX(W1,ABS(A(I))) |
---|
13774 | 200 END DO |
---|
13775 | RETURN |
---|
13776 | 90000 FORMAT (' Element ',I6,' with value ',D22.14,' has indices ',I8, & |
---|
13777 | ','/I8,' indices out of range') |
---|
13778 | 90001 FORMAT (' Non-zero ',I7,',',I6,' in zero off-diagonal',' block') |
---|
13779 | 90002 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 | |
---|
13925 | 20 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. |
---|
13951 | 60 DO I = 1, NZ |
---|
13952 | NROW = IRNORG(I) |
---|
13953 | NCOL = ICNORG(I) |
---|
13954 | R(NROW) = R(NROW) - AORG(I)*X(NCOL) |
---|
13955 | END DO |
---|
13956 | 80 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 |
---|
13998 | 120 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. |
---|
14004 | 130 IFLAG = -17 |
---|
14005 | CONVER = DD/D |
---|
14006 | WRITE (LP,90001) IFLAG, CONVER, CGCE |
---|
14007 | |
---|
14008 | ! The iterative process is terminated. |
---|
14009 | |
---|
14010 | 140 ERRMAX = DD |
---|
14011 | 150 CONTINUE |
---|
14012 | 160 RETURN |
---|
14013 | 90000 FORMAT (' Error return from MA28ID with IFLAG = ',I3/' More than ', & |
---|
14014 | I5,' iterations required') |
---|
14015 | 90001 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. |
---|
14361 | 30 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 |
---|
14375 | 50 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 |
---|
14398 | 60 SCALE = ABS(A(IACTIV)) |
---|
14399 | IF (ABS(SCALE)<=ZERO) GOTO 70 |
---|
14400 | IF (LBIG) BIG = MAX(BIG,SCALE) |
---|
14401 | GOTO 80 |
---|
14402 | 70 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 |
---|
14411 | 80 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 |
---|
14417 | 90 LASTR(ISTART) = ISTART |
---|
14418 | IPC(ISTART) = -ISING |
---|
14419 | GOTO 1070 |
---|
14420 | |
---|
14421 | ! Non-trivial block. |
---|
14422 | 100 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. |
---|
14434 | 120 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 |
---|
14456 | 160 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 |
---|
14476 | 180 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 |
---|
14483 | 190 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 |
---|
14492 | 200 ISW = IFIRST(NZ) |
---|
14493 | IFIRST(NZ) = I |
---|
14494 | IF (ISW>0) GOTO 210 |
---|
14495 | NEXTR(I) = 0 |
---|
14496 | LASTR(I) = ISW |
---|
14497 | GOTO 220 |
---|
14498 | 210 NEXTR(I) = ISW |
---|
14499 | LASTR(I) = LASTR(ISW) |
---|
14500 | LASTR(ISW) = I |
---|
14501 | 220 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 |
---|
14531 | 240 LL = 2 |
---|
14532 | IJFIR = -IJFIR |
---|
14533 | GOTO 300 |
---|
14534 | 250 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 |
---|
14569 | 270 END DO |
---|
14570 | END DO |
---|
14571 | |
---|
14572 | ! Columns with NZ non-zeros now examined. |
---|
14573 | 290 IJFIR = IFIRST(NZ) |
---|
14574 | IJFIR = -LASTR(IJFIR) |
---|
14575 | 300 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 |
---|
14608 | 320 END DO |
---|
14609 | 330 END DO |
---|
14610 | 340 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 |
---|
14628 | 360 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 |
---|
14647 | 370 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) |
---|
14657 | 390 IF (K==ILAST) GOTO 410 |
---|
14658 | 400 END DO |
---|
14659 | 410 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 |
---|
14665 | 420 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. |
---|
14671 | 430 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 |
---|
14681 | 440 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 |
---|
14709 | 450 NZ = LENC(J) |
---|
14710 | ISW = IFIRST(NZ) |
---|
14711 | IF (ISW>0) LASTR(ISW) = -NC |
---|
14712 | IF (ISW<0) IFIRST(NZ) = -NC |
---|
14713 | 460 END DO |
---|
14714 | ! Changes to row ordering. |
---|
14715 | 470 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 |
---|
14725 | 480 NZ = LENR(I) - LENRL(I) |
---|
14726 | IF (NR/=0) IFIRST(NZ) = NR |
---|
14727 | IF (NR==0) IFIRST(NZ) = LR |
---|
14728 | 490 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. |
---|
14745 | 500 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. |
---|
14765 | 510 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 |
---|
14775 | 520 K = IBEG - IJPOS |
---|
14776 | J = ICN(JJ) |
---|
14777 | ICN(JJ) = IQ(J) |
---|
14778 | IQ(J) = -K |
---|
14779 | 530 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 |
---|
14802 | 550 END DO |
---|
14803 | 560 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 |
---|
14839 | 580 END DO |
---|
14840 | ! JUMP if pivot row is a singleton. |
---|
14841 | 590 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 |
---|
14873 | 600 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 | |
---|
14894 | 610 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 |
---|
14900 | 630 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 |
---|
14916 | 640 NZ = LENC(J) + 1 |
---|
14917 | ISW = IFIRST(NZ) |
---|
14918 | IF (ISW>0) LASTR(ISW) = -NC |
---|
14919 | IF (ISW<0) IFIRST(NZ) = -NC |
---|
14920 | 650 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 |
---|
14932 | 670 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. |
---|
14950 | 690 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 |
---|
14959 | 710 JNPOS = I1 - JMORE |
---|
14960 | GOTO 730 |
---|
14961 | ! Whole row must be moved to the beginning of available |
---|
14962 | ! storage. |
---|
14963 | 720 JNPOS = IACTIV - LENR(I) - IFILL |
---|
14964 | ! Jump if there is space immediately available for the |
---|
14965 | ! shifted row. |
---|
14966 | 730 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 |
---|
14995 | 750 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 |
---|
15006 | 770 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 |
---|
15021 | 780 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 |
---|
15032 | 790 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. |
---|
15042 | 800 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 |
---|
15055 | 830 IRN(JEND) = I |
---|
15056 | NZCOL = NZCOL + 1 |
---|
15057 | LENC(J) = LENC(J) + 1 |
---|
15058 | ! End of adjustment to column file. |
---|
15059 | GOTO 850 |
---|
15060 | 840 ICN(JJ) = -J |
---|
15061 | 850 END DO |
---|
15062 | IF (IDROP==0) GOTO 870 |
---|
15063 | DO KDROP = 1, IDROP |
---|
15064 | ICN(IEND) = 0 |
---|
15065 | IEND = IEND + 1 |
---|
15066 | END DO |
---|
15067 | 870 LENR(I) = LENR(I) + IFILL |
---|
15068 | ! End of scan of pivot column. |
---|
15069 | 880 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 |
---|
15083 | 890 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 |
---|
15092 | 910 LASTR(I) = LASTR(IFIR) |
---|
15093 | NEXTR(I) = IFIR |
---|
15094 | LASTR(IFIR) = I |
---|
15095 | GOTO 930 |
---|
15096 | 920 LASTR(I) = 0 |
---|
15097 | NEXTR(I) = 0 |
---|
15098 | NZMIN = MIN(NZMIN,NZ) |
---|
15099 | 930 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). |
---|
15103 | 940 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 |
---|
15125 | 960 NZMIN = MIN(NZMIN,NZ) |
---|
15126 | 970 END DO |
---|
15127 | GOTO 1050 |
---|
15128 | 980 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 |
---|
15137 | 990 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 |
---|
15148 | 1010 IFIRST(NZ) = -J |
---|
15149 | NEXTC(J) = 0 |
---|
15150 | GOTO 1030 |
---|
15151 | 1020 LC = -LASTR(IFIR) |
---|
15152 | LASTR(IFIR) = -J |
---|
15153 | NEXTC(J) = LC |
---|
15154 | IF (LC/=0) LASTC(LC) = J |
---|
15155 | 1030 NZMIN = MIN(NZMIN,NZ) |
---|
15156 | 1040 END DO |
---|
15157 | 1050 END DO |
---|
15158 | ! ******************************************** |
---|
15159 | ! **** End of main elimination loop **** |
---|
15160 | ! ******************************************** |
---|
15161 | |
---|
15162 | ! Reset IACTIV to point to the beginning of the |
---|
15163 | ! next block. |
---|
15164 | 1060 IF (ILAST/=NN) IACTIV = IPTR(ILAST+1) |
---|
15165 | 1070 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 |
---|
15178 | 1080 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. |
---|
15183 | 1090 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 |
---|
15190 | 1110 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 |
---|
15219 | 1160 IDISP(2) = IACTIV |
---|
15220 | IF (LP==0) GOTO 1190 |
---|
15221 | WRITE (LP,90003) |
---|
15222 | GOTO 1180 |
---|
15223 | 1170 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) |
---|
15229 | 1180 PIVOT = PIVOT - ISTART + 1 |
---|
15230 | WRITE (LP,90006) PIVOT, NBLOCK, ISTART, ILAST |
---|
15231 | IF (PIVOT==0) WRITE (LP,90007) MINIRN |
---|
15232 | |
---|
15233 | 1190 RETURN |
---|
15234 | 90000 FORMAT (' Error return from MA30AD because matrix is', & |
---|
15235 | ' structurally singular') |
---|
15236 | 90001 FORMAT (' Error return from MA30AD because matrix is', & |
---|
15237 | ' numerically singular') |
---|
15238 | 90002 FORMAT (' LU decomposition destroyed to create more space') |
---|
15239 | 90003 FORMAT (' Error return from MA30AD because LICN is not big enough') |
---|
15240 | 90004 FORMAT (' Error return from MA30AD because LIRN is not big enough') |
---|
15241 | 90005 FORMAT (' Error return from MA30AD LIRN and LICN are too small') |
---|
15242 | 90006 FORMAT (' At stage ',I5,' in block ',I5,' with first row ',I5, & |
---|
15243 | ' and last row ',I5) |
---|
15244 | 90007 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 |
---|
15283 | 10 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 |
---|
15299 | 20 ICN(KN) = ICN(JPOS) |
---|
15300 | 30 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. |
---|
15385 | 30 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 |
---|
15419 | 60 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 |
---|
15424 | 80 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. |
---|
15433 | 100 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. |
---|
15444 | 110 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 |
---|
15448 | 120 END DO |
---|
15449 | 130 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 |
---|
15456 | 140 END DO |
---|
15457 | ISING = 0 |
---|
15458 | GOTO 170 |
---|
15459 | ! Matrix had non-zero pivot in MA30AD at this stage. |
---|
15460 | 150 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. |
---|
15471 | 170 END DO |
---|
15472 | |
---|
15473 | GOTO 190 |
---|
15474 | ! Error return |
---|
15475 | 180 IF (LP/=0) WRITE (LP,90000) I |
---|
15476 | IFLAG = -I |
---|
15477 | |
---|
15478 | 190 RETURN |
---|
15479 | 90000 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. |
---|
15613 | 30 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. |
---|
15623 | 50 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. |
---|
15646 | 70 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 |
---|
15663 | 90 W(II) = W(II)/A(JPIV) |
---|
15664 | END DO |
---|
15665 | 110 IFIRST = I + 1 |
---|
15666 | NEG = .FALSE. |
---|
15667 | 120 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)). |
---|
15680 | 140 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 |
---|
15712 | 170 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 |
---|
15737 | 190 W(I) = WI |
---|
15738 | 200 J1 = J1 + LENR(I) |
---|
15739 | END DO |
---|
15740 | GOTO 240 |
---|
15741 | ! Deal with rest of block which is singular. |
---|
15742 | 220 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. |
---|
15751 | 240 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 |
---|
15763 | 260 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 |
---|
15775 | 280 END DO |
---|
15776 | IBLEND = J1 |
---|
15777 | ILAST = IFIRST - 1 |
---|
15778 | END DO |
---|
15779 | ! Reorder solution vector, X(I) = W(IPINVERSE(I)). |
---|
15780 | 300 DO II = 1, N |
---|
15781 | I = IP(II) |
---|
15782 | I = IABS(I) |
---|
15783 | X(I) = W(II) |
---|
15784 | END DO |
---|
15785 | |
---|
15786 | 320 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. |
---|
16022 | 20 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. |
---|
16027 | 30 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 |
---|
16042 | 50 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. |
---|
16051 | 60 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. |
---|
16058 | 70 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 |
---|
16066 | 80 END DO |
---|
16067 | |
---|
16068 | 90 END DO |
---|
16069 | |
---|
16070 | ! Put permutation in the required form. |
---|
16071 | 100 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 |
---|
16143 | 40 JCE = JCEP + JDISP |
---|
16144 | |
---|
16145 | 50 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 |
---|
16196 | 20 INUM(K-1) = ICE |
---|
16197 | A(K-1) = ACE |
---|
16198 | KOR = KOR - 1 |
---|
16199 | END DO |
---|
16200 | ! Next column. |
---|
16201 | 40 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. |
---|
16286 | 30 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 |
---|
16304 | 40 END DO |
---|
16305 | |
---|
16306 | ! Backtracking step. |
---|
16307 | 50 J = PR(J) |
---|
16308 | IF (J==-1) GOTO 100 |
---|
16309 | END DO |
---|
16310 | |
---|
16311 | 70 END DO |
---|
16312 | |
---|
16313 | ! New assignment is made. |
---|
16314 | 80 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 | |
---|
16325 | 100 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 |
---|
16337 | 120 J = IPERM(I) |
---|
16338 | ARP(J) = I |
---|
16339 | 130 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 |
---|
16346 | 140 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 |
---|
16396 | 20 IW1(J) = IOLD |
---|
16397 | JJ = J2 + 1 |
---|
16398 | 30 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 |
---|
16439 | 60 A(IPOS) = AVAL |
---|
16440 | 70 ICN(IPOS) = IW(JVAL,2) |
---|
16441 | ! END OF MAIN LOOP |
---|
16442 | 80 END DO |
---|
16443 | 90 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. |
---|
16481 | 20 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)). |
---|
16532 | 60 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 |
---|
16586 | 90 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 |
---|
16592 | 100 IW1(I,1) = IW1(I-1,1) + LENOFF(I-1) |
---|
16593 | |
---|
16594 | ! Row IOLD is now split into diagonal and off-diagonal parts. |
---|
16595 | 110 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 |
---|
16618 | 120 END DO |
---|
16619 | |
---|
16620 | LENOFF(IOLD) = LENOFF(IOLD) - LENI |
---|
16621 | 130 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 |
---|
16641 | 160 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 |
---|
16648 | 170 IF (LP/=0) WRITE (LP,90000) NUMNZ |
---|
16649 | 90000 FORMAT (' Matrix is structurally singular, rank = ',I6) |
---|
16650 | IDISP(1) = -1 |
---|
16651 | GOTO 190 |
---|
16652 | 180 IF (LP/=0) WRITE (LP,90001) N |
---|
16653 | 90001 FORMAT (' LICN is not big enough; increase by ',I6) |
---|
16654 | IDISP(1) = -2 |
---|
16655 | 190 IF (LP/=0) WRITE (LP,90002) |
---|
16656 | 90002 FORMAT (' + Error return from MC23AD') |
---|
16657 | 200 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 |
---|
16693 | 20 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). |
---|
16698 | 30 J0 = J0 + 1 |
---|
16699 | IF (J0>J2) GOTO 50 |
---|
16700 | DO 40 JJ = J0, J2 |
---|
16701 | J = ICN(JJ) |
---|
16702 | 40 W(J) = MAX(ABS(A(JJ)),W(J)) |
---|
16703 | 50 J0 = J2 + 1 |
---|
16704 | 60 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 |
---|
16778 | 90000 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. |
---|
16783 | 30 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 |
---|
16787 | 40 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) |
---|
16810 | 60 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) |
---|
16830 | 80 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) |
---|
16855 | 110 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 |
---|
16881 | 160 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. |
---|
16886 | 180 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) |
---|
16892 | 190 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 |
---|
16900 | 210 IF (LP>0) WRITE (LP,90001) IFAIL |
---|
16901 | 90001 FORMAT (' Error return ',I2,' from MC19') |
---|
16902 | 220 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 |
---|
17278 | 10 CONTINUE |
---|
17279 | END IF |
---|
17280 | DO 20 J = 1, 50 |
---|
17281 | IWK(J) = 0 |
---|
17282 | 20 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 |
---|
17296 | 30 CONTINUE |
---|
17297 | 40 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 |
---|
17337 | 50 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 | |
---|
17347 | 60 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 |
---|
17408 | 100 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 | |
---|
17718 | 30 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. |
---|
17728 | 40 CONTINUE |
---|
17729 | JP = IWA1(MAXINC) |
---|
17730 | IF (JP > 0) GOTO 50 |
---|
17731 | MAXINC = MAXINC - 1 |
---|
17732 | GOTO 40 |
---|
17733 | 50 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 |
---|
17743 | 70 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 |
---|
17794 | 100 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) |
---|
17883 | 30 CONTINUE |
---|
17884 | IF (K == 0) GOTO 40 |
---|
17885 | INDEX(I) = K |
---|
17886 | I = I + 1 |
---|
17887 | K = NEXT(K) |
---|
17888 | GOTO 30 |
---|
17889 | 40 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 |
---|
17989 | 50 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 | |
---|
18186 | 30 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. |
---|
18193 | 40 CONTINUE |
---|
18194 | JCOL = IWA1(MINDEG) |
---|
18195 | IF (JCOL > 0) GOTO 50 |
---|
18196 | MINDEG = MINDEG + 1 |
---|
18197 | GOTO 40 |
---|
18198 | 50 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 |
---|
18247 | 80 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. |
---|
18331 | 40 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 |
---|
18475 | 40 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 |
---|
18789 | 10 CONTINUE |
---|
18790 | END IF |
---|
18791 | DO 20 J = 1, 50 |
---|
18792 | IWK(J) = 0 |
---|
18793 | 20 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 |
---|
18808 | 30 CONTINUE |
---|
18809 | 40 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 |
---|
18876 | 50 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 | |
---|
18886 | 60 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 |
---|
18986 | 100 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 | !_______________________________________________________________________ |
---|