MFIX  2016-1
stiff_chem_mod.f
Go to the documentation of this file.
1  MODULE stiff_chem
2 
3 ! External Routines.
4 !---------------------------------------------------------------------//
5 ! Routine used to calculate the reaction rates and populate the
6 ! fluid variable ODEs for ODEPACK.
8 ! Routine used to compare to values.
9  LOGICAL, external :: compare
10 ! Routine used to calculate species enthalpies.
11  DOUBLE PRECISION, external :: calc_h0
12 
13 
14 ! Runtime Flags:
15 !---------------------------------------------------------------------//
16 ! Flag to invoke stiff chemistry solver.
17  LOGICAL :: stiff_chemistry
18 ! Flag to invoke variable solids density.
19 ! LOGICAL :: VARIABLE_DENSITY
20 ! Flag indicating if cell IJK is own by myPE.
21  LOGICAL, dimension(:), allocatable :: notowner
22 
23 ! ODEPACK Controlling parameters:
24 !---------------------------------------------------------------------//
25 ! Dimension of ODEs solved in stiff solver.
26  INTEGER :: ode_dimn_all
27 ! Dimension of ODEs solved in stiff solver for gas phase only.
28  INTEGER :: ode_dimn_g
29 
30 ! Dimension of ODEs solved in stiff solver for gas phase only.
31  INTEGER :: neq_dimn
32 
33 ! Indicates type of Error control.
34  INTEGER :: ode_itol
35 ! Relative error tolerance paramter.
36  DOUBLE PRECISION, DIMENSION(1) :: ode_rtol
37 ! Absolute error tolerance parameter. (Dimension (ODE_DIMN))
38  DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: ode_atol
39 ! Declared length of RWORK.
40  INTEGER :: ode_lrw
41 ! Declared length of IWORK.
42  INTEGER :: ode_liw
43 ! Jacobian type indicator.
44  INTEGER :: ode_jt
45 ! The maximum number of steps ODEPACK may use to integrate.
47 ! Flag indicating that the max number of steps is unlimited.
48  LOGICAL :: unlimited_steps
49 
50 ! Explicit interface for ODEPACK
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 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvC
70 ! C
71 ! Module name: MCHEM_TIME_MARCH C
72 ! Purpose: Called in time_march.f to do rxns calcs C
73 ! C
74 ! Author: Nan Xie Date: 02-Aug-04 C
75 ! Reviewer: Date: C
76 ! C
77 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^C
78  SUBROUTINE stiff_chem_solver(ODE_DT, iErr)
79 
80 ! External Module Procedures:
81 !---------------------------------------------------------------------//
82  use stiff_chem_maps, only : mapodetomfix
83  use stiff_chem_maps, only : mapmfixtoode
84 
85 ! Global Variables:
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
95  use functions
96 
97  implicit none
98 
99 ! Passed Variables:
100 !----------------------------------------------------------------------!
101 ! Time integral length.
102  DOUBLE PRECISION, intent(IN) :: ODE_DT
103 ! Error Flag
104  INTEGER, intent(OUT) :: iErr
105 
106 ! Local Variables:
107 !----------------------------------------------------------------------!
108 ! Error flag -> Integration failed in one or more fluid cells.
109  LOGICAL :: lErr_l ! local
110 
111 ! Fluid Cell Index
112  INTEGER :: IJK
113 ! The maximum number of ODEs to solve.
114  DOUBLE PRECISION, dimension(ODE_DIMN_all) :: ODE_VARS
115 
116 ! (1) :: Number of ODEs
117 ! (2) :: Fluid cell index (IJK) passed into ODEPACK
118 ! (:) :: Flag for solving solid phase M density and species equations.
119  INTEGER, dimension(NEQ_DIMN) :: lNEQ
120 ! Start time for integration
121  DOUBLE PRECISION :: lT
122 ! Stop time for integration
123  DOUBLE PRECISION :: lTOUT
124 ! Indicates type of Error control.
125  INTEGER :: lITOL
126 ! Relative error tolerance paramter.
127  DOUBLE PRECISION :: lRTOL(1)
128 ! Absolute error tolerance parameter. (Dimension (ODE_DIMN))
129  DOUBLE PRECISION :: lATOL(ode_dimn_all)
130 ! Index specifying the ODEPACK task.
131  INTEGER :: lITASK
132 ! Specifies the state of ODEPACK
133  INTEGER :: lISTATE
134 ! Flag indicating optional inputs are used.
135  INTEGER :: lIOPT
136 ! Array for REAL* work
137  DOUBLE PRECISION :: RWORK(ode_lrw)
138 ! Declared length of RWORK.
139  INTEGER :: lLRW
140 ! Array for Integer work
141  INTEGER :: IWORK(ode_liw)
142 ! Declared length of IWORK.
143  INTEGER :: lLIW
144 ! Jacobain Routine (not used)
145  DOUBLE PRECISION :: lJAC
146 ! Jacobian type indicator.
147  INTEGER :: lJT
148 
149 ! The number of attempts of a specific fluid cell.
150  INTEGER :: lAtps
151 
152  LOGICAL :: lReset
153  LOGICAL :: lIncpt
154 
155  lerr_l = .false.
156 
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 ! Forced restset of tolerance values.
168  lrtol = ode_rtol
169  latol = ode_atol
170 
171 ! Increment the attempts counter.
172  50 latps = latps + 1
173 
174 ! Forced restset to initial values.
175  lt = 0.0d0
176  ltout = ode_dt
177  litol = ode_itol
178  llrw = ode_lrw
179  lliw = ode_liw
180  ljt = ode_jt
181 
182 ! Fixed parameters
183  litask = 1
184  listate = 1
185  liopt = 1
186 
187 ! Calculate the number of ODEs to solve.
188  CALL calc_ode_coeff(lneq, ijk)
189 
190 ! Clear the work arrays.
191  iwork = 0
192  rwork = zero
193 
194 ! The maximum number of internal steps ODEPACK may use to integrate over
195 ! the time interval. The default value is 500.
196  iwork(6) = stiff_chem_max_steps
197 
198  IF(calc_reactions(ijk)) THEN
199 
200 ! Map MFIX variables to ODE variables.
201  CALL mapmfixtoode(neq_dimn, lneq, ode_dimn_all, ode_vars)
202 
203 ! Store a copy of the original field variables. This allows for these
204 ! values to be 'reset' in the event that the stiff solver fails.
205  CALL update_ode_old(ode_dimn_all, ode_vars)
206 
207 ! Clear the error flag.
208  100 ierr = 0
209 
210 ! Integrate flow field variables to incorporate reactions.
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 ! Verify that the results are well defined.
216  CALL check_ode_data(neq_dimn, lneq, ode_dimn_all, &
217  ode_vars, unlimited_steps, listate, ierr)
218 
219 ! Successfully Integrated ODEs.
220  IF(ierr == 0) THEN
221  lreset = .false.
222 ! Additional integration steps are needed (lT < lTOUT).
223  ELSEIF(ierr == -1) THEN
224 ! Reste the state flag and keep integrating.
225  IF(unlimited_steps) THEN
226  listate = 2
227  goto 100
228  ELSE
229  lreset = .false.
230  lincpt = .true.
231  ENDIF
232 
233 ! Too much accuracy was requested.
234  ELSEIF(ierr == -2) THEN
235  IF(latps < 3) THEN
236 ! Write to the error log file.
237  IF(ode_debug_level >= 2) CALL write_ode_log(ierr, &
238  neq_dimn, lneq, ode_dimn_all, ode_vars)
239 ! Reset the ODE variable array.
240  CALL reset_ode(ode_dimn_all, ode_vars, latps)
241 ! Reset the field variables.
242  CALL mapodetomfix(neq_dimn, lneq, &
243  ode_dimn_all, ode_vars)
244 ! Loosen the convergence criteria and try again.
245  lrtol = ode_rtol*10.0d0
246  latol = ode_atol*10.0d0
247  goto 50
248  ELSE
249 ! Write to the error log file.
250  IF(ode_debug_level >= 1) CALL write_ode_log(ierr, &
251  neq_dimn, lneq, ode_dimn_all, ode_vars)
252 ! Set the flag to reset the field variables to the initial values.
253  lreset = .true.
254  ENDIF
255 ! All other errors.
256  ELSE
257 ! Tighten the convergence criteria and try again.
258  IF(latps < 3) THEN
259 ! Write to the error log file.
260  IF(ode_debug_level >= 2) CALL write_ode_log(ierr, &
261  neq_dimn, lneq, ode_dimn_all, ode_vars)
262 ! Reset the ODE variable array.
263  CALL reset_ode(ode_dimn_all, ode_vars, latps)
264 ! Rest the filed variables to their original values.
265  CALL mapodetomfix(neq_dimn, lneq, &
266  ode_dimn_all, ode_vars)
267 ! Reduce the tolerances and try again.
268  lrtol = ode_rtol/(10.0d0**latps)
269  latol = ode_atol/(10.0d0**latps)
270  goto 50
271  ELSE
272 ! Write to the error log file.
273  IF(ode_debug_level >= 1) CALL write_ode_log(ierr, &
274  neq_dimn, lneq, ode_dimn_all, ode_vars)
275 ! Set the flag to reset the field variables to the initial values.
276  lreset = .true.
277  ENDIF
278 
279  ENDIF ! IF(iErr == 0)
280 
281 ! Reset the field variables.
282  if(lreset) CALL reset_ode(ode_dimn_all, ode_vars, latps)
283 ! Store the results in the field variables.
284  CALL mapodetomfix(neq_dimn, lneq, ode_dimn_all, ode_vars)
285 ! Collect solver stats.
286  IF(full_log) CALL update_stiff_chem_stats(lneq, &
287  neq_dimn, iwork(11), ode_dimn_all, latps, lincpt)
288 
289 
290  ENDIF ! EndIF CALC_REACTIONS
291  ENDIF ! IF(CALC_REACTIONS(IJK))
292  END DO ijk_lp ! End Loop over fluiod Cells, IJK
293 
294 ! gErr_l = .FALSE.
295 ! CALL GLOBAL_ALL_OR(lErr_l, gErr_l)
296 ! IF(gErr_l) CALL WRITE_VTU_FILE
297 
298 
299  CALL finalize_stiff_solver()
300 
302 
303  ierr = 0
304 
305  RETURN
306  END SUBROUTINE stiff_chem_solver
307 
308 
309 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
310 ! !
311 ! Module name: CALC_REACTIONS !
312 ! !
313 ! Purpose: !
314 ! !
315 ! Author: J.Musser Date: 07-Feb-13 !
316 ! !
317 ! Comments: !
318 ! !
319 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
320  LOGICAL FUNCTION calc_reactions(IJK)
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 ! Initialize
333  rates = 0.0d0
334 
335 ! Calculate user defined reaction rates.
336  CALL usr_rates(ijk, rates)
337 
338 ! If there is little to no reaction in the cell, then set the ODE
339 ! Time to zero to avoid calling the stiff solver.
340  calc_reactions = .true.
341  if(maxval(rates) < rlimit) calc_reactions = .false.
342 
343 
344  RETURN
345  END FUNCTION calc_reactions
346 
347 
348 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
349 ! !
350 ! Module name: CALC_DIMN_ODE !
351 ! !
352 ! Purpose: !
353 ! !
354 ! Author: J.Musser Date: 07-Feb-13 !
355 ! !
356 ! Comments: !
357 ! !
358 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
359  SUBROUTINE calc_ode_coeff(lNEQ, IJK)
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 ! Initialize.
375  use_solids_odes = .false.
376  lneq(2) = ijk
377  lneq(3:) = 0
378 
379 ! If there is little to no solids in the cell, then set the ODE
380 ! dimension to gas phase only.
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 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv!
403 ! !
404 ! Module name: FINALIZE_STIFF_SOLVER !
405 ! !
406 ! Purpose: !
407 ! !
408 ! Author: J.Musser Date: 07-Feb-13 !
409 ! !
410 ! Comments: !
411 ! !
412 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
413  SUBROUTINE finalize_stiff_solver
415 ! Gas phase volume fraction
416  use fldvar, only : ep_g
417 ! Gas phase denisty
418  use fldvar, only: ro_g, rop_g
419 ! Gas phase pressure
420  use fldvar, only: p_g
421 ! Gas phase temperature
422  use fldvar, only: t_g
423 ! Gas phase species mass fraction
424  use fldvar, only: x_g
425 ! Molecular weight of each gas phase species
426  use physprop, only : mw_g
427 ! Gas phase mixture molecular weight.
428  use physprop, only : mw_mix_g
429 
430 ! Solids phase bulk density
431  use fldvar, only: rop_s
432 ! Solids phase temperature
433  use fldvar, only: t_s
434 ! Solids phase species mass fractions
435  use fldvar, only: x_s
436 
437 ! Number of solids phases
438  use physprop, only: mmax
439 ! Number of species in each phase.
440  use physprop, only: nmax
441 
442 ! Double precision: ONE = 1.0d0
443  use param1, only: one
444 ! Universal gas constant
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 ! Local loop indicies.
456  INTEGER :: IJK ! Fluid Cell index.
457  INTEGER :: M ! Solids phase index
458  INTEGER :: NN ! Species index
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 ! Solids temperature.
472  CALL send_recv(t_s(:,m),2)
473 ! Solids volume fraction. (Constant Solids Density)
474  CALL send_recv(rop_s(:,m),2)
475 ! Solids phase species mass fractions.
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 ! Calculate the mixture molecular weight.
485  mw_mix_g(ijk) = sum(x_g(ijk,1:nmax(0))/mw_g(1:nmax(0)))
486  mw_mix_g(ijk) = one/mw_mix_g(ijk)
487 ! Calculate the gas phase pressure.
488  p_g(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
subroutine, public write_ode_log(lErr, lnD, lNEQ, loD, lVARS)
integer ijkend3
Definition: compar_mod.f:80
double precision, dimension(:), allocatable ep_g
Definition: fldvar_mod.f:15
integer stiff_chem_max_steps
integer neq_dimn
double precision, parameter one
Definition: param1_mod.f:29
integer ode_liw
integer ode_itol
subroutine dlsoda(F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK, ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, JT)
Definition: ODEPACK.F:3738
logical, external compare
Definition: stiff_chem_mod.f:9
Definition: rxns_mod.f:1
logical, dimension(0:dim_m) species_eq
Definition: run_mod.f:115
double precision, dimension(:), allocatable t_g
Definition: fldvar_mod.f:63
double precision gas_const
Definition: constant_mod.f:152
subroutine, public mapodetomfix(lnD, lNEQ, loD, lVars)
double precision, dimension(:), allocatable p_g
Definition: fldvar_mod.f:26
subroutine usr_rates(IJK, RATES)
Definition: usr_rates.f:37
logical full_log
Definition: output_mod.f:31
subroutine, public check_ode_data(lnD, lNEQ, loD, VARS, lUNLIMITED, lState, lErr)
double precision, dimension(dim_n_g) mw_g
Definition: physprop_mod.f:124
subroutine, public write_stiff_chem_stats
subroutine, public update_stiff_chem_stats(lNEQ, lNEQ_DIMN, lNST, lODE_DIMN, lAtps, lIncpt)
double precision, dimension(1) ode_rtol
subroutine finalize_stiff_solver
subroutine, public update_ode_old(lODE_DIMN, lODE_VARS)
external stiff_chem_rrates
Definition: stiff_chem_mod.f:7
subroutine, public mapmfixtoode(lnD, lNEQ, loD, lVars)
integer, public ode_debug_level
double precision, external calc_h0
integer mmax
Definition: physprop_mod.f:19
double precision, dimension(:,:,:), allocatable x_s
Definition: fldvar_mod.f:78
double precision, dimension(:,:), allocatable t_s
Definition: fldvar_mod.f:66
double precision, dimension(:,:), allocatable x_g
Definition: fldvar_mod.f:75
subroutine calc_ode_coeff(lNEQ, IJK)
double precision function f(POS, ALPHAC, D_Target, L, N)
integer no_of_rxns
Definition: rxns_mod.f:41
integer ode_lrw
integer ode_jt
integer ode_dimn_g
Definition: run_mod.f:13
double precision, dimension(:), allocatable ode_atol
subroutine, public init_stiff_chem_stats
double precision, dimension(:), allocatable mw_mix_g
Definition: physprop_mod.f:130
integer, dimension(0:dim_m) nmax
Definition: physprop_mod.f:119
integer ijkstart3
Definition: compar_mod.f:80
subroutine stiff_chem_solver(ODE_DT, iErr)
double precision function ep_s(IJK, xxM)
Definition: fldvar_mod.f:178
subroutine, public reset_ode(lDIMN, lVARS, lAtps)
subroutine bound_x(ARRAY, IJKMAX2)
double precision, dimension(:,:), allocatable rop_s
Definition: fldvar_mod.f:51
logical unlimited_steps
integer ode_dimn_all
logical, dimension(:), allocatable notowner
double precision time
Definition: run_mod.f:45
logical stiff_chemistry
double precision, dimension(:), allocatable ro_g
Definition: fldvar_mod.f:32
double precision, dimension(:), allocatable rop_g
Definition: fldvar_mod.f:38
logical function calc_reactions(IJK)
double precision, parameter zero
Definition: param1_mod.f:27