MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_fld.t
Go to the documentation of this file.
1!> Nicolas Moens with updates by RK (16/03/2026)
2!> Module for including flux limited diffusion (FLD)-approximation in Radiation-hydrodynamics simulations
3!> Based on Turner and stone 2001. See
4!> [1]Moens, N., Sundqvist, J. O., El Mellah, I., Poniatowski, L., Teunissen, J., and Keppens, R.,
5!> Radiation-hydrodynamics with MPI-AMRVAC . Flux-limited diffusion
6!> <i>Astronomy and Astrophysics</i>, vol. 657, 2022. doi:10.1051/0004-6361/202141023.
7!> For more information.
8
9module mod_fld
10 use mod_comm_lib, only: mpistop
11 use mod_geometry
12 implicit none
13 !> source split for energy interact and radforce:
14 logical :: fld_eint_split = .false.
15 logical :: fld_radforce_split = .false.
16 !> Opacity per unit of unit_density
17 double precision, public :: fld_kappa0 = 0.34d0
18 !> mean particle mass
19 double precision, public :: fld_mu = 0.6d0
20 !> Tolerance for bisection method for Energy sourceterms
21 !> This is a percentage of the minimum of gas- and radiation energy
22 double precision, public :: fld_bisect_tol = 1.d-4
23 !> Tolerance for adi method for radiative Energy diffusion
24 double precision, public :: fld_diff_tol = 1.d-4
25 !> switches for opacity
26 character(len=8) :: fld_opacity_law = 'const'
27 character(len=50) :: fld_opal_table = 'Y09800'
28 !> flux limiter choice
29 character(len=16) :: fld_fluxlimiter = 'Pomraning'
30 !> diffusion coefficient for multigrid method
31 integer :: i_diff_mg
32 !> Which method to find the root for the energy interaction polynomial
33 character(len=8) :: fld_interaction_method = 'Halley'
34 !> Use or dont use lineforce opacities
35 logical :: lineforce_opacities = .false.
36 !> Resume run when multigrid returns error
37 logical :: diffcrash_resume = .true.
38 !> Index for Flux weighted opacities
39 integer, allocatable, public :: i_opf(:)
40 !> A copy of (m)hd_Gamma
41 double precision, private, protected :: fld_gamma
42 !> running timestep for diffusion solver, initialised as zero
43 double precision :: dt_diff = 0.d0
44 !> public methods
45 !> these are called in mod_hd_phys or mod_mhd_phys
46 public :: fld_init
47 public :: fld_get_radpress
49 public :: add_fld_rad_force
50 public :: fld_radforce_get_dt
51 ! these are made public for mod_usr purposes and diagnostics
52 public :: fld_get_radflux
53 public :: fld_get_fluxlimiter
54 public :: fld_get_opacity
55 contains
56
57 !> Reading in fld-list parameters from .par file
58 subroutine fld_params_read(files)
61 character(len=*), intent(in) :: files(:)
62 integer :: n
63
64 namelist /fld_list/ fld_kappa0, fld_eint_split, fld_radforce_split, &
68
69 do n = 1, size(files)
70 open(unitpar, file=trim(files(n)), status="old")
71 read(unitpar, fld_list, end=111)
72 111 close(unitpar)
73 end do
74 end subroutine fld_params_read
75
76 !> Initialising FLD-module:
77 !> Read opacities
78 !> Initialise Multigrid
79 !> adimensionalise kappa
80 !> Add extra variables to w-array, flux, kappa, eddington Tensor
81 !> Lambda and R
82 !> ...
83 subroutine fld_init(He_abundance, r_gamma)
86 use mod_physics
89
90 double precision, intent(in) :: he_abundance, r_gamma
91 double precision :: sigma_thomson
92 integer :: idir,jdir
93 character(len=1) :: ind_1
94 character(len=1) :: ind_2
95 character(len=2) :: cmp_f
96 character(len=5) :: cmp_e
97
98 !> read par files
100 !> Set lineforce opacities as variable
101 if(lineforce_opacities) then
102 allocate(i_opf(ndim))
103 do idir = 1,ndim
104 write(ind_1,'(I1)') idir
105 cmp_f = 'k' // ind_1
106 i_opf(idir) = var_set_extravar(cmp_f,cmp_f)
107 enddo
108 endif
111 use_multigrid = .true.
112 mg%n_extra_vars = 1
113 mg%operator_type = mg_vhelmholtz
114 i_diff_mg = var_set_extravar("D", "D")
115 !> Need mean molecular weight
116 fld_mu = (1.+4*he_abundance)/(2.+3.*he_abundance)
117 !> set gamma
118 fld_gamma = r_gamma
119 !> Read in opacity table if necesary
121 if(fld_opacity_law .eq. 'thomson') then
122 ! special fixed value for thomson opacity, assuming cgs units
123 sigma_thomson = 6.6524585d-25
124 fld_kappa0 = sigma_thomson/const_mp * (1.+2.*he_abundance)/(1.+4.*he_abundance)
125 endif
126 end subroutine fld_init
127
128 !> w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
129 !> This subroutine handles the radiation force
130 subroutine add_fld_rad_force(qdt,ixI^L,ixO^L,wCT,wCTprim,w,x,&
131 energy,qsourcesplit,active)
132 use mod_constants
135 use mod_geometry
136 integer, intent(in) :: ixi^l, ixo^l
137 double precision, intent(in) :: qdt, x(ixi^s,1:ndim)
138 double precision, intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw)
139 double precision, intent(inout) :: w(ixi^s,1:nw)
140 logical, intent(in) :: energy,qsourcesplit
141 logical, intent(inout) :: active
142 integer :: idir, jdir
143 double precision :: radiation_forcect(ixo^s,1:ndim)
144 double precision :: rad_fluxct(ixo^s,1:ndim)
145 double precision :: grad_e(ixi^s)
146 double precision :: lambda(ixo^s),fld_r(ixo^s)
147
148 !> Calculate and add sourceterms
149 if(qsourcesplit .eqv. fld_radforce_split) then
150 active = .true.
151 !> Radiation force = kappa*rho/c *Flux = lambda gradE
152 call fld_get_fluxlimiter(wct,x,ixi^l,ixo^l,lambda,fld_r,nghostcells)
153 do idir = 1,ndim
154 call gradient(wct(ixi^s,iw_r_e),ixi^l,ixo^l,idir,grad_e,nghostcells)
155 radiation_forcect(ixo^s,idir) = -lambda(ixo^s)*grad_e(ixo^s)
156 !> Momentum equation source term
157 w(ixo^s,iw_mom(idir)) = w(ixo^s,iw_mom(idir)) &
158 + qdt*radiation_forcect(ixo^s,idir)
159 !> Energy equation source term
160 w(ixo^s,iw_e) = w(ixo^s,iw_e) &
161 + qdt*wctprim(ixo^s,iw_mom(idir))*radiation_forcect(ixo^s,idir)
162 enddo
163 end if
164 end subroutine add_fld_rad_force
165
166 !> get dt limit for radiation force: NOTE: only uniform cartesian here!
167 subroutine fld_radforce_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
170 use mod_geometry
171 integer, intent(in) :: ixi^l, ixo^l
172 double precision, intent(in) :: dx^d, x(ixi^s,1:ndim), w(ixi^s,1:nw)
173 double precision, intent(inout) :: dtnew
174 double precision :: radiation_force(ixo^s,1:ndim)
175 double precision :: dxinv(1:ndim), max_grad
176 double precision :: lambda(ixo^s),fld_r(ixo^s),grad_e(ixi^s)
177 integer :: idir
178
179 ^d&dxinv(^d)=one/dx^d;
180 call fld_get_fluxlimiter(w,x,ixi^l,ixo^l,lambda,fld_r,nghostcells)
181 do idir = 1, ndim
182 call gradient(w(ixi^s,iw_r_e),ixi^l,ixo^l,idir,grad_e,nghostcells)
183 radiation_force(ixo^s,idir) = -lambda(ixo^s)*grad_e(ixo^s)
184 max_grad = maxval(dabs(radiation_force(ixo^s,idir)))
185 max_grad = max(max_grad, epsilon(1.0d0))
186 dtnew = min(dtnew, courantpar / dsqrt(max_grad * dxinv(idir)))
187 end do
188 end subroutine fld_radforce_get_dt
189
190 !> Sets the opacity in the w-array
191 !> by calling mod_opal_opacity
192 subroutine fld_get_opacity(w, x, ixI^L, ixO^L, fld_kappa)
194 use mod_physics, only: phys_get_tgas
197 integer, intent(in) :: ixi^l, ixo^l
198 double precision, intent(in) :: w(ixi^s, 1:nw)
199 double precision, intent(in) :: x(ixi^s, 1:ndim)
200 double precision, intent(out) :: fld_kappa(ixo^s)
201 double precision :: temp(ixi^s)
202 double precision :: rho0,temp0,n
203 integer :: i,j,ix^d, idir
204 select case (fld_opacity_law)
205 case('const')
206 fld_kappa(ixo^s) = fld_kappa0/unit_opacity
207 case('thomson')
208 fld_kappa(ixo^s) = fld_kappa0/unit_opacity
209 case('opal')
210 call phys_get_tgas(w,x,ixi^l,ixo^l,temp)
211 {do ix^d=ixomin^d,ixomax^d\ }
212 rho0 = w(ix^d,iw_rho)*unit_density
213 temp0 = temp(ix^d)*unit_temperature
214 call set_opal_opacity(rho0,temp0,n)
215 fld_kappa(ix^d) = n/unit_opacity
216 {enddo\ }
217 case('special')
218 if (.not. associated(usr_special_opacity)) then
219 call mpistop("special opacity not defined")
220 endif
221 call usr_special_opacity(ixi^l, ixo^l, w, x, fld_kappa)
222 case default
223 call mpistop("Doesn't know opacity law")
224 end select
225 end subroutine fld_get_opacity
226
227 !> Calculate fld flux limiter
228 !> This subroutine calculates flux limiter lambda using the prescription
229 !> stored in fld_fluxlimiter.
230 !> It also calculates the ratio of radiation scaleheight and mean free path
231 subroutine fld_get_fluxlimiter(w,x,ixI^L,ixO^L,fld_lambda,fld_R,nth)
233 use mod_geometry
235 integer, intent(in) :: ixi^l,ixo^l,nth
236 double precision, intent(in) :: w(ixi^s,1:nw)
237 double precision, intent(in) :: x(ixi^s,1:ndim)
238 double precision, intent(out) :: fld_r(ixo^s),fld_lambda(ixo^s)
239 integer :: idir, ix^d
240 integer :: filter
241 double precision :: kappa(ixo^s)
242 double precision :: normgrad2(ixo^s)
243 double precision :: grad_r_e(ixi^s)
244 double precision :: rad_e(ixi^s)
245 double precision :: tmp_l(ixi^s), filtered_l(ixi^s)
246
247 select case(fld_fluxlimiter)
248 case('Diffusion')
249 !> optically thick limit
250 fld_lambda(ixo^s) = 1.d0/3.d0
251 fld_r(ixo^s) = zero
252 case('FreeStream')
253 !> optically thin limit
254 !> Calculate R everywhere
255 !> |grad E|/(rho kappa E)
256 normgrad2(ixo^s) = zero
257 rad_e(ixi^s) = w(ixi^s, iw_r_e)
258 do idir=1,ndim
259 call gradient(rad_e,ixi^l,ixo^l,idir,grad_r_e,nth)
260 normgrad2(ixo^s) = normgrad2(ixo^s)+grad_r_e(ixo^s)**2
261 end do
262 call fld_get_opacity(w,x,ixi^l,ixo^l,kappa)
263 ! Note: possible zeros for uniform setup, to adjust
264 if(maxval(normgrad2(ixo^s))==0.0d0)call mpistop("choose other fluxlimiter, FreeStream has issues")
265 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
266 !> Calculate the flux limiter, lambda
267 fld_lambda(ixo^s) = one/fld_r(ixo^s)
268 case('Pomraning')
269 !> Calculate R everywhere
270 !> |grad E|/(rho kappa E)
271 normgrad2(ixo^s) = zero
272 rad_e(ixi^s) = w(ixi^s, iw_r_e)
273 do idir = 1,ndim
274 call gradient(rad_e,ixi^l,ixo^l,idir,grad_r_e,nth)
275 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
276 end do
277 call fld_get_opacity(w,x,ixi^l,ixo^l,kappa)
278 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
279 !> Calculate the flux limiter, lambda
280 !> Levermore and Pomraning: lambda = (2 + R)/(6 + 3R + R^2)
281 fld_lambda(ixo^s) = (2.d0+fld_r(ixo^s))/(6.d0+3*fld_r(ixo^s)+fld_r(ixo^s)**2.d0)
282 case('Minerbo')
283 !> Calculate R everywhere
284 !> |grad E|/(rho kappa E)
285 normgrad2(ixo^s) = zero
286 rad_e(ixi^s) = w(ixi^s, iw_r_e)
287 do idir = 1,ndim
288 call gradient(rad_e,ixi^l,ixo^l,idir,grad_r_e,nth)
289 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
290 end do
291 call fld_get_opacity(w, x, ixi^l, ixo^l, kappa)
292 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
293 !> Calculate the flux limiter, lambda
294 !> Minerbo:
295 {do ix^d = ixomin^d,ixomax^d\ }
296 if(fld_r(ix^d) .lt. 3.d0/2.d0) then
297 fld_lambda(ix^d) = 2.d0/(3.d0+dsqrt(9.d0+12.d0*fld_r(ix^d)**2.d0))
298 else
299 fld_lambda(ix^d) = 1.d0/(1.d0+fld_r(ix^d)+dsqrt(1.d0+2.d0*fld_r(ix^d)))
300 endif
301 {enddo\}
302 case('special')
303 if (.not. associated(usr_special_fluxlimiter)) then
304 call mpistop("special fluxlimiter not defined")
305 endif
306 call usr_special_fluxlimiter(ixi^l,ixo^l,w,x,fld_lambda,fld_r)
307 case default
308 call mpistop('Fluxlimiter unknown')
309 end select
310
311 end subroutine fld_get_fluxlimiter
312
313 !> Calculate Radiation Flux
314 !> stores radiation flux in w-array
315 subroutine fld_get_radflux(w, x, ixI^L, ixO^L, rad_flux, nth)
317 use mod_geometry
318 integer, intent(in) :: ixi^l, ixo^l, nth
319 double precision, intent(in) :: w(ixi^s, 1:nw)
320 double precision, intent(in) :: x(ixi^s, 1:ndim)
321 double precision, intent(out) :: rad_flux(ixo^s, 1:ndim)
322 double precision :: cc
323 double precision :: grad_r_e(ixi^s)
324 double precision :: rad_e(ixi^s)
325 double precision :: kappa(ixo^s), lambda(ixo^s), fld_r(ixo^s)
326 integer :: ix^d, idir
327
328 cc = const_c/unit_velocity
329 rad_e(ixi^s) = w(ixi^s, iw_r_e)
330 call fld_get_opacity(w, x, ixi^l, ixo^l, kappa)
331 call fld_get_fluxlimiter(w, x, ixi^l, ixo^l, lambda, fld_r, nghostcells)
332 !> Calculate the Flux using the fld closure relation
333 !> F = -c*lambda/(kappa*rho) *grad E
334 do idir = 1,ndim
335 call gradient(rad_e,ixi^l,ixo^l,idir,grad_r_e,nth)
336 rad_flux(ixo^s, idir) = -cc*lambda(ixo^s)/(kappa(ixo^s)*w(ixo^s,iw_rho))*grad_r_e(ixo^s)
337 end do
338 end subroutine fld_get_radflux
339
340 !> Calculate Eddington-tensor
341 subroutine fld_get_eddington(w, x, ixI^L, ixO^L, eddington_tensor, nth)
343 use mod_geometry
344 integer, intent(in) :: ixI^L, ixO^L, nth
345 double precision, intent(in) :: w(ixI^S, 1:nw)
346 double precision, intent(in) :: x(ixI^S, 1:ndim)
347 double precision, intent(out) :: eddington_tensor(ixI^S,1:ndim,1:ndim)
348 double precision :: tnsr2(ixO^S,1:ndim,1:ndim)
349 double precision :: normgrad2(ixO^S), f(ixO^S)
350 double precision :: grad_r_e(ixI^S,1:ndim), rad_e(ixI^S)
351 double precision :: lambda(ixO^S), fld_R(ixO^S)
352 integer :: i,j, idir,jdir
353
354 !> Calculate R everywhere
355 !> |grad E|/(rho kappa E)
356 normgrad2(ixo^s) = zero
357 rad_e(ixi^s) = w(ixi^s, iw_r_e)
358 do idir = 1,ndim
359 call gradient(rad_e,ixi^l,ixo^l,idir,grad_r_e(ixi^s,idir),nth)
360 normgrad2(ixo^s)=normgrad2(ixo^s)+grad_r_e(ixo^s,idir)**2
361 end do
362 call fld_get_fluxlimiter(w,x,ixi^l,ixo^l,lambda,fld_r,nth)
363 !> Calculate radiation pressure
364 !> P = (lambda + lambda^2 R^2)*E
365 f(ixo^s) = lambda(ixo^s)+lambda(ixo^s)**two*fld_r(ixo^s)**two
366 f(ixo^s) = half*(one-f(ixo^s))+half*(3.d0*f(ixo^s)-one)
367 {^ifoned
368 eddington_tensor(ixo^s,1,1) = f(ixo^s)
369 }
370 {^nooned
371 do idir = 1,ndim
372 eddington_tensor(ixo^s,idir,idir) = half*(one-f(ixo^s))
373 enddo
374 do idir = 1,ndim
375 do jdir = 1,ndim
376 if(idir .ne. jdir) eddington_tensor(ixo^s,idir,jdir) = zero
377 tnsr2(ixo^s,idir,jdir) = half*(3.d0*f(ixo^s)-one) &
378 * grad_r_e(ixo^s,idir)*grad_r_e(ixo^s,jdir)/max(normgrad2(ixo^s),smalldouble)
379 enddo
380 enddo
381 do idir = 1,ndim
382 do jdir = 1,ndim
383 where(normgrad2(ixo^s) .gt. smalldouble)
384 eddington_tensor(ixo^s,idir,jdir) = eddington_tensor(ixo^s,idir,jdir)+tnsr2(ixo^s,idir,jdir)
385 endwhere
386 enddo
387 enddo
388 }
389 end subroutine fld_get_eddington
390
391 !> Calculate Radiation Pressure
392 !> Returns Radiation Pressure as tensor
393 !> NOTE: w is primitive on entry
394 subroutine fld_get_radpress(w, x, ixI^L, ixO^L, rad_pressure, nth)
396 integer, intent(in) :: ixi^l, ixo^l, nth
397 double precision, intent(in) :: w(ixi^s, 1:nw)
398 double precision, intent(in) :: x(ixi^s, 1:ndim)
399 double precision, intent(out):: rad_pressure(ixo^s,1:ndim,1:ndim)
400 integer :: i,j
401 double precision :: eddington_tensor(ixi^s,1:ndim,1:ndim)
402
403 call fld_get_eddington(w, x, ixi^l, ixo^l, eddington_tensor, nth)
404 do i=1,ndim
405 do j=1,ndim
406 rad_pressure(ixo^s,i,j) = eddington_tensor(ixo^s,i,j)*w(ixo^s,iw_r_e)
407 enddo
408 enddo
409 end subroutine fld_get_radpress
410
411 subroutine fld_implicit_update(dtfactor,qdt,qtC,psa,psb)
413 type(state), target :: psa(max_blocks)
414 type(state), target :: psb(max_blocks)
415 double precision, intent(in) :: qdt
416 double precision, intent(in) :: qtC
417 double precision, intent(in) :: dtfactor
418 integer :: ixO^L,iigrid,igrid
419
420 call diffuse_e_rad_mg(dtfactor,qdt,qtc,psa,psb)
421
422 ixo^l=ixg^ll^lsubnghostcells;
423 !$OMP PARALLEL DO PRIVATE(igrid)
424 do iigrid=1,igridstail; igrid=igrids(iigrid);
425 call energy_interaction(psa(igrid)%w, psa(igrid)%x, ixg^ll, ixo^l, dtfactor, qdt);
426 end do
427 !$OMP END PARALLEL DO
428 end subroutine fld_implicit_update
429
430 !> Energy interaction and photon tiring
431 subroutine energy_interaction(w, x, ixI^L, ixO^L, dtfactor, qdt)
433 use mod_geometry
434 use mod_physics
436 integer, intent(in) :: ixI^L,ixO^L
437 double precision, intent(in) :: x(ixI^S,1:ndim)
438 double precision, intent(in) :: dtfactor, qdt
439 double precision, intent(inout) :: w(ixI^S,1:nw)
440
441 double precision :: wprim(ixI^S,1:nw)
442 double precision, dimension(ixO^S) :: a1,a2,a3,c0,c1,kappa
443 double precision, dimension(ixI^S) :: e_gas,E_rad,vel,grad_v,nabla_vP
444 double precision, dimension(ixI^S,1:ndim,1:ndim) :: div_v,edd
445 double precision :: sigma_b,cc
446 integer :: i,j,idir,jdir,ix^D
447
448 !> Photon tiring
449 !> calculate tensor div_v
450 !> !$OMP PARALLEL DO
451 do idir = 1,ndim
452 do jdir = 1,ndim
453 vel(ixi^s) = w(ixi^s,iw_mom(jdir))/w(ixi^s,iw_rho)
454 call gradient(vel,ixi^l,ixo^l,idir,grad_v)
455 div_v(ixo^s,idir,jdir) = grad_v(ixo^s)
456 enddo
457 enddo
458 !> !$OMP END PARALLEL DO
459 call fld_get_eddington(w,x,ixi^l,ixo^l,edd,nghostcells)
460 !> VARIABLE NAMES DIV ARE ACTUALLY GRADIENTS
461 {^ifoned
462 nabla_vp(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1)
463 }
464 {^iftwod
465 !>eq 34 Turner and stone (Only 2D)
466 nabla_vp(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
467 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
468 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
469 + div_v(ixo^s,2,2)*edd(ixo^s,2,2)
470 }
471 {^ifthreed
472 nabla_vp(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
473 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
474 + div_v(ixo^s,1,3)*edd(ixo^s,1,3) &
475 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
476 + div_v(ixo^s,2,2)*edd(ixo^s,2,2) &
477 + div_v(ixo^s,2,3)*edd(ixo^s,2,3) &
478 + div_v(ixo^s,3,1)*edd(ixo^s,3,1) &
479 + div_v(ixo^s,3,2)*edd(ixo^s,3,2) &
480 + div_v(ixo^s,3,3)*edd(ixo^s,3,3)
481 }
482
483 cc = const_c/unit_velocity
484 sigma_b = const_rad_a*cc/4.d0*(unit_temperature**4.d0)/(unit_pressure)
485 !> e_gas is the INTERNAL ENERGY without KINETIC ENERGY
486 e_gas(ixo^s) = w(ixo^s,iw_e)-half*sum(w(ixo^s,iw_mom(:))**2,dim=ndim+1)/w(ixo^s,iw_rho)
487 if(allocated(iw_mag)) then
488 e_gas(ixo^s) = e_gas(ixo^s)-half*sum(w(ixo^s,iw_mag(:))**2,dim=ndim+1)
489 endif
490 {do ix^d = ixomin^d,ixomax^d\ }
491 e_gas(ix^d) = max(e_gas(ix^d),small_pressure/(fld_gamma-1.d0))
492 {enddo\}
493 e_rad(ixo^s) = w(ixo^s,iw_r_e)
494 if(associated(usr_special_opacity_qdot)) then
495 call usr_special_opacity_qdot(ixi^l,ixo^l,w,x,kappa)
496 else
497 call fld_get_opacity(w,x,ixi^l,ixo^l,kappa)
498 endif
499 !> Coefficients for the polynomial in Moens et al. 2022, eq 37.
500 a1(ixo^s) = 4.d0*kappa(ixo^s)*sigma_b*(fld_gamma-one)**4/w(ixo^s,iw_rho)**3*dtfactor*qdt
501 a2(ixo^s) = cc*kappa(ixo^s)*w(ixo^s,iw_rho)*dtfactor*qdt
502 a3(ixo^s) = nabla_vp(ixo^s)*dtfactor*qdt
503 c0(ixo^s) = ((one+a2(ixo^s)+a3(ixo^s))*e_gas(ixo^s)+a2(ixo^s)*e_rad(ixo^s))/a1(ixo^s)/(one+a3(ixo^s))
504 c1(ixo^s) = (one+a2(ixo^s)+a3(ixo^s))/a1(ixo^s)/(one+a3(ixo^s))
505
506 !> Loop over every cell for rootfinding method
507 {do ix^d = ixomin^d,ixomax^d\}
508 select case(fld_interaction_method)
509 case('Bisect')
510 call bisection_method(e_gas(ix^d),e_rad(ix^d),c0(ix^d),c1(ix^d))
511 case('Newton')
512 call newton_method(e_gas(ix^d),e_rad(ix^d),c0(ix^d),c1(ix^d))
513 case('Halley')
514 call halley_method(e_gas(ix^d),e_rad(ix^d),c0(ix^d),c1(ix^d))
515 case default
516 call mpistop('root-method not known')
517 end select
518 {enddo\}
519 e_rad(ixo^s) = (a1(ixo^s)*e_gas(ixo^s)**4.d0+e_rad(ixo^s))/(one+a2(ixo^s)+a3(ixo^s))
520 !> Update gas-energy in w, internal + kinetic
521 w(ixo^s,iw_e) = e_gas(ixo^s)
522 !> Beginning of module substracted wCT Ekin
523 !> So now add wCT Ekin
524 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mom(:))**2,dim=ndim+1)/w(ixo^s,iw_rho)
525 if(allocated(iw_mag)) then
526 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mag(:))**2,dim=ndim+1)
527 endif
528 !> Update rad-energy in w
529 w(ixo^s,iw_r_e) = e_rad(ixo^s)
530 end subroutine energy_interaction
531
532 !> Calling all subroutines to perform the multigrid method
533 !> Communicates rad_e and diff_coeff to multigrid library
534 subroutine diffuse_e_rad_mg(dtfactor,qdt,qtC,psa,psb)
536 use mod_forest
538 type(state), target :: psa(max_blocks) !< Advance psa=psb+dtfactor*qdt*F_im(psa)
539 type(state), target :: psb(max_blocks)
540 double precision, intent(in) :: qdt
541 double precision, intent(in) :: qtC
542 double precision, intent(in) :: dtfactor
543 integer :: n
544 double precision :: res, max_residual, lambda
545 integer, parameter :: max_its = 100
546 integer :: iw_to,iw_from
547 integer :: iigrid, igrid, id
548 integer :: nc, lvl, i
549 type(tree_node), pointer :: pnode
550 double precision :: fac, facD
551
552 !> Set diffusion timestep, add previous timestep if mg did not converge:
553 if(it == 0) dt_diff = 0
554 dt_diff = dt_diff + qdt
555 ! Avoid setting a very restrictive limit to the residual when the time step
556 ! is small (as the operator is ~ 1/(D * qdt))
557 if(qdt < dtmin) then
558 if(mype==0)then
559 print *,'skipping implicit solve: dt too small!'
560 print *,'Currently at time=',global_time,' time step=',qdt,' dtmin=',dtmin
561 endif
562 return
563 endif
564 max_residual = fld_diff_tol
565 mg%operator_type = mg_vhelmholtz
566 mg%smoother_type = mg_smoother_gs
567 call mg_set_methods(mg)
568 if(.not. mg%is_allocated) call mpistop("multigrid tree not allocated yet")
569 lambda = 1.d0/(dtfactor * dt_diff)
570 call vhelmholtz_set_lambda(lambda)
571 call update_diffcoeff(psb)
572 fac = 1.d0
573 facd = 1.d0
574 call mg_copy_to_tree(i_diff_mg, mg_iveps, factor=facd, state_from=psb)
575 call mg_copy_to_tree(iw_r_e, mg_iphi, factor=fac, state_from=psb)
576 call mg_copy_to_tree(iw_r_e, mg_irhs, factor=-1/(dtfactor*dt_diff), state_from=psb)
577 if(time_advance)then
578 call mg_restrict(mg, mg_iveps)
579 call mg_fill_ghost_cells(mg, mg_iveps)
580 endif
581 call mg_fas_fmg(mg, .true., max_res=res)
582 do n = 1, max_its
583 if(res < max_residual) exit
584 call mg_fas_vcycle(mg, max_res=res)
585 end do
586 if(res .le. 0.d0) then
587 if (diffcrash_resume) then
588 if (mg%my_rank == 0) &
589 write(*,*) it, ' residual zero ', res
590 return
591 endif
592 if(mg%my_rank == 0) then
593 print*, res
594 error stop "Diffusion residual to zero"
595 endif
596 endif
597! if(n==max_its+1) then
598! if(diffcrash_resume) then
599! if(mg%my_rank == 0) &
600! write(*,*) it, ' residual high ', res
601! return
602! endif
603! if(mg%my_rank == 0) then
604! print *, "Did you specify boundary conditions correctly?"
605! print *, "Or is the variation in diffusion too large?"
606! print*, n, res
607! print *, mg%bc(1, mg_iphi)%bc_value, mg%bc(2, mg_iphi)%bc_value
608! end if
609! error stop "diffusion_solve: no convergence"
610! end if
611 !> Reset dt_diff when diffusion worked out
612 dt_diff = 0.d0
613 call mg_copy_from_tree_gc(mg_iphi, iw_r_e, state_to=psa)
614 end subroutine diffuse_e_rad_mg
615
616 !> inplace update of psa==>F_im(psa)
617 subroutine evaluate_e_rad_mg(qtC,psa)
620 type(state), target :: psa(max_blocks)
621 double precision, intent(in) :: qtC
622 integer :: iigrid, igrid, level
623 integer :: ixO^L
624
625 call update_diffcoeff(psa)
626 ixo^l=ixm^ll^ladd1;
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_diffterm_onegrid(ixg^ll,ixo^l,psa(igrid)%w)
631 end do
632 !$OMP END PARALLEL DO
633 ! enforce boundary conditions for psa
634 call getbc(qtc,0.d0,psa,1,nwflux+nwaux)
635 end subroutine evaluate_e_rad_mg
636
637 !> inplace update of psa==>F_im(psa)
638 subroutine put_diffterm_onegrid(ixI^L,ixO^L,w)
640 integer, intent(in) :: ixI^L, ixO^L
641 double precision, intent(inout) :: w(ixI^S, 1:nw)
642 double precision :: gradE(ixO^S),divF(ixO^S)
643 double precision :: divF_h(ixO^S),divF_j(ixO^S)
644 double precision :: diff_term(ixO^S)
645 integer :: idir, jxO^L, hxO^L
646
647 divf(ixo^s) = 0.d0
648 do idir = 1,ndim
649 hxo^l=ixo^l-kr(idir,^d);
650 jxo^l=ixo^l+kr(idir,^d);
651 divf_h(ixo^s) = w(ixo^s,i_diff_mg)*w(hxo^s,i_diff_mg)/(w(ixo^s,i_diff_mg) + w(hxo^s,i_diff_mg))*(w(hxo^s,iw_r_e) - w(ixo^s,iw_r_e))
652 divf_j(ixo^s) = w(ixo^s,i_diff_mg)*w(jxo^s,i_diff_mg)/(w(ixo^s,i_diff_mg) + w(jxo^s,i_diff_mg))*(w(jxo^s,iw_r_e) - w(ixo^s,iw_r_e))
653 divf(ixo^s) = divf(ixo^s) + 2.d0*(divf_h(ixo^s) + divf_j(ixo^s))/dxlevel(idir)**2
654 enddo
655 w(ixo^s,iw_r_e) = divf(ixo^s)
656 end subroutine put_diffterm_onegrid
657
658 !> Calculates cell-centered diffusion coefficient to be used in multigrid
659 subroutine fld_get_diffcoef_central(w, wCT, wCTprim, x, ixI^L, ixO^L, primitives_filled)
661 use mod_geometry
663 integer, intent(in) :: ixi^l, ixo^l
664 logical, intent(in) :: primitives_filled
665 double precision, intent(inout) :: w(ixi^s,1:nw)
666 double precision, intent(in) :: wct(ixi^s,1:nw)
667 double precision, intent(in) :: wctprim(ixi^s,1:nw)
668 double precision, intent(in) :: x(ixi^s,1:ndim)
669 integer :: idir,i,j,ix^d
670 double precision :: cc
671 double precision :: kappa(ixo^s),lambda(ixo^s),fld_r(ixo^s)
672 double precision :: max_d(ixi^s),grad_r_e(ixi^s),rad_e(ixi^s)
673
674 cc = const_c/unit_velocity
675 if(primitives_filled)then
676 ! TODO: pass primitives here
677 call fld_get_opacity(wct, x, ixi^l, ixo^l, kappa)
678 call fld_get_fluxlimiter(wct, x, ixi^l, ixo^l, lambda, fld_r, nghostcells-1)
679 !> calculate diffusion coefficient
680 w(ixi^s,i_diff_mg) = zero !> so that w(i_diff_mg) in ghostcells won't accumulate to extreme values
681 w(ixo^s,i_diff_mg) = cc*lambda(ixo^s)/(kappa(ixo^s)*wct(ixo^s,iw_rho))
682 where(w(ixo^s,i_diff_mg) .lt. 0.d0) w(ixo^s,i_diff_mg) = smalldouble
683 else
684 ! WARNING: in this case, w, wCT, wCTprim are exactly the same storage location
685 call fld_get_opacity(wct, x, ixi^l, ixo^l, kappa)
686 call fld_get_fluxlimiter(wct, x, ixi^l, ixo^l, lambda, fld_r, nghostcells-1)
687 !> calculate diffusion coefficient
688 w(ixi^s,i_diff_mg) = zero !> so that w(i_diff_mg) in ghostcells won't accumulate to extreme values
689 w(ixo^s,i_diff_mg) = cc*lambda(ixo^s)/(kappa(ixo^s)*wct(ixo^s,iw_rho))
690 where(w(ixo^s,i_diff_mg) .lt. 0.d0) w(ixo^s,i_diff_mg) = smalldouble
691 endif
692 if(associated(usr_special_diffcoef)) call usr_special_diffcoef(w, wct, x, ixi^l, ixo^l)
693
694 end subroutine fld_get_diffcoef_central
695
696 subroutine update_diffcoeff(psa)
698 type(state), target :: psa(max_blocks)
699 integer :: iigrid, igrid, level
700 integer :: ixO^L
701
702 ixo^l=ixm^ll^ladd1;
703 !$OMP PARALLEL DO PRIVATE(igrid)
704 do iigrid=1,igridstail; igrid=igrids(iigrid);
705 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
706 call fld_get_diffcoef_central(psa(igrid)%w, psa(igrid)%w, psa(igrid)%w, psa(igrid)%x, ixg^ll, ixo^l, .false.)
707 end do
708 !$OMP END PARALLEL DO
709 end subroutine update_diffcoeff
710
711 !> Find the root of the 4th degree polynomial using the bisection method
712 subroutine bisection_method(e_gas, E_rad, c0, c1)
714 double precision, intent(in) :: c0, c1
715 double precision, intent(in) :: E_rad
716 double precision, intent(inout) :: e_gas
717 double precision :: bisect_a, bisect_b, bisect_c
718 integer :: n, max_its
719
720 n = 0
721 max_its = 100
722 bisect_a = zero
723 bisect_b = min(abs(c0/c1),abs(c0)**(1.d0/4.d0))+smalldouble
724 do while(abs(bisect_b-bisect_a) .ge. fld_bisect_tol*min(e_gas,e_rad))
725 bisect_c = (bisect_a + bisect_b)/two
726 n = n +1
727 if(n .gt. max_its) then
728 goto 2435
729 call mpistop('No convergece in bisection scheme')
730 endif
731 if(polynomial_bisection(bisect_a, c0, c1)*&
732 polynomial_bisection(bisect_b, c0, c1) .lt. zero) then
733 if(polynomial_bisection(bisect_a, c0, c1)*&
734 polynomial_bisection(bisect_c, c0, c1) .lt. zero) then
735 bisect_b = bisect_c
736 elseif(polynomial_bisection(bisect_b, c0, c1)*&
737 polynomial_bisection(bisect_c, c0, c1) .lt. zero) then
738 bisect_a = bisect_c
739 elseif(polynomial_bisection(bisect_a, c0, c1) .eq. zero) then
740 bisect_b = bisect_a
741 bisect_c = bisect_a
742 goto 2435
743 elseif(polynomial_bisection(bisect_b, c0, c1) .eq. zero) then
744 bisect_a = bisect_b
745 bisect_c = bisect_b
746 goto 2435
747 elseif(polynomial_bisection(bisect_c, c0, c1) .eq. zero) then
748 bisect_a = bisect_c
749 bisect_b = bisect_c
750 goto 2435
751 else
752 call mpistop("Problem with fld bisection method")
753 endif
754 elseif(polynomial_bisection(bisect_a, c0, c1) &
755 - polynomial_bisection(bisect_b, c0, c1) .lt. fld_bisect_tol*polynomial_bisection(bisect_a, c0, c1)) then
756 goto 2435
757 else
758 bisect_a = e_gas
759 bisect_b = e_gas
760 print*, "IGNORING GAS-RAD ENERGY EXCHANGE ", c0, c1
761 print*, polynomial_bisection(bisect_a, c0, c1), polynomial_bisection(bisect_b, c0, c1)
762 if(polynomial_bisection(bisect_a, c0, c1) .le. smalldouble) then
763 bisect_b = bisect_a
764 elseif(polynomial_bisection(bisect_a, c0, c1) .le. smalldouble) then
765 bisect_a = bisect_b
766 endif
767 goto 2435
768 endif
769 enddo
770 2435 e_gas = (bisect_a + bisect_b)/two
771 end subroutine bisection_method
772
773 !> Find the root of the 4th degree polynomial using the Newton-Ralphson method
774 subroutine newton_method(e_gas, E_rad, c0, c1)
776 double precision, intent(in) :: c0, c1
777 double precision, intent(in) :: E_rad
778 double precision, intent(inout) :: e_gas
779 double precision :: xval, yval, der, deltax
780 integer :: ii
781
782 yval = bigdouble
783 xval = e_gas
784 der = one
785 deltax = one
786 ii = 0
787 !> Compare error with dx = dx/dy dy
788 do while(abs(deltax) .gt. fld_bisect_tol)
789 yval = polynomial_bisection(xval, c0, c1)
790 der = dpolynomial_bisection(xval, c0, c1)
791 deltax = -yval/der
792 xval = xval + deltax
793 ii = ii + 1
794 if(ii .gt. 1d3) then
795 print*, 'skip to bisection algorithm'
796 call bisection_method(e_gas, e_rad, c0, c1)
797 return
798 endif
799 enddo
800 e_gas = xval
801 end subroutine newton_method
802
803 !> Find the root of the 4th degree polynomial using the Halley method
804 subroutine halley_method(e_gas, E_rad, c0, c1)
806 double precision, intent(in) :: c0, c1
807 double precision, intent(in) :: E_rad
808 double precision, intent(inout) :: e_gas
809 double precision :: xval, yval, der, dder, deltax
810 integer :: ii
811
812 yval = bigdouble
813 xval = e_gas
814 der = one
815 dder = one
816 deltax = one
817 ii = 0
818 !> Compare error with dx = dx/dy dy
819 do while (abs(deltax) .gt. fld_bisect_tol)
820 yval = polynomial_bisection(xval, c0, c1)
821 der = dpolynomial_bisection(xval, c0, c1)
822 dder = ddpolynomial_bisection(xval, c0, c1)
823 deltax = -two*yval*der/(two*der**2 - yval*dder)
824 xval = xval + deltax
825 ii = ii + 1
826 if(ii .gt. 1d3) then
827 call newton_method(e_gas, e_rad, c0, c1)
828 return
829 endif
830 enddo
831 e_gas = xval
832 end subroutine halley_method
833
834 !> Evaluate polynomial at argument e_gas
835 function polynomial_bisection(e_gas, c0, c1) result(val)
837 double precision, intent(in) :: e_gas
838 double precision, intent(in) :: c0, c1
839 double precision :: val
840
841 val = e_gas**4.d0 + c1*e_gas - c0
842 end function polynomial_bisection
843
844 !> Evaluate first derivative of polynomial at argument e_gas
845 function dpolynomial_bisection(e_gas, c0, c1) result(der)
847 double precision, intent(in) :: e_gas
848 double precision, intent(in) :: c0, c1
849 double precision :: der
850
851 der = 4.d0*e_gas**3.d0 + c1
852 end function dpolynomial_bisection
853
854 !> Evaluate second derivative of polynomial at argument e_gas
855 function ddpolynomial_bisection(e_gas, c0, c1) result(dder)
857 double precision, intent(in) :: e_gas
858 double precision, intent(in) :: c0, c1
859 double precision :: dder
860
861 dder = 4.d0*3.d0*e_gas**2.d0
862 end function ddpolynomial_bisection
863end module mod_fld
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for physical and numeric constants.
Nicolas Moens with updates by RK (16/03/2026) Module for including flux limited diffusion (FLD)-appro...
Definition mod_fld.t:9
subroutine put_diffterm_onegrid(ixil, ixol, w)
inplace update of psa==>F_im(psa)
Definition mod_fld.t:639
subroutine, public fld_get_opacity(w, x, ixil, ixol, fld_kappa)
Sets the opacity in the w-array by calling mod_opal_opacity.
Definition mod_fld.t:193
double precision, public fld_mu
mean particle mass
Definition mod_fld.t:19
double precision, public fld_bisect_tol
Tolerance for bisection method for Energy sourceterms This is a percentage of the minimum of gas- and...
Definition mod_fld.t:22
subroutine energy_interaction(w, x, ixil, ixol, dtfactor, qdt)
Energy interaction and photon tiring.
Definition mod_fld.t:432
double precision, public fld_diff_tol
Tolerance for adi method for radiative Energy diffusion.
Definition mod_fld.t:24
subroutine fld_params_read(files)
public methods these are called in mod_hd_phys or mod_mhd_phys
Definition mod_fld.t:59
logical diffcrash_resume
Resume run when multigrid returns error.
Definition mod_fld.t:37
subroutine update_diffcoeff(psa)
Definition mod_fld.t:697
integer, dimension(:), allocatable, public i_opf
Index for Flux weighted opacities.
Definition mod_fld.t:39
character(len=8) fld_opacity_law
switches for opacity
Definition mod_fld.t:26
double precision function ddpolynomial_bisection(e_gas, c0, c1)
Evaluate second derivative of polynomial at argument e_gas.
Definition mod_fld.t:856
subroutine evaluate_e_rad_mg(qtc, psa)
inplace update of psa==>F_im(psa)
Definition mod_fld.t:618
subroutine, public fld_get_radpress(w, x, ixil, ixol, rad_pressure, nth)
Calculate Radiation Pressure Returns Radiation Pressure as tensor NOTE: w is primitive on entry.
Definition mod_fld.t:395
character(len=16) fld_fluxlimiter
flux limiter choice
Definition mod_fld.t:29
subroutine bisection_method(e_gas, e_rad, c0, c1)
Find the root of the 4th degree polynomial using the bisection method.
Definition mod_fld.t:713
character(len=50) fld_opal_table
Definition mod_fld.t:27
subroutine, public fld_get_diffcoef_central(w, wct, wctprim, x, ixil, ixol, primitives_filled)
Calculates cell-centered diffusion coefficient to be used in multigrid.
Definition mod_fld.t:660
double precision, public fld_kappa0
Opacity per unit of unit_density.
Definition mod_fld.t:17
subroutine, public fld_get_fluxlimiter(w, x, ixil, ixol, fld_lambda, fld_r, nth)
Calculate fld flux limiter This subroutine calculates flux limiter lambda using the prescription stor...
Definition mod_fld.t:232
logical lineforce_opacities
Use or dont use lineforce opacities.
Definition mod_fld.t:35
double precision function polynomial_bisection(e_gas, c0, c1)
Evaluate polynomial at argument e_gas.
Definition mod_fld.t:836
subroutine, public add_fld_rad_force(qdt, ixil, ixol, wct, wctprim, w, x, energy, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO This subroutine handles th...
Definition mod_fld.t:132
subroutine, public fld_init(he_abundance, r_gamma)
Initialising FLD-module: Read opacities Initialise Multigrid adimensionalise kappa Add extra variable...
Definition mod_fld.t:84
logical fld_eint_split
source split for energy interact and radforce:
Definition mod_fld.t:14
subroutine halley_method(e_gas, e_rad, c0, c1)
Find the root of the 4th degree polynomial using the Halley method.
Definition mod_fld.t:805
character(len=8) fld_interaction_method
Which method to find the root for the energy interaction polynomial.
Definition mod_fld.t:33
subroutine newton_method(e_gas, e_rad, c0, c1)
Find the root of the 4th degree polynomial using the Newton-Ralphson method.
Definition mod_fld.t:775
logical fld_radforce_split
Definition mod_fld.t:15
subroutine, public fld_get_radflux(w, x, ixil, ixol, rad_flux, nth)
Calculate Radiation Flux stores radiation flux in w-array.
Definition mod_fld.t:316
double precision function dpolynomial_bisection(e_gas, c0, c1)
Evaluate first derivative of polynomial at argument e_gas.
Definition mod_fld.t:846
subroutine diffuse_e_rad_mg(dtfactor, qdt, qtc, psa, psb)
Calling all subroutines to perform the multigrid method Communicates rad_e and diff_coeff to multigri...
Definition mod_fld.t:535
subroutine, public fld_radforce_get_dt(w, ixil, ixol, dtnew, dxd, x)
get dt limit for radiation force: NOTE: only uniform cartesian here!
Definition mod_fld.t:168
integer i_diff_mg
diffusion coefficient for multigrid method
Definition mod_fld.t:31
subroutine fld_get_eddington(w, x, ixil, ixol, eddington_tensor, nth)
Calculate Eddington-tensor.
Definition mod_fld.t:342
double precision dt_diff
running timestep for diffusion solver, initialised as zero
Definition mod_fld.t:43
subroutine fld_implicit_update(dtfactor, qdt, qtc, psa, psb)
Definition mod_fld.t:412
Module with basic grid data structures.
Definition mod_forest.t:2
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
update ghost cells of all blocks including physical boundaries
subroutine getbc(time, qdt, psb, nwstart, nwbc)
do update ghost cells of all blocks including physical boundaries
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision unit_density
Physical scaling factor for density.
double precision unit_opacity
Physical scaling factor for Opacity.
integer, parameter unitpar
file handle for IO
double precision global_time
The global simulation time.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer it
Number of time steps taken.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
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
double precision courantpar
The Courant (CFL) number used for the simulation.
integer ixm
the mesh range of a physical block without ghost cells
double precision unit_velocity
Physical scaling factor for velocity.
logical time_advance
do time evolving
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
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,...
type(mg_t) mg
Data structure containing the multigrid tree.
subroutine mg_copy_to_tree(iw_from, iw_to, restrict, restrict_gc, factor, state_from)
Copy a variable to the multigrid tree, including a layer of ghost cells.
subroutine mg_copy_from_tree_gc(iw_from, iw_to, state_to)
Copy from multigrid tree with one layer of ghost cells. Corner ghost cells are not used/set.
This module reads in Rosseland-mean opacities from OPAL tables. Table opacity values are given in bas...
subroutine, public init_opal_table(tabledir, set_custom_tabledir)
This subroutine is called when the FLD radiation module is initialised. The OPAL tables for different...
subroutine, public set_opal_opacity(rho, temp, kappa)
This subroutine calculates the opacity for a given temperature-density structure. Opacities are read ...
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_get_tgas), pointer phys_get_tgas
Definition mod_physics.t:71
procedure(sub_evaluate_implicit), pointer phys_evaluate_implicit
Definition mod_physics.t:79
procedure(sub_implicit_update), pointer phys_implicit_update
Definition mod_physics.t:78
Module with all the methods that users can customize in AMRVAC.
procedure(special_opacity), pointer usr_special_opacity
procedure(special_diffcoef), pointer usr_special_diffcoef
procedure(special_fluxlimiter), pointer usr_special_fluxlimiter
procedure(special_opacity_qdot), pointer usr_special_opacity_qdot
integer function var_set_extravar(name_cons, name_prim, ix)
Set extra variable in w, which is not advected and has no boundary conditions. This has to be done af...
The data structure that contains information about a tree node/grid block.
Definition mod_forest.t:11