File: N:\mfix\model\chem\stiff_chem_mod.f
1 MODULE STIFF_CHEM
2
3
4
5
6
7 external STIFF_CHEM_RRATES
8
9 LOGICAL, external :: COMPARE
10
11 DOUBLE PRECISION, external :: CALC_H0
12
13
14
15
16
17 LOGICAL :: STIFF_CHEMISTRY
18
19
20
21 LOGICAL, dimension(:), allocatable :: notOwner
22
23
24
25
26 INTEGER :: ODE_DIMN_all
27
28 INTEGER :: ODE_DIMN_g
29
30
31 INTEGER :: NEQ_DIMN
32
33
34 INTEGER :: ODE_ITOL
35
36 DOUBLE PRECISION, DIMENSION(1) :: ODE_RTOL
37
38 DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: ODE_ATOL
39
40 INTEGER :: ODE_LRW
41
42 INTEGER :: ODE_LIW
43
44 INTEGER :: ODE_JT
45
46 INTEGER :: STIFF_CHEM_MAX_STEPS
47
48 LOGICAL :: UNLIMITED_STEPS
49
50
51
52 INTERFACE
53 SUBROUTINE DLSODA (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, &
54 ITASK,ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, JT)
55 external F
56 INTEGER :: ITOL, ITASK, ISTATE, IOPT, LRW, LIW, JT
57 INTEGER, dimension(2) :: NEQ
58 INTEGER, dimension(LIW) :: IWORK
59 DOUBLE PRECISION :: T, TOUT
60 DOUBLE PRECISION :: JAC
61 DOUBLE PRECISION, dimension(1) :: RTOL
62 DOUBLE PRECISION, dimension(LRW) :: RWORK
63 DOUBLE PRECISION, dimension(NEQ(1)) :: Y, ATOL
64 END SUBROUTINE DLSODA
65 END INTERFACE
66
67 contains
68
69
70
71
72
73
74
75
76
77
78 SUBROUTINE STIFF_CHEM_SOLVER(ODE_DT, iErr)
79
80
81
82 use stiff_chem_maps, only : mapODEtoMFIX
83 use stiff_chem_maps, only : mapMFIXtoODE
84
85
86
87 use output, only : FULL_LOG
88 use param1, only : zero
89 use run, only : TIME
90
91 use mpi_utility
92
93 use stiff_chem_dbg
94 use stiff_chem_stats
95 use functions
96
97 implicit none
98
99
100
101
102 DOUBLE PRECISION, intent(IN) :: ODE_DT
103
104 INTEGER, intent(OUT) :: iErr
105
106
107
108
109 LOGICAL :: lErr_l
110
111
112 INTEGER :: IJK
113
114 DOUBLE PRECISION, dimension(ODE_DIMN_all) :: ODE_VARS
115
116
117
118
119 INTEGER, dimension(NEQ_DIMN) :: lNEQ
120
121 DOUBLE PRECISION :: lT
122
123 DOUBLE PRECISION :: lTOUT
124
125 INTEGER :: lITOL
126
127 DOUBLE PRECISION :: lRTOL(1)
128
129 DOUBLE PRECISION :: lATOL(ODE_DIMN_all)
130
131 INTEGER :: lITASK
132
133 INTEGER :: lISTATE
134
135 INTEGER :: lIOPT
136
137 DOUBLE PRECISION :: RWORK(ODE_LRW)
138
139 INTEGER :: lLRW
140
141 INTEGER :: IWORK(ODE_LIW)
142
143 INTEGER :: lLIW
144
145 DOUBLE PRECISION :: lJAC
146
147 INTEGER :: lJT
148
149
150 INTEGER :: lAtps
151
152 LOGICAL :: lReset
153 LOGICAL :: lIncpt
154
155 lErr_l = .FALSE.
156
157 CALL INIT_STIFF_CHEM_STATS
158
159 IJK_LP: DO IJK = IJKSTART3, IJKEND3
160 IF(notOwner(IJK)) cycle IJK_LP
161 IF(FLUID_AT(IJK)) THEN
162
163 lAtps = 0
164 lReset = .FALSE.
165 lIncpt = .FALSE.
166
167
168 = ODE_RTOL
169 lATOL = ODE_ATOL
170
171
172 = lAtps + 1
173
174
175 = 0.0d0
176 lTOUT = ODE_DT
177 lITOL = ODE_ITOL
178 lLRW = ODE_LRW
179 lLIW = ODE_LIW
180 lJT = ODE_JT
181
182
183 = 1
184 lISTATE = 1
185 lIOPT = 1
186
187
188 CALL CALC_ODE_COEFF(lNEQ, IJK)
189
190
191 = 0
192 RWORK = ZERO
193
194
195
196 (6) = STIFF_CHEM_MAX_STEPS
197
198 IF(CALC_REACTIONS(IJK)) THEN
199
200
201 CALL mapMFIXtoODE(NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
202
203
204
205 CALL UPDATE_ODE_OLD(ODE_DIMN_all, ODE_VARS)
206
207
208 = 0
209
210
211 CALL DLSODA(STIFF_CHEM_RRATES, lNEQ, ODE_VARS, lT, &
212 lTOUT, lITOL, lRTOL, lATOL, lITASK, lISTATE, lIOPT, &
213 RWORK, lLRW, IWORK, lLIW, lJAC, lJT)
214
215
216 CALL CHECK_ODE_DATA(NEQ_DIMN, lNEQ, ODE_DIMN_all, &
217 ODE_VARS, UNLIMITED_STEPS, lISTATE, iErr)
218
219
220 IF(iErr == 0) THEN
221 lReset = .FALSE.
222
223 ELSEIF(iErr == -1) THEN
224
225 IF(UNLIMITED_STEPS) THEN
226 lISTATE = 2
227 goto 100
228 ELSE
229 lReset = .FALSE.
230 lIncpt = .TRUE.
231 ENDIF
232
233
234 ELSEIF(iErr == -2) THEN
235 IF(lAtps < 3) THEN
236
237 IF(ODE_DEBUG_LEVEL >= 2) CALL WRITE_ODE_LOG(iErr, &
238 NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
239
240 CALL RESET_ODE(ODE_DIMN_all, ODE_VARS, lAtps)
241
242 CALL mapODEtoMFIX(NEQ_DIMN, lNEQ, &
243 ODE_DIMN_all, ODE_VARS)
244
245 = ODE_RTOL*10.0d0
246 lATOL = ODE_ATOL*10.0d0
247 goto 50
248 ELSE
249
250 IF(ODE_DEBUG_LEVEL >= 1) CALL WRITE_ODE_LOG(iErr, &
251 NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
252
253 = .TRUE.
254 ENDIF
255
256 ELSE
257
258 IF(lAtps < 3) THEN
259
260 IF(ODE_DEBUG_LEVEL >= 2) CALL WRITE_ODE_LOG(iErr, &
261 NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
262
263 CALL RESET_ODE(ODE_DIMN_all, ODE_VARS, lAtps)
264
265 CALL mapODEtoMFIX(NEQ_DIMN, lNEQ, &
266 ODE_DIMN_all, ODE_VARS)
267
268 = ODE_RTOL/(10.0d0**lAtps)
269 lATOL = ODE_ATOL/(10.0d0**lAtps)
270 goto 50
271 ELSE
272
273 IF(ODE_DEBUG_LEVEL >= 1) CALL WRITE_ODE_LOG(iErr, &
274 NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
275
276 = .TRUE.
277 ENDIF
278
279 ENDIF
280
281
282 if(lReset) CALL RESET_ODE(ODE_DIMN_all, ODE_VARS, lAtps)
283
284 CALL mapODEtoMFIX(NEQ_DIMN, lNEQ, ODE_DIMN_all, ODE_VARS)
285
286 IF(FULL_LOG) CALL UPDATE_STIFF_CHEM_STATS(lNEQ, &
287 NEQ_DIMN, IWORK(11), ODE_DIMN_all, lAtps, lIncpt)
288
289
290 ENDIF
291 ENDIF
292 END DO IJK_LP
293
294
295
296
297
298
299 CALL FINALIZE_STIFF_SOLVER()
300
301 IF(FULL_LOG) CALL WRITE_STIFF_CHEM_STATS()
302
303 iErr = 0
304
305 RETURN
306 END SUBROUTINE STIFF_CHEM_SOLVER
307
308
309
310
311
312
313
314
315
316
317
318
319
320 LOGICAL FUNCTION CALC_REACTIONS(IJK)
321
322 use rxns, only : NO_OF_RXNS
323
324 implicit none
325
326 INTEGER, intent(in) :: IJK
327
328 DOUBLE PRECISION :: RATES(NO_OF_RXNS)
329
330 DOUBLE PRECISION, parameter :: rLimit = 1.0d-8
331
332
333 = 0.0d0
334
335
336 CALL USR_RATES(IJK, RATES)
337
338
339
340 = .TRUE.
341 if(maxval(RATES) < rLimit) CALC_REACTIONS = .FALSE.
342
343
344 RETURN
345 END FUNCTION CALC_REACTIONS
346
347
348
349
350
351
352
353
354
355
356
357
358
359 SUBROUTINE CALC_ODE_COEFF(lNEQ, IJK)
360
361 use fldvar, only : EP_S
362 use physprop, only : MMAX
363 use run, only : SPECIES_EQ
364
365 implicit none
366
367 INTEGER, intent(in) :: IJK
368 INTEGER, intent(out) :: lNEQ(NEQ_DIMN)
369
370 INTEGER :: M
371
372 LOGICAL :: USE_SOLIDS_ODEs
373
374
375 = .FALSE.
376 lNEQ(2) = IJK
377 lNEQ(3:) = 0
378
379
380
381 DO M=1, MMAX
382 IF(SPECIES_EQ(M)) THEN
383 IF(EP_s(IJK,M) > 1.0d-6) THEN
384 USE_SOLIDS_ODEs = .TRUE.
385 lNEQ(2+M) = 1
386 ENDIF
387 ENDIF
388 ENDDO
389
390 IF(USE_SOLIDS_ODEs)THEN
391 lNEQ(1) = ODE_DIMN_all
392 ELSE
393 lNEQ(1) = ODE_DIMN_g
394 lNEQ(3:) = 0
395 ENDIF
396
397
398 RETURN
399 END SUBROUTINE CALC_ODE_COEFF
400
401
402
403
404
405
406
407
408
409
410
411
412
413 SUBROUTINE FINALIZE_STIFF_SOLVER
414
415
416 use fldvar, only : EP_g
417
418 use fldvar, only: RO_g, ROP_g
419
420 use fldvar, only: P_g
421
422 use fldvar, only: T_g
423
424 use fldvar, only: X_g
425
426 use physprop, only : MW_g
427
428 use physprop, only : MW_MIX_g
429
430
431 use fldvar, only: ROP_S
432
433 use fldvar, only: T_s
434
435 use fldvar, only: X_s
436
437
438 use physprop, only: MMAX
439
440 use physprop, only: NMAX
441
442
443 use param1, only: ONE
444
445 use constant, only : GAS_CONST
446
447 use compar
448 use mpi_utility
449 use sendrecv
450 use functions
451 use utilities
452
453 implicit none
454
455
456 INTEGER :: IJK
457 INTEGER :: M
458 INTEGER :: NN
459
460 CALL send_recv(EP_G,2)
461 CALL send_recv(RO_G,2)
462 CALL send_recv(ROP_G,2)
463 CALL send_recv(T_G,2)
464
465 DO NN=1,NMAX(0)
466 CALL send_recv(X_G(:,NN),2)
467 CALL BOUND_X (X_G(1,NN), IJKMAX2)
468 ENDDO
469
470 DO M = 1, MMAX
471
472 CALL send_recv(T_S(:,M),2)
473
474 CALL send_recv(ROP_S(:,M),2)
475
476 DO NN=1,NMAX(M)
477 CALL send_recv(X_S(:,M,NN),2)
478 CALL BOUND_X (X_S(1,M,NN), IJKMAX2)
479 ENDDO
480 ENDDO
481
482 DO IJK = ijkStart3, ijkEnd3
483 IF(.NOT.FLUID_AT(IJK)) CYCLE
484
485 (IJK) = sum(X_G(IJK,1:NMAX(0))/MW_g(1:NMAX(0)))
486 MW_MIX_G(IJK) = ONE/MW_MIX_G(IJK)
487
488 (IJK) = (RO_G(IJK)*GAS_CONST*T_G(IJK))/MW_MIX_G(IJK)
489 ENDDO
490
491 RETURN
492 END SUBROUTINE FINALIZE_STIFF_SOLVER
493
494 END MODULE STIFF_CHEM
495