MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_ard_phys.t
Go to the documentation of this file.
1 !> Module containing the physics routines for advection-reaction-diffusion equations
2 !>
3 !> This module can be seen as an extension of the reaction-diffusion (rd) module
4 !> and includes the same reaction systems and more: the Gray-Scott model, the
5 !> Schnakenberg model, the Brusselator model, the diffusive logistic equation,
6 !> an analytical testcase from "Numerical solution of time-dependent advection-
7 !> diffusion-reaction equations" by Hundsdorfer & Verwer, the Oregonator model,
8 !> the extended Brusselator model, the diffusive Lorenz system and the advection-
9 !> diffusion equation. See the documentation of the advection-reaction-diffusion
10 !> module for more information.
11 !>
12 !> An advection term can be aplied to these systems of the form:
13 !> nabla( (A1/adv_pow) * u^(adv_pow) ) (for the first unknown)
14 !> nabla( (A2/adv_pow) * v^(adv_pow) ) (for the second unknown, if applicable)
15 !> nabla( (A3/adv_pow) * w^(adv_pow) ) (for the third unknown, if applicable)
16 !>
17 !> IMEX methods are also supported. The implicit system is solved by a
18 !> multigrid solver coupled into MPI-AMRVAC.
19 !>
22 
23  implicit none
24  private
25 
26  !> Indices of the unknowns
27  integer, protected, public :: u_ = 1
28  integer, protected, public :: v_ = 2 !< For 2 or more equations
29  integer, protected, public :: w_ = 3 !< For 3 or more equations
30 
31  !> Whether particles module is added
32  logical, public, protected :: ard_particles = .false.
33 
34  !> Parameter with which to multiply the reaction timestep restriction
35  double precision, public, protected :: dtreacpar = 0.5d0
36 
37  !> Name of the system to be solved
38  character(len=20), public, protected :: equation_name = "gray-scott"
39  integer :: number_of_species = 2
40  integer :: equation_type = 1
41  integer, parameter :: eq_gray_scott = 1 ! Gray-Scott model
42  integer, parameter :: eq_schnakenberg = 2 ! Schnakenberg model
43  integer, parameter :: eq_brusselator = 3 ! Brusselator model
44  integer, parameter :: eq_logistic = 4 ! Logistic equation
45  integer, parameter :: eq_analyt_hunds = 5
46  integer, parameter :: eq_belousov_fn = 6 ! Field-Noyes model, or Oregonator
47  integer, parameter :: eq_ext_brusselator = 7 ! Extended Brusselator
48  integer, parameter :: eq_lorenz = 8 ! Lorenz system
49  integer, parameter :: eq_no_reac = 9 ! Advection-diffusion equation
50 
51  !> Diffusion coefficient for first species (u)
52  double precision, public, protected :: d1 = 0.05d0
53  !> Diffusion coefficient for second species (v) (if applicable)
54  double precision, public, protected :: d2 = 1.0d0
55  !> Diffusion coefficient for third species (w) (if applicable)
56  double precision, public, protected :: d3 = 1.0d0
57 
58  !> Power of the unknown in the advection term (1 for linear)
59  integer, public, protected :: adv_pow = 1
60 
61  !> Advection coefficients for first species (u)
62  double precision, public, protected :: a1(^nd) = 0.0d0
63  !> Advection coefficients for second species (v) (if applicable)
64  double precision, public, protected :: a2(^nd) = 0.0d0
65  !> Advection coefficients for third species (w) (if applicable)
66  double precision, public, protected :: a3(^nd) = 0.0d0
67 
68  !> Parameters for Schnakenberg model
69  double precision, public, protected :: sb_alpha = 0.1305d0
70  double precision, public, protected :: sb_beta = 0.7695d0
71  double precision, public, protected :: sb_kappa = 100.0d0
72 
73  !> Feed rate for Gray-Scott model
74  double precision, public, protected :: gs_f = 0.046d0
75  !> Kill rate for Gray-Scott model
76  double precision, public, protected :: gs_k = 0.063d0
77 
78  !> Parameters for Brusselator model
79  double precision, public, protected :: br_a = 4.5d0
80  double precision, public, protected :: br_b = 8.0d0
81  double precision, public, protected :: br_c = 1.0d0
82  double precision, public, protected :: br_d = 1.0d0
83 
84  !> Parameter for logistic model (Fisher / KPP equation)
85  double precision, public, protected :: lg_lambda = 1.0d0
86 
87  !> Parameters for the Field-Noyes model of the Belousov-Zhabotinsky reaction
88  double precision, public, protected :: bzfn_epsilon = 1.0d0
89  double precision, public, protected :: bzfn_delta = 1.0d0
90  double precision, public, protected :: bzfn_lambda = 1.0d0
91  double precision, public, protected :: bzfn_mu = 1.0d0
92 
93  !> Parameter for Lorenz system (Rayleigh number)
94  double precision, public, protected :: lor_r = 28.0d0
95  !> Parameter for Lorenz system (Prandtl number)
96  double precision, public, protected :: lor_sigma = 10.0d0
97  !> Parameter for Lorenz system (aspect ratio of the convection rolls)
98  double precision, public, protected :: lor_b = 8.0d0 / 3.0d0
99 
100  !> Whether to handle the explicitly handled source term in split fashion
101  logical :: ard_source_split = .false.
102 
103  !> Boundary condition information for the multigrid method
104  type(mg_bc_t), public :: ard_mg_bc(3, mg_num_neighbors)
105 
106  ! Public methods
107  public :: ard_phys_init
108 
109 contains
110 
111  !> Read this module's parameters from a file
112  subroutine ard_params_read(files)
113  use mod_global_parameters, only: unitpar
114  character(len=*), intent(in) :: files(:)
115  integer :: n
116 
117  namelist /ard_list/ d1, d2, d3, adv_pow, a1, a2, a3, sb_alpha, sb_beta, sb_kappa, &
120  ard_source_split, dtreacpar
121 
122  do n = 1, size(files)
123  open(unitpar, file=trim(files(n)), status='old')
124  read(unitpar, ard_list, end=111)
125 111 close(unitpar)
126  end do
127 
128  !> Set the equation type and number of species
129  select case (equation_name)
130  case ("gray-scott")
131  equation_type = eq_gray_scott
132  number_of_species = 2
133  case ("schnakenberg")
134  equation_type = eq_schnakenberg
135  number_of_species = 2
136  case ("brusselator")
137  equation_type = eq_brusselator
138  number_of_species = 2
139  case ("logistic")
140  equation_type = eq_logistic
141  number_of_species = 1
142  case ("analyt_hunds")
143  equation_type = eq_analyt_hunds
144  number_of_species = 1
145  case ("belousov_fieldnoyes")
146  equation_type = eq_belousov_fn
147  number_of_species = 3
148  case ("ext_brusselator")
149  equation_type = eq_ext_brusselator
150  number_of_species = 3
151  case ("lorenz")
152  equation_type = eq_lorenz
153  number_of_species = 3
154  case ("no_reac")
155  equation_type = eq_no_reac
156  number_of_species = 1
157  case default
158  call mpistop("Unknown equation_name (valid: gray-scott, schnakenberg, ...)")
159  end select
160 
161  end subroutine ard_params_read
162 
163  !> Write this modules parameters to a snapshot
164  subroutine ard_write_info(fh)
166  integer, intent(in) :: fh
167  integer, parameter :: n_par = 0
168  integer, dimension(MPI_STATUS_SIZE) :: st
169  integer :: er
170  integer :: idim
171 
172  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
173  end subroutine ard_write_info
174 
175  subroutine ard_phys_init()
177  use mod_physics
179  use mod_particles, only: particles_init
180 
181  call ard_params_read(par_files)
182 
183  physics_type = "ard"
184  phys_energy = .false.
185  ! Whether diagonal ghost cells are required for the physics
186  phys_req_diagonal = .false.
188 
189  allocate(start_indices(number_species),stop_indices(number_species))
190  ! set the index of the first flux variable for species 1
191  start_indices(1)=1
192  ! Use the first variable as a density
193  u_ = var_set_fluxvar("u", "u")
194  if (number_of_species >= 2) then
195  v_ = var_set_fluxvar("v", "v")
196  end if
197  if (number_of_species >= 3) then
198  w_ = var_set_fluxvar("w", "w")
199  end if
200 
201  ! set number of variables which need update ghostcells
202  nwgc=nwflux
203  ! set the index of the last flux variable for species 1
204  stop_indices(1)=nwflux
205 
206  ! Check whether custom flux types have been defined
207  if (.not. allocated(flux_type)) then
208  allocate(flux_type(ndir, nw))
210  else if (any(shape(flux_type) /= [ndir, nw])) then
211  call mpistop("phys_check error: flux_type has wrong shape")
212  end if
213 
226 
227  ! Initialize particles module
228  if (ard_particles) then
229  call particles_init()
230  phys_req_diagonal = .true.
231  end if
232 
233  end subroutine ard_phys_init
234 
235  subroutine ard_check_params
237  integer :: n, i, iw, species_list(number_of_species)
238 
239  if (use_imex_scheme) then
240  use_multigrid = .true.
241  select case(number_of_species)
242  case(1)
243  species_list = [u_]
244  if (d1 == 0.0d0) then
245  write(*, *) "Diffusion coefficient cannot be zero in IMEX scheme"
246  call mpistop("Zero diffusion in IMEX scheme")
247  end if
248  case(2)
249  species_list = [u_, v_]
250  if ((d1 == 0.0d0) .or. (d2 == 0.0d0)) then
251  write(*, *) "Diffusion coefficient cannot be zero in IMEX scheme"
252  call mpistop("Zero diffusion in IMEX scheme")
253  end if
254  case(3)
255  species_list = [u_, v_, w_]
256  if ((d1 == 0.0d0) .or. (d2 == 0.0d0) .or. (d3 == 0.0d0)) then
257  write(*, *) "Diffusion coefficient cannot be zero in IMEX scheme"
258  call mpistop("Zero diffusion in IMEX scheme")
259  end if
260  end select
261 
262  do i = 1, number_of_species
263  iw = species_list(i)
264 
265  ! Set boundary conditions for the multigrid solver
266  do n = 1, 2*ndim
267  select case (typeboundary(iw, n))
268  case (bc_symm)
269  ! d/dx u = 0
270  ard_mg_bc(i, n)%bc_type = mg_bc_neumann
271  ard_mg_bc(i, n)%bc_value = 0.0_dp
272  case (bc_asymm)
273  ! u = 0
274  ard_mg_bc(i, n)%bc_type = mg_bc_dirichlet
275  ard_mg_bc(i, n)%bc_value = 0.0_dp
276  case (bc_cont)
277  ! d/dx u = 0
278  ard_mg_bc(i, n)%bc_type = mg_bc_neumann
279  ard_mg_bc(i, n)%bc_value = 0.0_dp
280  case (bc_periodic)
281  ! Nothing to do here
282  case (bc_special)
283  if (.not. associated(ard_mg_bc(i, n)%boundary_cond)) then
284  write(*, "(A,I0,A,I0,A)") "typeboundary(", iw, ",", n, &
285  ") is 'special', but the corresponding method " // &
286  "ard_mg_bc(i, n)%boundary_cond is not set"
287  call mpistop("ard_mg_bc(i, n)%boundary_cond not set")
288  end if
289  case default
290  write(*,*) "ard_check_params warning: unknown boundary type"
291  ard_mg_bc(i, n)%bc_type = mg_bc_dirichlet
292  ard_mg_bc(i, n)%bc_value = 0.0_dp
293  end select
294  end do
295  end do
296  end if
297 
298  end subroutine ard_check_params
299 
300  subroutine ard_to_conserved(ixI^L, ixO^L, w, x)
302  integer, intent(in) :: ixI^L, ixO^L
303  double precision, intent(inout) :: w(ixI^S, nw)
304  double precision, intent(in) :: x(ixI^S, 1:^ND)
305 
306  ! Do nothing (primitive and conservative are equal for ard module)
307  end subroutine ard_to_conserved
308 
309  subroutine ard_to_primitive(ixI^L, ixO^L, w, x)
311  integer, intent(in) :: ixI^L, ixO^L
312  double precision, intent(inout) :: w(ixI^S, nw)
313  double precision, intent(in) :: x(ixI^S, 1:^ND)
314 
315  ! Do nothing (primitive and conservative are equal for ard module)
316  end subroutine ard_to_primitive
317 
318  subroutine ard_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
320  integer, intent(in) :: ixI^L, ixO^L, idim
321  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:^ND)
322  double precision, intent(inout) :: cmax(ixI^S)
323 
324  cmax(ixo^s) = abs(a1(idim) * w(ixo^s,u_)**(adv_pow-1))
325  if (number_of_species >= 2) then
326  cmax(ixo^s) = max(cmax(ixo^s), abs(a2(idim) * w(ixo^s,v_)**(adv_pow-1)))
327  end if
328  if (number_of_species >= 3) then
329  cmax(ixo^s) = max(cmax(ixo^s), abs(a3(idim) * w(ixo^s,w_)**(adv_pow-1)))
330  end if
331 
332  end subroutine ard_get_cmax
333 
334  subroutine ard_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed, cmax, cmin)
336  use mod_variables
337  integer, intent(in) :: ixI^L, ixO^L, idim
338  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S,nw)
339  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S,nw)
340  double precision, intent(in) :: x(ixI^S, 1:^ND)
341  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
342  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
343  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
344 
345  double precision :: wmean(ixI^S,nw)
346 
347  ! Since the advection coefficient can depend on unknowns,
348  ! some average over the left and right state should be taken
349  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
350 
351  if (present(cmin)) then
352  cmin(ixo^s,1) = min(a1(idim) * wmean(ixo^s,u_)**(adv_pow-1), zero)
353  cmax(ixo^s,1) = max(a1(idim) * wmean(ixo^s,u_)**(adv_pow-1), zero)
354  if (number_of_species >= 2) then
355  cmin(ixo^s,1) = min(cmin(ixo^s,1), a2(idim) * wmean(ixo^s,v_)**(adv_pow-1))
356  cmax(ixo^s,1) = max(cmax(ixo^s,1), a2(idim) * wmean(ixo^s,v_)**(adv_pow-1))
357  end if
358  if (number_of_species >= 3) then
359  cmin(ixo^s,1) = min(cmin(ixo^s,1), a3(idim) * wmean(ixo^s,w_)**(adv_pow-1))
360  cmax(ixo^s,1) = max(cmax(ixo^s,1), a3(idim) * wmean(ixo^s,w_)**(adv_pow-1))
361  end if
362  else
363  cmax(ixo^s,1) = maxval(abs(a1(idim) * wmean(ixo^s,u_)**(adv_pow-1)))
364  if (number_of_species >=2) then
365  cmax(ixo^s,1) = max(cmax(ixo^s,1), maxval(abs(a2(idim) * wmean(ixo^s,v_)**(adv_pow-1))))
366  end if
367  if (number_of_species >=3) then
368  cmax(ixo^s,1) = max(cmax(ixo^s,1), maxval(abs(a3(idim) * wmean(ixo^s,w_)**(adv_pow-1))))
369  end if
370  end if
371 
372  end subroutine ard_get_cbounds
373 
374  subroutine ard_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
376  integer, intent(in) :: ixI^L, ixO^L
377  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
378  double precision, intent(in) :: w(ixI^S, 1:nw)
379  double precision, intent(inout) :: dtnew
380  double precision :: maxrate
381  double precision :: maxD
382  double precision :: maxA
383 
384  dtnew = bigdouble
385 
386  ! dt < dx^2 / (2 * ndim * diffusion_coeff)
387  ! use dtdiffpar < 1 for explicit and > 1 for imex/split
388  maxd = d1
389  if (number_of_species >= 2) then
390  maxd = max(maxd, d2)
391  end if
392  if (number_of_species >= 3) then
393  maxd = max(maxd, d3)
394  end if
395  dtnew = min(dtnew, dtdiffpar * minval([ dx^d ])**2 / (2 * ndim * maxd))
396 
397  ! Estimate time step for reactions
398  select case (equation_type)
399  case (eq_gray_scott)
400  maxrate = max(maxval(w(ixo^s, v_))**2 + gs_f, &
401  maxval(w(ixo^s, v_) * w(ixo^s, u_)) - gs_f - gs_k)
402  case (eq_schnakenberg)
403  maxrate = max(maxval(abs(w(ixo^s, v_) * w(ixo^s, u_) - 1)), &
404  maxval(w(ixo^s, u_))**2)
405  case (eq_brusselator)
406  maxrate = max( maxval(w(ixo^s, u_)*w(ixo^s, v_) - (br_b+1)), &
407  maxval(w(ixo^s, u_)**2) )
408  case (eq_ext_brusselator)
409  maxrate = max( maxval(w(ixo^s, u_)*w(ixo^s, v_) - (br_b+1)) + br_c, &
410  maxval(w(ixo^s, u_)**2) )
411  maxrate = max(maxrate, br_d)
412  case (eq_logistic)
413  maxrate = lg_lambda*maxval(abs(1 - w(ixo^s, u_))) ! abs for safety, normally u < 1
414  case (eq_analyt_hunds)
415  maxrate = maxval(w(ixo^s, u_)*abs(1 - w(ixo^s, u_))) / d1
416  case (eq_belousov_fn)
417  maxrate = max(&
418  maxval(abs(1.0d0 - w(ixo^s, w_) - w(ixo^s, u_))) / bzfn_epsilon, &
419  maxval(bzfn_lambda + w(ixo^s, u_)) / bzfn_delta &
420  )
421  case (eq_lorenz)
422  ! det(J) = sigma(b(r-1) + x*(x*+y*))
423  maxrate = max(lor_sigma, 1.0d0, lor_b)
424  case (eq_no_reac)
425  ! No reaction term, so no influence on timestep
426  maxrate = zero
427  case default
428  maxrate = one
429  call mpistop("Unknown equation type")
430  end select
431 
432  dtnew = min(dtnew, dtreacpar / maxrate)
433 
434  end subroutine ard_get_dt
435 
436  ! Add the flux from the advection term
437  subroutine ard_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
439  integer, intent(in) :: ixI^L, ixO^L, idim
440  double precision, intent(in) :: wC(ixI^S, 1:nw)
441  double precision, intent(in) :: w(ixI^S, 1:nw)
442  double precision, intent(in) :: x(ixI^S, 1:^ND)
443  double precision, intent(out) :: f(ixI^S, nwflux)
444 
445  f(ixo^s, u_) = (a1(idim)/adv_pow) * w(ixo^s,u_)**adv_pow
446  if (number_of_species >=2) then
447  f(ixo^s, v_) = (a2(idim)/adv_pow) * w(ixo^s,v_)**adv_pow
448  end if
449  if (number_of_species >=3) then
450  f(ixo^s, w_) = (a3(idim)/adv_pow) * w(ixo^s,w_)**adv_pow
451  end if
452 
453  end subroutine ard_get_flux
454 
455  subroutine ard_add_source_geom(qdt, ixI^L, ixO^L, wCT, w, x)
456 
457  ! Add geometrical source terms
458  ! There are no geometrical source terms
459 
461 
462  integer, intent(in) :: ixI^L, ixO^L
463  double precision, intent(in) :: qdt, x(ixI^S, 1:^ND)
464  double precision, intent(inout) :: wCT(ixI^S, 1:nw), w(ixI^S, 1:nw)
465 
466  end subroutine ard_add_source_geom
467 
468  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
469  subroutine ard_add_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active,wCTprim)
471  integer, intent(in) :: ixI^L, ixO^L
472  double precision, intent(in) :: qdt
473  double precision, intent(in) :: wCT(ixI^S, 1:nw), x(ixI^S, 1:ndim)
474  double precision, intent(inout) :: w(ixI^S, 1:nw)
475  double precision :: lpl_u(ixO^S), lpl_v(ixO^S), lpl_w(ixO^S)
476  logical, intent(in) :: qsourcesplit
477  logical, intent(inout) :: active
478  double precision, intent(in), optional :: wCTprim(ixI^S, 1:nw)
479 
480  ! here we add the reaction terms (always) and the diffusion if no imex is used
481  if (qsourcesplit .eqv. ard_source_split) then
482  if (.not.use_imex_scheme) then
483  call ard_laplacian(ixi^l, ixo^l, wct(ixi^s, u_), lpl_u)
484  if (number_of_species >= 2) then
485  call ard_laplacian(ixi^l, ixo^l, wct(ixi^s, v_), lpl_v)
486  end if
487  if (number_of_species >= 3) then
488  call ard_laplacian(ixi^l, ixo^l, wct(ixi^s, w_), lpl_w)
489  end if
490  else
491  ! for all IMEX scheme variants: only add the reactions
492  lpl_u = 0.0d0
493  lpl_v = 0.0d0
494  lpl_w = 0.0d0
495  end if
496 
497  select case (equation_type)
498  case (eq_gray_scott)
499  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u - &
500  wct(ixo^s, u_) * wct(ixo^s, v_)**2 + &
501  gs_f * (1 - wct(ixo^s, u_)))
502  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v + &
503  wct(ixo^s, u_) * wct(ixo^s, v_)**2 - &
504  (gs_f + gs_k) * wct(ixo^s, v_))
505  case (eq_schnakenberg)
506  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
507  + sb_kappa * (sb_alpha - wct(ixo^s, u_) + &
508  wct(ixo^s, u_)**2 * wct(ixo^s, v_)))
509  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
510  + sb_kappa * (sb_beta - wct(ixo^s, u_)**2 * wct(ixo^s, v_)))
511  case (eq_brusselator)
512  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
513  + br_a - (br_b + 1) * wct(ixo^s, u_) &
514  + wct(ixo^s, u_)**2 * wct(ixo^s, v_))
515  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
516  + br_b * wct(ixo^s, u_) - wct(ixo^s, u_)**2 * wct(ixo^s, v_))
517  case (eq_ext_brusselator)
518  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
519  + br_a - (br_b + 1) * wct(ixo^s, u_) &
520  + wct(ixo^s, u_)**2 * wct(ixo^s, v_) &
521  - br_c * wct(ixo^s, u_) + br_d * w(ixo^s, w_))
522  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
523  + br_b * wct(ixo^s, u_) &
524  - wct(ixo^s, u_)**2 * wct(ixo^s, v_))
525  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
526  + br_c * wct(ixo^s, u_) - br_d * w(ixo^s, w_))
527  case (eq_logistic)
528  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
529  + lg_lambda * w(ixo^s, u_) * (1 - w(ixo^s, u_)))
530  case (eq_analyt_hunds)
531  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
532  + 1.0d0/d1 * w(ixo^s, u_)**2 * (1 - w(ixo^s, u_)))
533  case (eq_belousov_fn)
534  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
535  + 1.0d0/bzfn_epsilon * (bzfn_lambda * wct(ixo^s, u_) &
536  - wct(ixo^s, u_)*wct(ixo^s, w_) + wct(ixo^s, u_) &
537  - wct(ixo^s, u_)**2))
538  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
539  + wct(ixo^s, u_) - wct(ixo^s, v_))
540  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
541  + 1.0d0/bzfn_delta * (-bzfn_lambda * wct(ixo^s, w_) &
542  - wct(ixo^s, u_)*wct(ixo^s, w_) + bzfn_mu * wct(ixo^s, v_)))
543  case (eq_lorenz)
544  ! xdot = sigma.(y-x)
545  w(ixo^s, u_) = w(ixo^s, u_) + qdt * (d1 * lpl_u &
546  + lor_sigma * (wct(ixo^s, v_) - wct(ixo^s, u_)))
547  ! ydot = r.x - y - x.z
548  w(ixo^s, v_) = w(ixo^s, v_) + qdt * (d2 * lpl_v &
549  + lor_r * wct(ixo^s, u_) - wct(ixo^s, v_) &
550  - wct(ixo^s, u_)*wct(ixo^s, w_))
551  ! zdot = x.y - b.z
552  w(ixo^s, w_) = w(ixo^s, w_) + qdt * (d3 * lpl_w &
553  + wct(ixo^s, u_)*wct(ixo^s, v_) - lor_b * wct(ixo^s, w_))
554  case (eq_no_reac)
555  w(ixo^s, u_) = w(ixo^s, u_) + qdt * d1 * lpl_u
556  case default
557  call mpistop("Unknown equation type")
558  end select
559 
560  ! enforce getbc call after source addition
561  active = .true.
562  end if
563 
564  end subroutine ard_add_source
565 
566  !> Compute the Laplacian using a standard second order scheme. For now this
567  !> method only works in slab geometries. Requires one ghost cell only.
568  subroutine ard_laplacian(ixI^L,ixO^L,var,lpl)
570  integer, intent(in) :: ixI^L, ixO^L
571  double precision, intent(in) :: var(ixI^S)
572  double precision, intent(out) :: lpl(ixO^S)
573  integer :: idir, jxO^L, hxO^L
574  double precision :: h_inv2
575 
576  if (slab) then
577  lpl(ixo^s) = 0.0d0
578  do idir = 1, ndim
579  hxo^l=ixo^l-kr(idir,^d);
580  jxo^l=ixo^l+kr(idir,^d);
581  h_inv2 = 1/dxlevel(idir)**2
582  lpl(ixo^s) = lpl(ixo^s) + h_inv2 * &
583  (var(jxo^s) - 2 * var(ixo^s) + var(hxo^s))
584  end do
585  else
586  call mpistop("ard_laplacian not implemented in this geometry")
587  end if
588 
589  end subroutine ard_laplacian
590 
591  subroutine put_laplacians_onegrid(ixI^L,ixO^L,w)
593  integer, intent(in) :: ixI^L, ixO^L
594  double precision, intent(inout) :: w(ixI^S, 1:nw)
595 
596  double precision :: lpl_u(ixO^S), lpl_v(ixO^S), lpl_w(ixO^S)
597 
598  call ard_laplacian(ixi^l, ixo^l, w(ixi^s, u_), lpl_u)
599  if (number_of_species >= 2) then
600  call ard_laplacian(ixi^l, ixo^l, w(ixi^s, v_), lpl_v)
601  end if
602  if (number_of_species >= 3) then
603  call ard_laplacian(ixi^l, ixo^l, w(ixi^s, w_), lpl_w)
604  end if
605 
606  w(ixo^s,u_) = d1*lpl_u
607  if (number_of_species >= 2) then
608  w(ixo^s,v_) = d2*lpl_v
609  end if
610  if (number_of_species >= 3) then
611  w(ixo^s,w_) = d3*lpl_w
612  end if
613 
614  end subroutine put_laplacians_onegrid
615 
616  !> inplace update of psa==>F_im(psa)
617  subroutine ard_evaluate_implicit(qtC,psa)
619  type(state), target :: psa(max_blocks)
620  double precision, intent(in) :: qtC
621 
622  integer :: iigrid, igrid, level
623  integer :: ixO^L
624 
625  !ixO^L=ixG^LL^LSUB1;
626  ixo^l=ixm^ll;
627  !$OMP PARALLEL DO PRIVATE(igrid)
628  do iigrid=1,igridstail; igrid=igrids(iigrid);
629  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
630  call put_laplacians_onegrid(ixg^ll,ixo^l,psa(igrid)%w)
631  end do
632  !$OMP END PARALLEL DO
633 
634  end subroutine ard_evaluate_implicit
635 
636  !> Implicit solve of psa=psb+dtfactor*dt*F_im(psa)
637  subroutine ard_implicit_update(dtfactor,qdt,qtC,psa,psb)
639  use mod_forest
640 
641  type(state), target :: psa(max_blocks)
642  type(state), target :: psb(max_blocks)
643  double precision, intent(in) :: qdt
644  double precision, intent(in) :: qtC
645  double precision, intent(in) :: dtfactor
646 
647  integer :: n
648  double precision :: res, max_residual, lambda
649 
650  integer :: iw_to,iw_from
651  integer :: iigrid, igrid, id
652  integer :: nc, lvl
653  type(tree_node), pointer :: pnode
654  real(dp) :: fac
655 
656  ! Avoid setting a very restrictive limit to the residual when the time step
657  ! is small (as the operator is ~ 1/(D * qdt))
658  if (qdt < dtmin) then
659  if(mype==0)then
660  print *,'skipping implicit solve: dt too small!'
661  print *,'Currently at time=',global_time,' time step=',qdt,' dtmin=',dtmin
662  endif
663  return
664  endif
665  max_residual = 1d-7/qdt
666 
667  mg%operator_type = mg_helmholtz
668  call mg_set_methods(mg)
669 
670  if (.not. mg%is_allocated) call mpistop("multigrid tree not allocated yet")
671 
672  ! First handle the u variable ***************************************
673  lambda = 1/(dtfactor * qdt * d1)
674  call helmholtz_set_lambda(lambda)
675  mg%bc(:, mg_iphi) = ard_mg_bc(1, :)
676 
677  call mg_copy_to_tree(u_, mg_irhs, factor=-lambda, state_from=psb)
678  call mg_copy_to_tree(u_, mg_iphi, state_from=psb)
679 
680  call mg_fas_fmg(mg, .true., max_res=res)
681  do n = 1, 10
682  call mg_fas_vcycle(mg, max_res=res)
683  if (res < max_residual) exit
684  end do
685 
686  call mg_copy_from_tree_gc(mg_iphi, u_, state_to=psa)
687  ! Done with the u variable ***************************************
688 
689  ! Next handle the v variable ***************************************
690  if (number_of_species >= 2) then
691  lambda = 1/(dtfactor * qdt * d2)
692  call helmholtz_set_lambda(lambda)
693  mg%bc(:, mg_iphi) = ard_mg_bc(2, :)
694 
695  call mg_copy_to_tree(v_, mg_irhs, factor=-lambda, state_from=psb)
696  call mg_copy_to_tree(v_, mg_iphi, state_from=psb)
697 
698  call mg_fas_fmg(mg, .true., max_res=res)
699  do n = 1, 10
700  call mg_fas_vcycle(mg, max_res=res)
701  if (res < max_residual) exit
702  end do
703 
704  call mg_copy_from_tree_gc(mg_iphi, v_, state_to=psa)
705  end if
706  ! Done with the v variable ***************************************
707 
708  ! Next handle the w variable ***************************************
709  if (number_of_species >= 3) then
710  lambda = 1/(dtfactor * qdt * d3)
711  call helmholtz_set_lambda(lambda)
712 
713  call mg_copy_to_tree(w_, mg_irhs, factor=-lambda, state_from=psb)
714  call mg_copy_to_tree(w_, mg_iphi, state_from=psb)
715 
716  call mg_fas_fmg(mg, .true., max_res=res)
717  do n = 1, 10
718  call mg_fas_vcycle(mg, max_res=res)
719  if (res < max_residual) exit
720  end do
721 
722  call mg_copy_from_tree_gc(mg_iphi, w_, state_to=psa)
723  end if
724  ! Done with the w variable ***************************************
725 
726  end subroutine ard_implicit_update
727 
728 end module mod_ard_phys
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
Module containing the physics routines for advection-reaction-diffusion equations.
Definition: mod_ard_phys.t:20
subroutine ard_get_flux(wC, w, x, ixIL, ixOL, idim, f)
Definition: mod_ard_phys.t:438
double precision, public, protected br_a
Parameters for Brusselator model.
Definition: mod_ard_phys.t:79
double precision, dimension(^nd), public, protected a3
Advection coefficients for third species (w) (if applicable)
Definition: mod_ard_phys.t:66
double precision, public, protected lg_lambda
Parameter for logistic model (Fisher / KPP equation)
Definition: mod_ard_phys.t:85
double precision, public, protected gs_k
Kill rate for Gray-Scott model.
Definition: mod_ard_phys.t:76
integer, public, protected v_
For 2 or more equations.
Definition: mod_ard_phys.t:28
subroutine ard_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_ard_phys.t:375
double precision, public, protected sb_alpha
Parameters for Schnakenberg model.
Definition: mod_ard_phys.t:69
double precision, public, protected gs_f
Feed rate for Gray-Scott model.
Definition: mod_ard_phys.t:74
double precision, public, protected sb_beta
Definition: mod_ard_phys.t:70
double precision, public, protected br_b
Definition: mod_ard_phys.t:80
subroutine ard_get_cmax(w, x, ixIL, ixOL, idim, cmax)
Definition: mod_ard_phys.t:319
double precision, public, protected br_c
Definition: mod_ard_phys.t:81
subroutine, public ard_phys_init()
Definition: mod_ard_phys.t:176
subroutine ard_get_cbounds(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
Definition: mod_ard_phys.t:335
double precision, public, protected sb_kappa
Definition: mod_ard_phys.t:71
character(len=20), public, protected equation_name
Name of the system to be solved.
Definition: mod_ard_phys.t:38
integer, public, protected u_
Indices of the unknowns.
Definition: mod_ard_phys.t:27
double precision, public, protected lor_b
Parameter for Lorenz system (aspect ratio of the convection rolls)
Definition: mod_ard_phys.t:98
double precision, public, protected dtreacpar
Parameter with which to multiply the reaction timestep restriction.
Definition: mod_ard_phys.t:35
double precision, public, protected bzfn_mu
Definition: mod_ard_phys.t:91
double precision, public, protected lor_sigma
Parameter for Lorenz system (Prandtl number)
Definition: mod_ard_phys.t:96
integer, public, protected adv_pow
Power of the unknown in the advection term (1 for linear)
Definition: mod_ard_phys.t:59
subroutine ard_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_ard_phys.t:569
double precision, public, protected d1
Diffusion coefficient for first species (u)
Definition: mod_ard_phys.t:52
double precision, public, protected d2
Diffusion coefficient for second species (v) (if applicable)
Definition: mod_ard_phys.t:54
type(mg_bc_t), dimension(3, mg_num_neighbors), public ard_mg_bc
Boundary condition information for the multigrid method.
Definition: mod_ard_phys.t:104
double precision, public, protected bzfn_epsilon
Parameters for the Field-Noyes model of the Belousov-Zhabotinsky reaction.
Definition: mod_ard_phys.t:88
logical, public, protected ard_particles
Whether particles module is added.
Definition: mod_ard_phys.t:32
double precision, public, protected lor_r
Parameter for Lorenz system (Rayleigh number)
Definition: mod_ard_phys.t:94
double precision, dimension(^nd), public, protected a2
Advection coefficients for second species (v) (if applicable)
Definition: mod_ard_phys.t:64
subroutine put_laplacians_onegrid(ixIL, ixOL, w)
Definition: mod_ard_phys.t:592
double precision, public, protected d3
Diffusion coefficient for third species (w) (if applicable)
Definition: mod_ard_phys.t:56
double precision, public, protected bzfn_lambda
Definition: mod_ard_phys.t:90
subroutine ard_write_info(fh)
Write this modules parameters to a snapshot.
Definition: mod_ard_phys.t:165
integer, public, protected w_
For 3 or more equations.
Definition: mod_ard_phys.t:29
subroutine ard_implicit_update(dtfactor, qdt, qtC, psa, psb)
Implicit solve of psa=psb+dtfactor*dt*F_im(psa)
Definition: mod_ard_phys.t:638
subroutine ard_add_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active, wCTprim)
Definition: mod_ard_phys.t:470
subroutine ard_check_params
Definition: mod_ard_phys.t:236
double precision, dimension(^nd), public, protected a1
Advection coefficients for first species (u)
Definition: mod_ard_phys.t:62
subroutine ard_to_primitive(ixIL, ixOL, w, x)
Definition: mod_ard_phys.t:310
double precision, public, protected bzfn_delta
Definition: mod_ard_phys.t:89
subroutine ard_evaluate_implicit(qtC, psa)
inplace update of psa==>F_im(psa)
Definition: mod_ard_phys.t:618
subroutine ard_add_source_geom(qdt, ixIL, ixOL, wCT, w, x)
Definition: mod_ard_phys.t:456
subroutine ard_to_conserved(ixIL, ixOL, w, x)
Definition: mod_ard_phys.t:301
double precision, public, protected br_d
Definition: mod_ard_phys.t:82
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 ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range (within a block with ghost cells)
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 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.
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_add_source_geom), pointer phys_add_source_geom
Definition: mod_physics.t:70
procedure(sub_check_params), pointer phys_check_params
Definition: mod_physics.t:56
integer, parameter flux_default
Indicates a normal flux.
Definition: mod_physics.t:46
integer, dimension(:, :), allocatable flux_type
Array per direction per variable, which can be used to specify that certain fluxes have to be treated...
Definition: mod_physics.t:43
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
integer nwflux
Number of flux variables.
Definition: mod_variables.t:8
The data structure that contains information about a tree node/grid block.
Definition: mod_forest.t:11