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