MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_rd_phys.t
Go to the documentation of this file.
1 !> Reaction-diffusion module (physics routines)
2 !>
3 !> Multiple reaction-diffusion systems are included: the Gray-Scott model, the
4 !> Schnakenberg model, the Brusselator model, the diffusive logistic equation,
5 !> an analytical testcase from "Numerical solution of time-dependent advection-
6 !> diffusion-reaction equations" by Hundsdorfer & Verwer, the Oregonator model,
7 !> the extended Brusselator model, and the diffusive Lorenz system. See the
8 !> documentation of the reaction-diffusion module for more information.
9 !>
10 !> IMEX methods are also supported. The implicit system is solved by a
11 !> multigrid solver coupled into MPI-AMRVAC.
12 !>
15 
16  implicit none
17  private
18 
19  integer, protected, public :: u_ = 1
20  integer, protected, public :: v_ = 2 !< For 2 or more equations
21  integer, protected, public :: w_ = 3 !< For 3 or more equations
22 
23  !> Whether particles module is added
24  logical, public, protected :: rd_particles = .false.
25 
26  !> Parameter with which to multiply the reaction timestep restriction
27  double precision, public, protected :: dtreacpar = 0.5d0
28 
29  !> Name of the system to be solved
30  character(len=20), public, protected :: equation_name = "gray-scott"
31  integer :: number_of_species = 2
32  integer :: equation_type = 1
33  integer, parameter :: eq_gray_scott = 1
34  integer, parameter :: eq_schnakenberg = 2
35  integer, parameter :: eq_brusselator = 3
36  integer, parameter :: eq_logistic = 4
37  integer, parameter :: eq_analyt_hunds = 5
38  integer, parameter :: eq_belousov_fn = 6 ! Field-Noyes model, or Oregonator
39  integer, parameter :: eq_ext_brusselator = 7
40  integer, parameter :: eq_lorenz = 8
41 
42  !> Diffusion coefficient for first species (u)
43  double precision, public, protected :: d1 = 0.05d0
44  !> Diffusion coefficient for second species (v) (if applicable)
45  double precision, public, protected :: d2 = 1.0d0
46  !> Diffusion coefficient for third species (w) (if applicable)
47  double precision, public, protected :: d3 = 1.0d0
48 
49  !> Parameter for Schnakenberg model
50  double precision, public, protected :: sb_alpha = 0.1305d0
51  !> Parameter for Schnakenberg model
52  double precision, public, protected :: sb_beta = 0.7695d0
53  !> Parameter for Schnakenberg model
54  double precision, public, protected :: sb_kappa = 100.0d0
55 
56  !> Feed rate for Gray-Scott model
57  double precision, public, protected :: gs_f = 0.046d0
58  !> Kill rate for Gray-Scott model
59  double precision, public, protected :: gs_k = 0.063d0
60 
61  !> Parameter for Brusselator model
62  double precision, public, protected :: br_a = 4.5d0
63  !> Parameter for Brusselator model
64  double precision, public, protected :: br_b = 8.0d0
65  !> Parameter for extended Brusselator model
66  double precision, public, protected :: br_c = 1.0d0
67  !> Parameter for extended Brusselator model
68  double precision, public, protected :: br_d = 1.0d0
69 
70  !> Parameter for logistic model (Fisher / KPP equation)
71  double precision, public, protected :: lg_lambda = 1.0d0
72 
73  !> Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction
74  double precision, public, protected :: bzfn_epsilon = 1.0d0
75  !> Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction
76  double precision, public, protected :: bzfn_delta = 1.0d0
77  !> Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction
78  double precision, public, protected :: bzfn_lambda = 1.0d0
79  !> Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction
80  double precision, public, protected :: bzfn_mu = 1.0d0
81 
82  !> Parameter for Lorenz system (Rayleigh number)
83  double precision, public, protected :: lor_r = 28.0d0
84  !> Parameter for Lorenz system (Prandtl number)
85  double precision, public, protected :: lor_sigma = 10.0d0
86  !> Parameter for Lorenz system (aspect ratio of the convection rolls)
87  double precision, public, protected :: lor_b = 8.0d0 / 3.0d0
88 
89  !> Whether to handle the explicitly handled source term in split fashion
90  logical :: rd_source_split = .false.
91 
92  !> Boundary condition information for the multigrid method
93  type(mg_bc_t), public :: rd_mg_bc(3, mg_num_neighbors)
94 
95  ! Public methods
96  public :: rd_phys_init
97 
98 contains
99 
100  subroutine rd_params_read(files)
101  use mod_global_parameters, only: unitpar
102  character(len=*), intent(in) :: files(:)
103  integer :: n
104 
105  namelist /rd_list/ d1, d2, d3, sb_alpha, sb_beta, sb_kappa, gs_f, gs_k, &
108  equation_name, rd_particles, rd_source_split, dtreacpar
109 
110  do n = 1, size(files)
111  open(unitpar, file=trim(files(n)), status='old')
112  read(unitpar, rd_list, end=111)
113 111 close(unitpar)
114  end do
115 
116  select case (equation_name)
117  case ("gray-scott")
118  equation_type = eq_gray_scott
119  number_of_species = 2
120  case ("schnakenberg")
121  equation_type = eq_schnakenberg
122  number_of_species = 2
123  case ("brusselator")
124  equation_type = eq_brusselator
125  number_of_species = 2
126  case ("logistic")
127  equation_type = eq_logistic
128  number_of_species = 1
129  case ("analyt_hunds")
130  equation_type = eq_analyt_hunds
131  number_of_species = 1
132  case ("belousov_fieldnoyes")
133  equation_type = eq_belousov_fn
134  number_of_species = 3
135  case ("ext_brusselator")
136  equation_type = eq_ext_brusselator
137  number_of_species = 3
138  case ("lorenz")
139  equation_type = eq_lorenz
140  number_of_species = 3
141  case default
142  call mpistop("Unknown equation_name (valid: gray-scott, schnakenberg, ...)")
143  end select
144 
145  end subroutine rd_params_read
146 
147  !> Write this module's parameters to a snapshot
148  subroutine rd_write_info(fh)
150  integer, intent(in) :: fh
151  integer, parameter :: n_par = 0
152  integer, dimension(MPI_STATUS_SIZE) :: st
153  integer :: er
154  integer :: idim
155 
156  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
157  end subroutine rd_write_info
158 
159  subroutine rd_phys_init()
161  use mod_physics
163  use mod_particles, only: particles_init
164 
165  call rd_params_read(par_files)
166 
167  physics_type = "rd"
168  phys_energy = .false.
169  phys_req_diagonal = .false.
171 
172  allocate(start_indices(number_species),stop_indices(number_species))
173  ! set the index of the first flux variable for species 1
174  start_indices(1)=1
175  ! Use the first variable as a density
176  u_ = var_set_fluxvar("u", "u")
177  if (number_of_species >= 2) then
178  v_ = var_set_fluxvar("v", "v")
179  end if
180  if (number_of_species >= 3) then
181  w_ = var_set_fluxvar("w", "w")
182  end if
183 
184  ! set number of variables which need update ghostcells
185  nwgc=nwflux
186 
187  ! set the index of the last flux variable for species 1
188  stop_indices(1)=nwflux
189 
190  ! Disable flux conservation near AMR boundaries, since we have no fluxes
191  fix_conserve_global = .false.
192 
204 
205  ! Initialize particles module
206  if (rd_particles) then
207  call particles_init()
208  phys_req_diagonal = .true.
209  end if
210 
211  end subroutine rd_phys_init
212 
213  subroutine rd_check_params
215  integer :: n, i, iw, species_list(number_of_species)
216 
217  if (any(flux_method /= fs_source)) then
218  ! there are no fluxes, only source terms in reaction-diffusion
219  call mpistop("mod_rd requires flux_scheme = source")
220  end if
221 
222  if (use_imex_scheme) then
223  use_multigrid = .true.
224  select case(number_of_species)
225  case(1); species_list = [u_]
226  case(2); species_list = [u_, v_]
227  case(3); species_list = [u_, v_, w_]
228  end select
229 
230  do i = 1, number_of_species
231  iw = species_list(i)
232 
233  ! Set boundary conditions for the multigrid solver
234  do n = 1, 2*ndim
235  select case (typeboundary(iw, n))
236  case (bc_symm)
237  ! d/dx u = 0
238  rd_mg_bc(i, n)%bc_type = mg_bc_neumann
239  rd_mg_bc(i, n)%bc_value = 0.0_dp
240  case (bc_asymm)
241  ! u = 0
242  rd_mg_bc(i, n)%bc_type = mg_bc_dirichlet
243  rd_mg_bc(i, n)%bc_value = 0.0_dp
244  case (bc_cont)
245  ! d/dx u = 0
246  rd_mg_bc(i, n)%bc_type = mg_bc_neumann
247  rd_mg_bc(i, n)%bc_value = 0.0_dp
248  case (bc_periodic)
249  ! Nothing to do here
250  case (bc_special)
251  if (.not. associated(rd_mg_bc(i, n)%boundary_cond)) then
252  write(*, "(A,I0,A,I0,A)") "typeboundary(", iw, ",", n, &
253  ") is 'special', but the corresponding method " // &
254  "rd_mg_bc(i, n)%boundary_cond is not set"
255  call mpistop("rd_mg_bc(i, n)%boundary_cond not set")
256  end if
257  case default
258  write(*,*) "rd_check_params warning: unknown boundary type"
259  rd_mg_bc(i, n)%bc_type = mg_bc_dirichlet
260  rd_mg_bc(i, n)%bc_value = 0.0_dp
261  end select
262  end do
263  end do
264  end if
265 
266  end subroutine rd_check_params
267 
268  subroutine rd_to_conserved(ixI^L, ixO^L, w, x)
270  integer, intent(in) :: ixI^L, ixO^L
271  double precision, intent(inout) :: w(ixI^S, nw)
272  double precision, intent(in) :: x(ixI^S, 1:^ND)
273 
274  ! Do nothing (primitive and conservative are equal for rd module)
275  end subroutine rd_to_conserved
276 
277  subroutine rd_to_primitive(ixI^L, ixO^L, w, x)
279  integer, intent(in) :: ixI^L, ixO^L
280  double precision, intent(inout) :: w(ixI^S, nw)
281  double precision, intent(in) :: x(ixI^S, 1:^ND)
282 
283  ! Do nothing (primitive and conservative are equal for rd module)
284  end subroutine rd_to_primitive
285 
286  subroutine rd_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
288  integer, intent(in) :: ixI^L, ixO^L, idim
289  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:^ND)
290  double precision, intent(inout) :: cmax(ixI^S)
291 
292  cmax(ixo^s) = 0.0d0
293  end subroutine rd_get_cmax
294 
295  subroutine rd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed, cmax, cmin)
297  use mod_variables
298  integer, intent(in) :: ixI^L, ixO^L, idim
299  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S,nw)
300  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S,nw)
301  double precision, intent(in) :: x(ixI^S, 1:^ND)
302  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
303  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
304  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
305 
306  if (present(cmin)) then
307  cmin(ixo^s,1) = 0.0d0
308  cmax(ixo^s,1) = 0.0d0
309  else
310  cmax(ixo^s,1) = 0.0d0
311  end if
312 
313  end subroutine rd_get_cbounds
314 
315  subroutine rd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
317  integer, intent(in) :: ixI^L, ixO^L
318  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
319  double precision, intent(in) :: w(ixI^S, 1:nw)
320  double precision, intent(inout) :: dtnew
321  double precision :: maxrate
322  double precision :: maxD
323 
324  ! dt < dx^2 / (2 * ndim * diffusion_coeff)
325  ! use dtdiffpar < 1 for explicit and > 1 for imex/split
326  maxd = d1
327  if (number_of_species >= 2) then
328  maxd = max(maxd, d2)
329  end if
330  if (number_of_species >= 3) then
331  maxd = max(maxd, d3)
332  end if
333  dtnew = dtdiffpar * minval([ dx^d ])**2 / (2 * ndim * maxd)
334 
335  ! Estimate time step for reactions
336  select case (equation_type)
337  case (eq_gray_scott)
338  maxrate = max(maxval(w(ixo^s, v_))**2 + gs_f, &
339  maxval(w(ixo^s, v_) * w(ixo^s, u_)) - gs_f - gs_k)
340  case (eq_schnakenberg)
341  maxrate = max(maxval(abs(w(ixo^s, v_) * w(ixo^s, u_) - 1)), &
342  maxval(w(ixo^s, u_))**2)
343  case (eq_brusselator)
344  maxrate = max( maxval(w(ixo^s, u_)*w(ixo^s, v_) - (br_b+1)), &
345  maxval(w(ixo^s, u_)**2) )
346  case (eq_ext_brusselator)
347  maxrate = max( maxval(w(ixo^s, u_)*w(ixo^s, v_) - (br_b+1)) + br_c, &
348  maxval(w(ixo^s, u_)**2) )
349  maxrate = max(maxrate, br_d)
350  case (eq_logistic)
351  maxrate = lg_lambda*maxval(abs(1 - w(ixo^s, u_))) ! abs for safety, normally u < 1
352  case (eq_analyt_hunds)
353  maxrate = maxval(w(ixo^s, u_)*abs(1 - w(ixo^s, u_))) / d1
354  case (eq_belousov_fn)
355  maxrate = max(&
356  maxval(abs(1.0d0 - w(ixo^s, w_) - w(ixo^s, u_))) / bzfn_epsilon, &
357  maxval(bzfn_lambda + w(ixo^s, u_)) / bzfn_delta &
358  )
359  case (eq_lorenz)
360  ! det(J) = sigma(b(r-1) + x*(x*+y*))
361  maxrate = max(lor_sigma, 1.0d0, lor_b)
362  case default
363  maxrate = one
364  call mpistop("Unknown equation type")
365  end select
366 
367  dtnew = min(dtnew, dtreacpar / maxrate)
368 
369  end subroutine rd_get_dt
370 
371  ! There is nothing to add to the transport flux in the transport equation
372  subroutine rd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
374  integer, intent(in) :: ixI^L, ixO^L, idim
375  double precision, intent(in) :: wC(ixI^S, 1:nw)
376  double precision, intent(in) :: w(ixI^S, 1:nw)
377  double precision, intent(in) :: x(ixI^S, 1:^ND)
378  double precision, intent(out) :: f(ixI^S, nwflux)
379 
380  f(ixo^s, :) = 0.0d0
381  end subroutine rd_get_flux
382 
383  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
384  subroutine rd_add_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active,wCTprim)
386  integer, intent(in) :: ixI^L, ixO^L
387  double precision, intent(in) :: qdt
388  double precision, intent(in) :: wCT(ixI^S, 1:nw), x(ixI^S, 1:ndim)
389  double precision, intent(inout) :: w(ixI^S, 1:nw)
390  double precision :: lpl_u(ixO^S), lpl_v(ixO^S), lpl_w(ixO^S)
391  logical, intent(in) :: qsourcesplit
392  logical, intent(inout) :: active
393  double precision, intent(in), optional :: wCTprim(ixI^S, 1:nw)
394 
395  ! here we add the reaction terms (always) and the diffusion if no imex is used
396  if (qsourcesplit .eqv. rd_source_split) then
397  if (.not.use_imex_scheme) then
398  call rd_laplacian(ixi^l, ixo^l, wct(ixi^s, u_), lpl_u)
399  if (number_of_species >= 2) then
400  call rd_laplacian(ixi^l, ixo^l, wct(ixi^s, v_), lpl_v)
401  end if
402  if (number_of_species >= 3) then
403  call rd_laplacian(ixi^l, ixo^l, wct(ixi^s, w_), lpl_w)
404  end if
405  else
406  ! for all IMEX scheme variants: only add the reactions
407  lpl_u = 0.0d0
408  lpl_v = 0.0d0
409  lpl_w = 0.0d0
410  end if
411 
412  select case (equation_type)
413  case (eq_gray_scott)
414  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u - &
415  wct(ixo^s, u_) * wct(ixo^s, v_)**2 + &
416  gs_f * (1 - wct(ixo^s, u_)))
417  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v + &
418  wct(ixo^s, u_) * wct(ixo^s, v_)**2 - &
419  (gs_f + gs_k) * wct(ixo^s, v_))
420  case (eq_schnakenberg)
421  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
422  + sb_kappa * (sb_alpha - wct(ixo^s, u_) + &
423  wct(ixo^s, u_)**2 * wct(ixo^s, v_)))
424  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
425  + sb_kappa * (sb_beta - wct(ixo^s, u_)**2 * wct(ixo^s, v_)))
426  case (eq_brusselator)
427  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
428  + br_a - (br_b + 1) * wct(ixo^s, u_) &
429  + wct(ixo^s, u_)**2 * wct(ixo^s, v_))
430  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
431  + br_b * wct(ixo^s, u_) - wct(ixo^s, u_)**2 * wct(ixo^s, v_))
432  case (eq_ext_brusselator)
433  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
434  + br_a - (br_b + 1) * wct(ixo^s, u_) &
435  + wct(ixo^s, u_)**2 * wct(ixo^s, v_) &
436  - br_c * wct(ixo^s, u_) + br_d * w(ixo^s, w_))
437  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
438  + br_b * wct(ixo^s, u_) &
439  - wct(ixo^s, u_)**2 * wct(ixo^s, v_))
440  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
441  + br_c * wct(ixo^s, u_) - br_d * w(ixo^s, w_))
442  case (eq_logistic)
443  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
444  + lg_lambda * w(ixo^s, u_) * (1 - w(ixo^s, u_)))
445  case (eq_analyt_hunds)
446  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
447  + 1.0d0/d1 * w(ixo^s, u_)**2 * (1 - w(ixo^s, u_)))
448  case (eq_belousov_fn)
449  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
450  + 1.0d0/bzfn_epsilon * (bzfn_lambda * wct(ixo^s, u_) &
451  - wct(ixo^s, u_)*wct(ixo^s, w_) + wct(ixo^s, u_) &
452  - wct(ixo^s, u_)**2))
453  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
454  + wct(ixo^s, u_) - wct(ixo^s, v_))
455  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
456  + 1.0d0/bzfn_delta * (-bzfn_lambda * wct(ixo^s, w_) &
457  - wct(ixo^s, u_)*wct(ixo^s, w_) + bzfn_mu * wct(ixo^s, v_)))
458  case (eq_lorenz)
459  ! xdot = sigma.(y-x)
460  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
461  + lor_sigma * (wct(ixo^s, v_) - wct(ixo^s, u_)))
462  ! ydot = r.x - y - x.z
463  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
464  + lor_r * wct(ixo^s, u_) - wct(ixo^s, v_) &
465  - wct(ixo^s, u_)*wct(ixo^s, w_))
466  ! zdot = x.y - b.z
467  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
468  + wct(ixo^s, u_)*wct(ixo^s, v_) - lor_b * wct(ixo^s, w_))
469  case default
470  call mpistop("Unknown equation type")
471  end select
472 
473  ! enforce getbc call after source addition
474  active = .true.
475  end if
476 
477  end subroutine rd_add_source
478 
479  !> Compute the Laplacian using a standard second order scheme. For now this
480  !> method only works in slab geometries. Requires one ghost cell only.
481  subroutine rd_laplacian(ixI^L,ixO^L,var,lpl)
483  integer, intent(in) :: ixI^L, ixO^L
484  double precision, intent(in) :: var(ixI^S)
485  double precision, intent(out) :: lpl(ixO^S)
486  integer :: idir, jxO^L, hxO^L
487  double precision :: h_inv2
488 
489  if (slab) then
490  lpl(ixo^s) = 0.0d0
491  do idir = 1, ndim
492  hxo^l=ixo^l-kr(idir,^d);
493  jxo^l=ixo^l+kr(idir,^d);
494  h_inv2 = 1/dxlevel(idir)**2
495  lpl(ixo^s) = lpl(ixo^s) + h_inv2 * &
496  (var(jxo^s) - 2 * var(ixo^s) + var(hxo^s))
497  end do
498  else
499  call mpistop("rd_laplacian not implemented in this geometry")
500  end if
501 
502  end subroutine rd_laplacian
503 
504  subroutine put_laplacians_onegrid(ixI^L,ixO^L,w)
506  integer, intent(in) :: ixI^L, ixO^L
507  double precision, intent(inout) :: w(ixI^S, 1:nw)
508 
509  double precision :: lpl_u(ixO^S), lpl_v(ixO^S), lpl_w(ixO^S)
510 
511  call rd_laplacian(ixi^l, ixo^l, w(ixi^s, u_), lpl_u)
512  if (number_of_species >= 2) then
513  call rd_laplacian(ixi^l, ixo^l, w(ixi^s, v_), lpl_v)
514  end if
515  if (number_of_species >= 3) then
516  call rd_laplacian(ixi^l, ixo^l, w(ixi^s, w_), lpl_w)
517  end if
518 
519  w(ixo^s,u_) = d1*lpl_u
520  if (number_of_species >= 2) then
521  w(ixo^s,v_) = d2*lpl_v
522  end if
523  if (number_of_species >= 3) then
524  w(ixo^s,w_) = d3*lpl_w
525  end if
526 
527  end subroutine put_laplacians_onegrid
528 
529  !> inplace update of psa==>F_im(psa)
530  subroutine rd_evaluate_implicit(qtC,psa)
532  type(state), target :: psa(max_blocks)
533  double precision, intent(in) :: qtC
534 
535  integer :: iigrid, igrid, level
536  integer :: ixO^L
537 
538  !ixO^L=ixG^LL^LSUB1;
539  ixo^l=ixm^ll;
540  !$OMP PARALLEL DO PRIVATE(igrid)
541  do iigrid=1,igridstail; igrid=igrids(iigrid);
542  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
543  call put_laplacians_onegrid(ixg^ll,ixo^l,psa(igrid)%w)
544  end do
545  !$OMP END PARALLEL DO
546 
547  end subroutine rd_evaluate_implicit
548 
549  !> Implicit solve of psa=psb+dtfactor*dt*F_im(psa)
550  subroutine rd_implicit_update(dtfactor,qdt,qtC,psa,psb)
552  use mod_forest
553 
554  type(state), target :: psa(max_blocks)
555  type(state), target :: psb(max_blocks)
556  double precision, intent(in) :: qdt
557  double precision, intent(in) :: qtC
558  double precision, intent(in) :: dtfactor
559 
560  integer :: n
561  double precision :: res, max_residual, lambda
562 
563  integer :: iw_to,iw_from
564  integer :: iigrid, igrid, id
565  integer :: nc, lvl
566  type(tree_node), pointer :: pnode
567  real(dp) :: fac
568 
569  ! Avoid setting a very restrictive limit to the residual when the time step
570  ! is small (as the operator is ~ 1/(D * qdt))
571  if (qdt < dtmin) then
572  if(mype==0)then
573  print *,'skipping implicit solve: dt too small!'
574  print *,'Currently at time=',global_time,' time step=',qdt,' dtmin=',dtmin
575  endif
576  return
577  endif
578  max_residual = 1d-7/qdt
579 
580  mg%operator_type = mg_helmholtz
581  call mg_set_methods(mg)
582 
583  if (.not. mg%is_allocated) call mpistop("multigrid tree not allocated yet")
584 
585  ! First handle the u variable ***************************************
586  lambda = 1/(dtfactor * qdt * d1)
587  call helmholtz_set_lambda(lambda)
588  mg%bc(:, mg_iphi) = rd_mg_bc(1, :)
589 
590  call mg_copy_to_tree(u_, mg_irhs, factor=-lambda, state_from=psb)
591  call mg_copy_to_tree(u_, mg_iphi, state_from=psb)
592 
593  call mg_fas_fmg(mg, .true., max_res=res)
594  do n = 1, 10
595  call mg_fas_vcycle(mg, max_res=res)
596  if (res < max_residual) exit
597  end do
598 
599  call mg_copy_from_tree_gc(mg_iphi, u_, state_to=psa)
600  ! Done with the u variable ***************************************
601 
602  ! Next handle the v variable ***************************************
603  if (number_of_species >= 2) then
604  lambda = 1/(dtfactor * qdt * d2)
605  call helmholtz_set_lambda(lambda)
606  mg%bc(:, mg_iphi) = rd_mg_bc(2, :)
607 
608  call mg_copy_to_tree(v_, mg_irhs, factor=-lambda, state_from=psb)
609  call mg_copy_to_tree(v_, mg_iphi, state_from=psb)
610 
611  call mg_fas_fmg(mg, .true., max_res=res)
612  do n = 1, 10
613  call mg_fas_vcycle(mg, max_res=res)
614  if (res < max_residual) exit
615  end do
616 
617  call mg_copy_from_tree_gc(mg_iphi, v_, state_to=psa)
618  end if
619  ! Done with the v variable ***************************************
620 
621  ! Next handle the w variable ***************************************
622  if (number_of_species >= 3) then
623  lambda = 1/(dtfactor * qdt * d3)
624  call helmholtz_set_lambda(lambda)
625 
626  call mg_copy_to_tree(w_, mg_irhs, factor=-lambda, state_from=psb)
627  call mg_copy_to_tree(w_, mg_iphi, state_from=psb)
628 
629  call mg_fas_fmg(mg, .true., max_res=res)
630  do n = 1, 10
631  call mg_fas_vcycle(mg, max_res=res)
632  if (res < max_residual) exit
633  end do
634 
635  call mg_copy_from_tree_gc(mg_iphi, w_, state_to=psa)
636  end if
637  ! Done with the w variable ***************************************
638 
639  end subroutine rd_implicit_update
640 
641 end module mod_rd_phys
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
Module with basic grid data structures.
Definition: mod_forest.t:2
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision dtdiffpar
For resistive MHD, the time step is also limited by the diffusion time: .
integer, parameter unitpar
file handle for IO
integer, parameter bc_asymm
double precision global_time
The global simulation time.
logical use_imex_scheme
whether IMEX in use or not
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical use_particles
Use particles module or not.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer mype
The rank of the current MPI task.
integer, dimension(:), allocatable, parameter d
integer ixm
the mesh range (within a block with ghost cells)
integer, dimension(:), allocatable flux_method
Which flux scheme of spatial discretization to use (per grid level)
logical slab
Cartesian geometry or not.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
integer, parameter bc_cont
integer, parameter bc_symm
logical fix_conserve_global
Whether to apply flux conservation at refinement boundaries.
logical use_multigrid
Use multigrid (only available in 2D and 3D)
double precision dtmin
Stop the simulation when the time step becomes smaller than this value.
integer, parameter fs_source
double precision, dimension(ndim) dxlevel
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
Module containing all the particle routines.
Definition: mod_particles.t:2
subroutine particles_init()
Initialize particle data and parameters.
Definition: mod_particles.t:15
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
procedure(sub_convert), pointer phys_to_primitive
Definition: mod_physics.t:59
procedure(sub_write_info), pointer phys_write_info
Definition: mod_physics.t:79
procedure(sub_get_flux), pointer phys_get_flux
Definition: mod_physics.t:66
procedure(sub_evaluate_implicit), pointer phys_evaluate_implicit
Definition: mod_physics.t:86
logical phys_req_diagonal
Whether the physics routines require diagonal ghost cells, for example for computing a curl.
Definition: mod_physics.t:27
procedure(sub_get_cbounds), pointer phys_get_cbounds
Definition: mod_physics.t:65
procedure(sub_get_dt), pointer phys_get_dt
Definition: mod_physics.t:69
procedure(sub_check_params), pointer phys_check_params
Definition: mod_physics.t:56
procedure(sub_convert), pointer phys_to_conserved
Definition: mod_physics.t:58
character(len=name_len) physics_type
String describing the physics type of the simulation.
Definition: mod_physics.t:19
procedure(sub_implicit_update), pointer phys_implicit_update
Definition: mod_physics.t:85
procedure(sub_add_source), pointer phys_add_source
Definition: mod_physics.t:71
procedure(sub_get_cmax), pointer phys_get_cmax
Definition: mod_physics.t:61
logical phys_energy
Solve energy equation or not.
Definition: mod_physics.t:30
Reaction-diffusion module (physics routines)
Definition: mod_rd_phys.t:13
subroutine rd_write_info(fh)
Write this module's parameters to a snapshot.
Definition: mod_rd_phys.t:149
double precision, public, protected gs_f
Feed rate for Gray-Scott model.
Definition: mod_rd_phys.t:57
double precision, public, protected lor_b
Parameter for Lorenz system (aspect ratio of the convection rolls)
Definition: mod_rd_phys.t:87
integer, public, protected u_
Definition: mod_rd_phys.t:19
double precision, public, protected bzfn_lambda
Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction.
Definition: mod_rd_phys.t:78
subroutine rd_add_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active, wCTprim)
Definition: mod_rd_phys.t:385
type(mg_bc_t), dimension(3, mg_num_neighbors), public rd_mg_bc
Boundary condition information for the multigrid method.
Definition: mod_rd_phys.t:93
subroutine, public rd_phys_init()
Definition: mod_rd_phys.t:160
subroutine rd_get_cmax(w, x, ixIL, ixOL, idim, cmax)
Definition: mod_rd_phys.t:287
double precision, public, protected d3
Diffusion coefficient for third species (w) (if applicable)
Definition: mod_rd_phys.t:47
logical, public, protected rd_particles
Whether particles module is added.
Definition: mod_rd_phys.t:24
double precision, public, protected sb_kappa
Parameter for Schnakenberg model.
Definition: mod_rd_phys.t:54
double precision, public, protected br_d
Parameter for extended Brusselator model.
Definition: mod_rd_phys.t:68
double precision, public, protected gs_k
Kill rate for Gray-Scott model.
Definition: mod_rd_phys.t:59
double precision, public, protected d2
Diffusion coefficient for second species (v) (if applicable)
Definition: mod_rd_phys.t:45
subroutine rd_evaluate_implicit(qtC, psa)
inplace update of psa==>F_im(psa)
Definition: mod_rd_phys.t:531
double precision, public, protected dtreacpar
Parameter with which to multiply the reaction timestep restriction.
Definition: mod_rd_phys.t:27
integer, public, protected w_
For 3 or more equations.
Definition: mod_rd_phys.t:21
subroutine rd_get_cbounds(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
Definition: mod_rd_phys.t:296
double precision, public, protected bzfn_epsilon
Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction.
Definition: mod_rd_phys.t:74
double precision, public, protected d1
Diffusion coefficient for first species (u)
Definition: mod_rd_phys.t:43
double precision, public, protected lg_lambda
Parameter for logistic model (Fisher / KPP equation)
Definition: mod_rd_phys.t:71
integer, public, protected v_
For 2 or more equations.
Definition: mod_rd_phys.t:20
double precision, public, protected sb_beta
Parameter for Schnakenberg model.
Definition: mod_rd_phys.t:52
subroutine rd_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_rd_phys.t:316
double precision, public, protected bzfn_mu
Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction.
Definition: mod_rd_phys.t:80
double precision, public, protected sb_alpha
Parameter for Schnakenberg model.
Definition: mod_rd_phys.t:50
subroutine rd_check_params
Definition: mod_rd_phys.t:214
subroutine rd_to_primitive(ixIL, ixOL, w, x)
Definition: mod_rd_phys.t:278
subroutine rd_implicit_update(dtfactor, qdt, qtC, psa, psb)
Implicit solve of psa=psb+dtfactor*dt*F_im(psa)
Definition: mod_rd_phys.t:551
double precision, public, protected bzfn_delta
Parameter for the Field-Noyes model of the Belousov-Zhabotinsky reaction.
Definition: mod_rd_phys.t:76
double precision, public, protected lor_r
Parameter for Lorenz system (Rayleigh number)
Definition: mod_rd_phys.t:83
subroutine put_laplacians_onegrid(ixIL, ixOL, w)
Definition: mod_rd_phys.t:505
subroutine rd_to_conserved(ixIL, ixOL, w, x)
Definition: mod_rd_phys.t:269
double precision, public, protected br_a
Parameter for Brusselator model.
Definition: mod_rd_phys.t:62
subroutine rd_laplacian(ixIL, ixOL, var, lpl)
Compute the Laplacian using a standard second order scheme. For now this method only works in slab ge...
Definition: mod_rd_phys.t:482
double precision, public, protected lor_sigma
Parameter for Lorenz system (Prandtl number)
Definition: mod_rd_phys.t:85
subroutine rd_get_flux(wC, w, x, ixIL, ixOL, idim, f)
Definition: mod_rd_phys.t:373
double precision, public, protected br_c
Parameter for extended Brusselator model.
Definition: mod_rd_phys.t:66
character(len=20), public, protected equation_name
Name of the system to be solved.
Definition: mod_rd_phys.t:30
double precision, public, protected br_b
Parameter for Brusselator model.
Definition: mod_rd_phys.t:64
The data structure that contains information about a tree node/grid block.
Definition: mod_forest.t:11