MPI-AMRVAC  3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
mod_finite_volume.t
Go to the documentation of this file.
1 !> Module with finite volume methods for fluxes
3 #include "amrvac.h"
4  implicit none
5  private
6 
7  public :: finite_volume
8  public :: hancock
9  public :: reconstruct_lr
10 
11 contains
12 
13  !> The non-conservative Hancock predictor for TVDLF
14  !>
15  !> on entry:
16  !> input available on ixI^L=ixG^L asks for output on ixO^L=ixG^L^LSUBnghostcells
17  !> one entry: (predictor): wCT -- w_n wnew -- w_n qdt=dt/2
18  !> on exit : (predictor): wCT -- w_n wnew -- w_n+1/2
19  subroutine hancock(qdt,dtfactor,ixI^L,ixO^L,idims^LIM,qtC,sCT,qt,snew,dxs,x)
20  use mod_physics
22  use mod_source, only: addsource2
23  use mod_comm_lib, only: mpistop
24 
25  integer, intent(in) :: ixi^l, ixo^l, idims^lim
26  double precision, intent(in) :: qdt, dtfactor,qtc, qt, dxs(ndim), x(ixi^s,1:ndim)
27  type(state) :: sct, snew
28 
29  double precision, dimension(ixI^S,1:nw) :: wprim, wlc, wrc
30  ! left and right constructed status in primitive form, needed for better performance
31  double precision, dimension(ixI^S,1:nw) :: wlp, wrp
32  double precision, dimension(ixO^S) :: inv_volume
33  double precision :: flc(ixi^s, nwflux), frc(ixi^s, nwflux)
34  double precision :: dxinv(1:ndim)
35  integer :: idims, iw, ix^l, hxo^l
36  logical :: active
37 
38  associate(wct=>sct%w,wnew=>snew%w)
39  ! Expand limits in each idims direction in which fluxes are added
40  ix^l=ixo^l;
41  do idims= idims^lim
42  ix^l=ix^l^laddkr(idims,^d);
43  end do
44  if (ixi^l^ltix^l|.or.|.or.) &
45  call mpistop("Error in Hancock: Nonconforming input limits")
46 
47  wrp=0.d0
48  wlp=0.d0
49  wprim=wct
50  call phys_to_primitive(ixi^l,ixi^l,wprim,x)
51 
52  dxinv=-qdt/dxs
53  if(.not.slab_uniform) inv_volume = 1.d0/block%dvolume(ixo^s)
54  do idims= idims^lim
55  b0i=idims
56  ! Calculate w_j+g_j/2 and w_j-g_j/2
57  ! First copy all variables, then upwind wLC and wRC.
58  ! wLC is to the left of ixO, wRC is to the right of wCT.
59  hxo^l=ixo^l-kr(idims,^d);
60 
61  wrp(hxo^s,1:nwflux)=wprim(ixo^s,1:nwflux)
62  wlp(ixo^s,1:nwflux)=wprim(ixo^s,1:nwflux)
63 
64  ! apply limited reconstruction for left and right status at cell interfaces
65  call reconstruct_lr(ixi^l,ixo^l,hxo^l,idims,wprim,wlc,wrc,wlp,wrp,x,dxs(idims))
66 
67  ! Calculate the fLC and fRC fluxes
68  call phys_get_flux(wrc,wrp,x,ixi^l,hxo^l,idims,frc)
69  call phys_get_flux(wlc,wlp,x,ixi^l,ixo^l,idims,flc)
70 
71  ! Advect w(iw)
72  if (slab_uniform) then
73  if(local_timestep) then
74  do iw=1,nwflux
75  wnew(ixo^s,iw)=wnew(ixo^s,iw)-block%dt(ixo^s)*dtfactor/dxs(idims)* &
76  (flc(ixo^s, iw)-frc(hxo^s, iw))
77  end do
78  else
79  do iw=1,nwflux
80  wnew(ixo^s,iw)=wnew(ixo^s,iw)+dxinv(idims)* &
81  (flc(ixo^s, iw)-frc(hxo^s, iw))
82  end do
83  endif
84  else
85  if(local_timestep) then
86  do iw=1,nwflux
87  wnew(ixo^s,iw)=wnew(ixo^s,iw) - block%dt(ixo^s)*dtfactor * inv_volume &
88  *(block%surfaceC(ixo^s,idims)*flc(ixo^s, iw) &
89  -block%surfaceC(hxo^s,idims)*frc(hxo^s, iw))
90  end do
91  else
92  do iw=1,nwflux
93  wnew(ixo^s,iw)=wnew(ixo^s,iw) - qdt * inv_volume &
94  *(block%surfaceC(ixo^s,idims)*flc(ixo^s, iw) &
95  -block%surfaceC(hxo^s,idims)*frc(hxo^s, iw))
96  end do
97  end if
98  end if
99  end do ! next idims
100  b0i=0
101 
102  if (.not.slab.and.idimsmin==1) call phys_add_source_geom(qdt,dtfactor,ixi^l,ixo^l,wct,wnew,x)
103 
104  call addsource2(qdt*dble(idimsmax-idimsmin+1)/dble(ndim), &
105  dtfactor*dble(idimsmax-idimsmin+1)/dble(ndim),&
106  ixi^l,ixo^l,1,nw,qtc,wct,wprim,qt,wnew,x,.false.,active)
107 
108  ! check and optionally correct unphysical values
109  if(fix_small_values) then
110  call phys_handle_small_values(.false.,wnew,x,ixi^l,ixo^l,'exit hancock finite_volume')
111  endif
112  end associate
113  end subroutine hancock
114 
115  !> finite volume method
116  subroutine finite_volume(method,qdt,dtfactor,ixI^L,ixO^L,idims^LIM, &
117  qtC,sCT,qt,snew,fC,fE,dxs,x)
118  use mod_physics
119  use mod_variables
121  use mod_tvd, only:tvdlimit2
122  use mod_source, only: addsource2
123  use mod_usr_methods
124  use mod_comm_lib, only: mpistop
125 
126  integer, intent(in) :: method
127  double precision, intent(in) :: qdt, dtfactor, qtc, qt, dxs(ndim)
128  integer, intent(in) :: ixi^l, ixo^l, idims^lim
129  double precision, dimension(ixI^S,1:ndim), intent(in) :: x
130  type(state) :: sct, snew
131  double precision, dimension(ixI^S,1:nwflux,1:ndim) :: fc
132  double precision, dimension(ixI^S,sdim:3) :: fe
133 
134  ! primitive w at cell center
135  double precision, dimension(ixI^S,1:nw) :: wprim, wcons
136  ! left and right constructed status in conservative form
137  double precision, dimension(ixI^S,1:nw) :: wlc, wrc
138  ! left and right constructed status in primitive form, needed for better performance
139  double precision, dimension(ixI^S,1:nw) :: wlp, wrp
140  double precision, dimension(ixI^S,1:nwflux) :: flc, frc
141  double precision, dimension(ixI^S,1:number_species) :: cmaxc
142  double precision, dimension(ixI^S,1:number_species) :: cminc
143  double precision, dimension(ixI^S) :: hspeed
144  double precision, dimension(ixO^S) :: inv_volume
145  double precision, dimension(1:ndim) :: dxinv
146  integer, dimension(ixI^S) :: patchf
147  integer :: idims, iw, ix^l, hxo^l, ixc^l, jxc^l,ixcr^l, kxc^l, kxr^l, ii
148  logical :: active
149  type(ct_velocity) :: vcts
150 
151  associate(wct=>sct%w, wnew=>snew%w)
152 
153  fc=0.d0
154  flc=0.d0
155  frc=0.d0
156  wlp=0.d0
157  wrp=0.d0
158 
159  ! The flux calculation contracts by one in the idims direction it is applied.
160  ! The limiter contracts the same directions by one more, so expand ixO by 2.
161  ix^l=ixo^l;
162  do idims= idims^lim
163  ix^l=ix^l^ladd2*kr(idims,^d);
164  end do
165  if (ixi^l^ltix^l|.or.|.or.) &
166  call mpistop("Error in fv : Nonconforming input limits")
167 
168  wprim=wct
169  wcons=wct
170  call phys_to_primitive(ixi^l,ixi^l,wprim,x)
171 
172  do idims= idims^lim
173  ! use interface value of w0 at idims
174  b0i=idims
175 
176  hxo^l=ixo^l-kr(idims,^d);
177 
178  kxcmin^d=iximin^d; kxcmax^d=iximax^d-kr(idims,^d);
179  kxr^l=kxc^l+kr(idims,^d);
180 
181  if(stagger_grid) then
182  ! ct needs all transverse cells
183  ixcmax^d=ixomax^d+nghostcells-nghostcells*kr(idims,^d);
184  ixcmin^d=hxomin^d-nghostcells+nghostcells*kr(idims,^d);
185  else
186  ! ixC is centered index in the idims direction from ixOmin-1/2 to ixOmax+1/2
187  ixcmax^d=ixomax^d; ixcmin^d=hxomin^d;
188  end if
189 
190  ! wRp and wLp are defined at the same locations, and will correspond to
191  ! the left and right reconstructed values at a cell face. Their indexing
192  ! is similar to cell-centered values, but in direction idims they are
193  ! shifted half a cell towards the 'lower' direction.
194  wrp(kxc^s,1:nw)=wprim(kxr^s,1:nw)
195  wlp(kxc^s,1:nw)=wprim(kxc^s,1:nw)
196 
197  ! Determine stencil size
198  {ixcrmin^d = max(ixcmin^d - phys_wider_stencil,ixglo^d)\}
199  {ixcrmax^d = min(ixcmax^d + phys_wider_stencil,ixghi^d)\}
200  ! apply limited reconstruction for left and right status at cell interfaces
201  call reconstruct_lr(ixi^l,ixcr^l,ixcr^l,idims,wprim,wlc,wrc,wlp,wrp,x,dxs(idims))
202 
203  ! special modification of left and right status before flux evaluation
204  call phys_modify_wlr(ixi^l,ixcr^l,qt,wlc,wrc,wlp,wrp,sct,idims)
205 
206  ! evaluate physical fluxes according to reconstructed status
207  call phys_get_flux(wlc,wlp,x,ixi^l,ixc^l,idims,flc)
208  call phys_get_flux(wrc,wrp,x,ixi^l,ixc^l,idims,frc)
209 
210  if(h_correction) then
211  call phys_get_h_speed(wprim,x,ixi^l,ixo^l,idims,hspeed)
212  end if
213  ! estimating bounds for the minimum and maximum signal velocities
214  if(method==fs_tvdlf.or.method==fs_tvdmu) then
215  call phys_get_cbounds(wlc,wrc,wlp,wrp,x,ixi^l,ixc^l,idims,hspeed,cmaxc)
216  ! index of var velocity appears in the induction eq.
217  if(stagger_grid) call phys_get_ct_velocity(vcts,wlp,wrp,ixi^l,ixc^l,idims,cmaxc(ixi^s,index_v_mag))
218  else
219  call phys_get_cbounds(wlc,wrc,wlp,wrp,x,ixi^l,ixc^l,idims,hspeed,cmaxc,cminc)
220  if(stagger_grid) call phys_get_ct_velocity(vcts,wlp,wrp,ixi^l,ixc^l,idims,cmaxc(ixi^s,index_v_mag),cminc(ixi^s,index_v_mag))
221  end if
222 
223  ! use approximate Riemann solver to get flux at interfaces
224  select case(method)
225  case(fs_hll)
226  do ii=1,number_species
227  call get_riemann_flux_hll(start_indices(ii),stop_indices(ii))
228  end do
229  case(fs_hllc,fs_hllcd)
230  do ii=1,number_species
231  call get_riemann_flux_hllc(start_indices(ii),stop_indices(ii))
232  end do
233  case(fs_hlld)
234  do ii=1,number_species
235  if(ii==index_v_mag) then
236  call get_riemann_flux_hlld(start_indices(ii),stop_indices(ii))
237  else
238  call get_riemann_flux_hll(start_indices(ii),stop_indices(ii))
239  endif
240  end do
241  case(fs_tvdlf)
242  do ii=1,number_species
243  call get_riemann_flux_tvdlf(start_indices(ii),stop_indices(ii))
244  end do
245  case(fs_tvdmu)
247  case default
248  call mpistop('unkown Riemann flux in finite volume')
249  end select
250 
251  end do ! Next idims
252  b0i=0
253  if(stagger_grid) call phys_update_faces(ixi^l,ixo^l,qt,qdt,wprim,fc,fe,sct,snew,vcts)
254  if(slab_uniform) then
255  dxinv=-qdt/dxs
256  do idims= idims^lim
257  hxo^l=ixo^l-kr(idims,^d);
258  ! TODO maybe put if outside loop idims: but too much code is copy pasted
259  ! this is also done in hancock and fd, centdiff in mod_finite_difference
260  if(local_timestep) then
261  do iw=iwstart,nwflux
262  fc(ixi^s,iw,idims)=-block%dt(ixi^s)*dtfactor/dxs(idims)*fc(ixi^s,iw,idims)
263  end do
264  else
265  ! Multiply the fluxes by -dt/dx since Flux fixing expects this
266  fc(ixi^s,1:nwflux,idims)=dxinv(idims)*fc(ixi^s,1:nwflux,idims)
267  end if
268 
269  wnew(ixo^s,iwstart:nwflux)=wnew(ixo^s,iwstart:nwflux)+&
270  (fc(ixo^s,iwstart:nwflux,idims)-fc(hxo^s,iwstart:nwflux,idims))
271 
272  ! For the MUSCL scheme apply the characteristic based limiter
273  if(method==fs_tvdmu) &
274  call tvdlimit2(method,qdt,ixi^l,ixc^l,ixo^l,idims,wlc,wrc,wnew,x,fc,dxs)
275 
276  end do ! Next idims
277  else
278  inv_volume = 1.d0/block%dvolume(ixo^s)
279  do idims= idims^lim
280  hxo^l=ixo^l-kr(idims,^d);
281 
282  if(local_timestep) then
283  do iw=iwstart,nwflux
284  fc(ixi^s,iw,idims)=-block%dt(ixi^s)*dtfactor*fc(ixi^s,iw,idims)*block%surfaceC(ixi^s,idims)
285  wnew(ixo^s,iw)=wnew(ixo^s,iw) + (fc(ixo^s,iw,idims)-fc(hxo^s,iw,idims)) * &
286  inv_volume
287  end do
288  else
289  do iw=iwstart,nwflux
290  fc(ixi^s,iw,idims)=-qdt*fc(ixi^s,iw,idims)*block%surfaceC(ixi^s,idims)
291  wnew(ixo^s,iw)=wnew(ixo^s,iw) + (fc(ixo^s,iw,idims)-fc(hxo^s,iw,idims)) * &
292  inv_volume
293  end do
294  end if
295  ! For the MUSCL scheme apply the characteristic based limiter
296  if (method==fs_tvdmu) &
297  call tvdlimit2(method,qdt,ixi^l,ixc^l,ixo^l,idims,wlc,wrc,wnew,x,fc,dxs)
298 
299  end do ! Next idims
300  end if
301 
302  if (.not.slab.and.idimsmin==1) &
303  call phys_add_source_geom(qdt,dtfactor,ixi^l,ixo^l,wct,wnew,x)
304 
305  if(stagger_grid) call phys_face_to_center(ixo^l,snew)
306 
307  ! check and optionally correct unphysical values
308  if(fix_small_values) then
309  call phys_handle_small_values(.false.,wnew,x,ixi^l,ixo^l,'multi-D finite_volume')
310  if(crash) then
311  ! replace erroneous values with values at previous step
312  wnew=wct
313  if(stagger_grid) snew%ws=sct%ws
314  end if
315  end if
316 
317  call addsource2(qdt*dble(idimsmax-idimsmin+1)/dble(ndim),&
318  dtfactor*dble(idimsmax-idimsmin+1)/dble(ndim),&
319  ixi^l,ixo^l,1,nw,qtc,wct,wprim,qt,wnew,x,.false.,active)
320 
321  end associate
322  contains
323 
325  do iw=iwstart,nwflux
326  ! To save memory we use fLC to store (F_L+F_R)/2=half*(fLC+fRC)
327  flc(ixc^s, iw)=half*(flc(ixc^s, iw)+frc(ixc^s, iw))
328  fc(ixc^s,iw,idims)=flc(ixc^s, iw)
329  end do
330  end subroutine get_riemann_flux_tvdmu
331 
332  subroutine get_riemann_flux_tvdlf(iws,iwe)
333  integer, intent(in) :: iws,iwe
334  double precision :: fac(ixC^S),phi(ixC^S)
335 
336  jxc^l=ixc^l+kr(idims,^d);
337  fac(ixc^s) = -0.5d0*tvdlfeps*cmaxc(ixc^s,ii)
338  ! Calculate fLC=f(uL_j+1/2) and fRC=f(uR_j+1/2) for each iw
339  do iw=iws,iwe
340  ! To save memory we use fLC to store (F_L+F_R)/2=half*(fLC+fRC)
341  flc(ixc^s, iw)=0.5d0*(flc(ixc^s, iw)+frc(ixc^s, iw))
342  ! Add TVDLF dissipation to the flux
343  if(flux_type(idims, iw) /= flux_no_dissipation) then
344  if(flux_adaptive_diffusion) then
345  !> adaptive diffusion from Rempel et al. 2009, see also Rempel et al. 2014
346  !> the previous version is adopt
347  phi=zero
348  where(((wrc(ixc^s,iw)-wlc(ixc^s,iw))*(wcons(jxc^s,iw)-wcons(ixc^s,iw))) .gt. 1.e-18)
349  phi(ixc^s)=min((wrc(ixc^s,iw)-wlc(ixc^s,iw))**2/((wcons(jxc^s,iw)-wcons(ixc^s,iw))**2+1.e-18),one)
350  endwhere
351  else
352  phi=one
353  end if
354  flc(ixc^s,iw)=flc(ixc^s,iw) + fac(ixc^s)*(wrc(ixc^s,iw)-wlc(ixc^s,iw))*phi(ixc^s)
355  end if
356  fc(ixc^s,iw,idims)=flc(ixc^s, iw)
357  end do ! Next iw
358  end subroutine get_riemann_flux_tvdlf
359 
360  subroutine get_riemann_flux_hll(iws,iwe)
361  integer, intent(in) :: iws,iwe
362  integer :: ix^D
363  double precision :: phi(ixI^S)
364 
365  do iw=iws,iwe
366  if(flux_type(idims, iw) == flux_tvdlf) then
367  ! CT MHD does not need normal B flux
368  if(stagger_grid) cycle
369  fc(ixc^s,iw,idims) = -tvdlfeps*half*max(cmaxc(ixc^s,ii),dabs(cminc(ixc^s,ii))) * &
370  (wrc(ixc^s,iw)-wlc(ixc^s,iw))
371  else
372  {do ix^db=ixcmin^db,ixcmax^db\}
373  if(cminc(ix^d,ii) >= zero) then
374  fc(ix^d,iw,idims)=flc(ix^d,iw)
375  else if(cmaxc(ix^d,ii) <= zero) then
376  fc(ix^d,iw,idims)=frc(ix^d,iw)
377  else
378  ! Add hll dissipation to the flux
379  if(flux_adaptive_diffusion) then
380  !> reduced diffusion is from Wang et al. 2024
381  phi(ix^d)=max(abs(cmaxc(ix^d,ii)),abs(cminc(ix^d,ii)))/(cmaxc(ix^d,ii)-cminc(ix^d,ii))
382  fc(ix^d,iw,idims)=(cmaxc(ix^d,ii)*flc(ix^d, iw)-cminc(ix^d,ii)*frc(ix^d,iw)&
383  +phi(ix^d)*cminc(ix^d,ii)*cmaxc(ix^d,ii)*(wrc(ix^d,iw)-wlc(ix^d,iw)))&
384  /(cmaxc(ix^d,ii)-cminc(ix^d,ii))
385  else
386  fc(ix^d,iw,idims)=(cmaxc(ix^d,ii)*flc(ix^d, iw)-cminc(ix^d,ii)*frc(ix^d,iw)&
387  +cminc(ix^d,ii)*cmaxc(ix^d,ii)*(wrc(ix^d,iw)-wlc(ix^d,iw)))&
388  /(cmaxc(ix^d,ii)-cminc(ix^d,ii))
389  end if
390  end if
391  {end do\}
392  endif
393  end do
394  end subroutine get_riemann_flux_hll
395 
396  subroutine get_riemann_flux_hllc(iws,iwe)
397  integer, intent(in) :: iws, iwe
398  double precision, dimension(ixI^S,1:nwflux) :: whll, Fhll, fCD
399  double precision, dimension(ixI^S) :: lambdaCD
400 
401  integer :: rho_, p_, e_, mom(1:ndir)
402 
403  rho_ = iw_rho
404  if (allocated(iw_mom)) mom(:) = iw_mom(:)
405  e_ = iw_e
406 
407  if(associated(phys_hllc_init_species)) then
408  call phys_hllc_init_species(ii, rho_, mom(:), e_)
409  endif
410 
411  p_ = e_
412 
413  patchf(ixc^s) = 1
414  where(cminc(ixc^s,1) >= zero)
415  patchf(ixc^s) = -2
416  elsewhere(cmaxc(ixc^s,1) <= zero)
417  patchf(ixc^s) = 2
418  endwhere
419  ! Use more diffusive scheme, is actually TVDLF and selected by patchf=4
420  if(method==fs_hllcd) &
421  call phys_diffuse_hllcd(ixi^l,ixc^l,idims,wlc,wrc,flc,frc,patchf)
422 
423  !---- calculate speed lambda at CD ----!
424  if(any(patchf(ixc^s)==1)) &
425  call phys_get_lcd(wlc,wrc,flc,frc,cminc(ixi^s,ii),cmaxc(ixi^s,ii),idims,ixi^l,ixc^l, &
426  whll,fhll,lambdacd,patchf)
427 
428  ! now patchf may be -1 or 1 due to phys_get_lCD
429  if(any(abs(patchf(ixc^s))== 1))then
430  !======== flux at intermediate state ========!
431  call phys_get_wcd(wlc,wrc,whll,frc,flc,fhll,patchf,lambdacd,&
432  cminc(ixi^s,ii),cmaxc(ixi^s,ii),ixi^l,ixc^l,idims,fcd)
433  endif ! Calculate the CD flux
434 
435  do iw=iws,iwe
436  if (flux_type(idims, iw) == flux_tvdlf) then
437  flc(ixc^s,iw)=-tvdlfeps*half*max(cmaxc(ixc^s,ii),abs(cminc(ixc^s,ii))) * &
438  (wrc(ixc^s,iw) - wlc(ixc^s,iw))
439  else
440  where(patchf(ixc^s)==-2)
441  flc(ixc^s,iw)=flc(ixc^s,iw)
442  elsewhere(abs(patchf(ixc^s))==1)
443  flc(ixc^s,iw)=fcd(ixc^s,iw)
444  elsewhere(patchf(ixc^s)==2)
445  flc(ixc^s,iw)=frc(ixc^s,iw)
446  elsewhere(patchf(ixc^s)==3)
447  ! fallback option, reducing to HLL flux
448  flc(ixc^s,iw)=fhll(ixc^s,iw)
449  elsewhere(patchf(ixc^s)==4)
450  ! fallback option, reducing to TVDLF flux
451  flc(ixc^s,iw) = half*((flc(ixc^s,iw)+frc(ixc^s,iw)) &
452  -tvdlfeps * max(cmaxc(ixc^s,ii), dabs(cminc(ixc^s,ii))) * &
453  (wrc(ixc^s,iw)-wlc(ixc^s,iw)))
454  endwhere
455  end if
456 
457  fc(ixc^s,iw,idims)=flc(ixc^s,iw)
458 
459  end do ! Next iw
460  end subroutine get_riemann_flux_hllc
461 
462  !> HLLD Riemann flux from Miyoshi 2005 JCP, 208, 315 and Guo 2016 JCP, 327, 543
463  subroutine get_riemann_flux_hlld(iws,iwe)
464  integer, intent(in) :: iws, iwe
465  double precision, dimension(ixI^S,1:nwflux) :: w1R,w1L,f1R,f1L,f2R,f2L
466  double precision, dimension(ixI^S,1:nwflux) :: w2R,w2L
467  double precision, dimension(ixI^S) :: sm,s1R,s1L,suR,suL,Bx
468  double precision, dimension(ixI^S) :: pts,ptR,ptL,signBx,r1L,r1R,tmp
469  ! velocity from the right and the left reconstruction
470  double precision, dimension(ixI^S,ndir) :: vRC, vLC
471  ! magnetic field from the right and the left reconstruction
472  double precision, dimension(ixI^S,ndir) :: BR, BL
473  integer :: ip1,ip2,ip3,idir,ix^D
474  integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
475 
476  associate(sr=>cmaxc,sl=>cminc)
477 
478  rho_ = iw_rho
479  mom(:) = iw_mom(:)
480  mag(:) = iw_mag(:)
481  e_ = iw_e
482  p_ = e_
483 
484  f1r=0.d0
485  f1l=0.d0
486  f2r=0.d0
487  f2l=0.d0
488  w1l=0.d0
489  w1r=0.d0
490  w2l=0.d0
491  w2r=0.d0
492  ip1=idims
493  ip3=3
494  vrc(ixc^s,:)=wrp(ixc^s,mom(:))
495  vlc(ixc^s,:)=wlp(ixc^s,mom(:))
496  if(b0field) then
497  br(ixc^s,:)=wrc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
498  bl(ixc^s,:)=wlc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
499  else
500  br(ixc^s,:)=wrc(ixc^s,mag(:))
501  bl(ixc^s,:)=wlc(ixc^s,mag(:))
502  end if
503  if(stagger_grid) then
504  bx(ixc^s)=block%ws(ixc^s,ip1)
505  else
506  ! HLL estimation of normal magnetic field at cell interfaces
507  ! Li, Shenghai, 2005 JCP, 203, 344, equation (33)
508  bx(ixc^s)=(sr(ixc^s,ii)*br(ixc^s,ip1)-sl(ixc^s,ii)*bl(ixc^s,ip1))/(sr(ixc^s,ii)-sl(ixc^s,ii))
509  end if
510  ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(br(ixc^s,:)**2,dim=ndim+1)
511  ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(bl(ixc^s,:)**2,dim=ndim+1)
512  if(iw_equi_rho>0) then
513  sur(ixc^s) = wrc(ixc^s,rho_)+ block%equi_vars(ixc^s,iw_equi_rho,ip1)
514  else
515  sur(ixc^s) = wrc(ixc^s,rho_)
516  endif
517  sur(ixc^s)=(sr(ixc^s,ii)-vrc(ixc^s,ip1))*sur(ixc^s)
518  if(iw_equi_rho>0) then
519  sul(ixc^s) = wlc(ixc^s,rho_)+ block%equi_vars(ixc^s,iw_equi_rho,ip1)
520  else
521  sul(ixc^s) = wlc(ixc^s,rho_)
522  endif
523  sul(ixc^s)=(sl(ixc^s,ii)-vlc(ixc^s,ip1))*sul(ixc^s)
524  ! Miyoshi equation (38) and Guo euqation (20)
525  sm(ixc^s)=(sur(ixc^s)*vrc(ixc^s,ip1)-sul(ixc^s)*vlc(ixc^s,ip1)-&
526  ptr(ixc^s)+ptl(ixc^s))/(sur(ixc^s)-sul(ixc^s))
527  ! Miyoshi equation (39) and Guo euqation (28)
528  w1r(ixc^s,mom(ip1))=sm(ixc^s)
529  w1l(ixc^s,mom(ip1))=sm(ixc^s)
530  w2r(ixc^s,mom(ip1))=sm(ixc^s)
531  w2l(ixc^s,mom(ip1))=sm(ixc^s)
532  ! Guo equation (22)
533  w1r(ixc^s,mag(ip1))=bx(ixc^s)
534  w1l(ixc^s,mag(ip1))=bx(ixc^s)
535  if(b0field) then
536  ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(wrc(ixc^s,mag(:))**2,dim=ndim+1)
537  ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(wlc(ixc^s,mag(:))**2,dim=ndim+1)
538  end if
539 
540  ! Miyoshi equation (43) and Guo equation (27)
541  w1r(ixc^s,rho_)=sur(ixc^s)/(sr(ixc^s,ii)-sm(ixc^s))
542  w1l(ixc^s,rho_)=sul(ixc^s)/(sl(ixc^s,ii)-sm(ixc^s))
543 
544  ip2=mod(ip1+1,ndir)
545  if(ip2==0) ip2=ndir
546  r1r(ixc^s)=sur(ixc^s)*(sr(ixc^s,ii)-sm(ixc^s))-bx(ixc^s)**2
547  where(abs(r1r(ixc^s))>smalldouble)
548  r1r(ixc^s)=1.d0/r1r(ixc^s)
549  else where
550  r1r(ixc^s)=0.d0
551  end where
552  r1l(ixc^s)=sul(ixc^s)*(sl(ixc^s,ii)-sm(ixc^s))-bx(ixc^s)**2
553  where(abs(r1l(ixc^s))>smalldouble)
554  r1l(ixc^s)=1.d0/r1l(ixc^s)
555  else where
556  r1l(ixc^s)=0.d0
557  end where
558  ! Miyoshi equation (44)
559  w1r(ixc^s,mom(ip2))=vrc(ixc^s,ip2)-bx(ixc^s)*br(ixc^s,ip2)*&
560  (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
561  w1l(ixc^s,mom(ip2))=vlc(ixc^s,ip2)-bx(ixc^s)*bl(ixc^s,ip2)*&
562  (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
563  ! partial solution for later usage
564  w1r(ixc^s,mag(ip2))=(sur(ixc^s)*(sr(ixc^s,ii)-vrc(ixc^s,ip1))-bx(ixc^s)**2)*r1r(ixc^s)
565  w1l(ixc^s,mag(ip2))=(sul(ixc^s)*(sl(ixc^s,ii)-vlc(ixc^s,ip1))-bx(ixc^s)**2)*r1l(ixc^s)
566  if(ndir==3) then
567  ip3=mod(ip1+2,ndir)
568  if(ip3==0) ip3=ndir
569  ! Miyoshi equation (46)
570  w1r(ixc^s,mom(ip3))=vrc(ixc^s,ip3)-bx(ixc^s)*br(ixc^s,ip3)*&
571  (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
572  w1l(ixc^s,mom(ip3))=vlc(ixc^s,ip3)-bx(ixc^s)*bl(ixc^s,ip3)*&
573  (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
574  ! Miyoshi equation (47)
575  w1r(ixc^s,mag(ip3))=br(ixc^s,ip3)*w1r(ixc^s,mag(ip2))
576  w1l(ixc^s,mag(ip3))=bl(ixc^s,ip3)*w1l(ixc^s,mag(ip2))
577  end if
578  ! Miyoshi equation (45)
579  w1r(ixc^s,mag(ip2))=br(ixc^s,ip2)*w1r(ixc^s,mag(ip2))
580  w1l(ixc^s,mag(ip2))=bl(ixc^s,ip2)*w1l(ixc^s,mag(ip2))
581  if(b0field) then
582  ! Guo equation (26)
583  w1r(ixc^s,mag(:))=w1r(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
584  w1l(ixc^s,mag(:))=w1l(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
585  end if
586  ! equation (48)
587  if(phys_energy) then
588  ! Guo equation (25) equivalent to Miyoshi equation (41)
589  w1r(ixc^s,p_)=sur(ixc^s)*(sm(ixc^s)-vrc(ixc^s,ip1))+ptr(ixc^s)
590  !w1L(ixC^S,p_)=suL(ixC^S)*(sm(ixC^S)-vLC(ixC^S,ip1))+ptL(ixC^S)
591  w1l(ixc^s,p_)=w1r(ixc^s,p_)
592  if(b0field) then
593  ! Guo equation (32)
594  w1r(ixc^s,p_)=w1r(ixc^s,p_)+sum(block%B0(ixc^s,:,ip1)*(wrc(ixc^s,mag(:))-w1r(ixc^s,mag(:))),dim=ndim+1)
595  w1l(ixc^s,p_)=w1l(ixc^s,p_)+sum(block%B0(ixc^s,:,ip1)*(wlc(ixc^s,mag(:))-w1l(ixc^s,mag(:))),dim=ndim+1)
596  end if
597  ! Miyoshi equation (48) and main part of Guo euqation (31)
598  w1r(ixc^s,e_)=((sr(ixc^s,ii)-vrc(ixc^s,ip1))*wrc(ixc^s,e_)-ptr(ixc^s)*vrc(ixc^s,ip1)+&
599  w1r(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vrc(ixc^s,:)*wrc(ixc^s,mag(:)),dim=ndim+1)-&
600  sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)))/(sr(ixc^s,ii)-sm(ixc^s))
601  w1l(ixc^s,e_)=((sl(ixc^s,ii)-vlc(ixc^s,ip1))*wlc(ixc^s,e_)-ptl(ixc^s)*vlc(ixc^s,ip1)+&
602  w1l(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vlc(ixc^s,:)*wlc(ixc^s,mag(:)),dim=ndim+1)-&
603  sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)))/(sl(ixc^s,ii)-sm(ixc^s))
604  if(b0field) then
605  ! Guo equation (31)
606  w1r(ixc^s,e_)=w1r(ixc^s,e_)+(sum(w1r(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
607  sum(wrc(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*vrc(ixc^s,ip1))/(sr(ixc^s,ii)-sm(ixc^s))
608  w1l(ixc^s,e_)=w1l(ixc^s,e_)+(sum(w1l(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
609  sum(wlc(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*vlc(ixc^s,ip1))/(sl(ixc^s,ii)-sm(ixc^s))
610  end if
611  if(iw_equi_p>0) then
612 #if !defined(E_RM_W0) || E_RM_W0 == 1
613  w1r(ixc^s,e_)= w1r(ixc^s,e_) + 1d0/(phys_gamma - 1) * block%equi_vars(ixc^s,iw_equi_p,ip1) * &
614  (sm(ixc^s)-vrc(ixc^s,ip1))/(sr(ixc^s,ii)-sm(ixc^s))
615  w1l(ixc^s,e_)= w1l(ixc^s,e_) + 1d0/(phys_gamma - 1) * block%equi_vars(ixc^s,iw_equi_p,ip1) * &
616  (sm(ixc^s)-vlc(ixc^s,ip1))/(sl(ixc^s,ii)-sm(ixc^s))
617 #else
618  w1r(ixc^s,e_)= w1r(ixc^s,e_) + phys_gamma /(phys_gamma - 1) * block%equi_vars(ixc^s,iw_equi_p,ip1) * &
619  (sm(ixc^s)-vrc(ixc^s,ip1))/(sr(ixc^s,ii)-sm(ixc^s))
620  w1l(ixc^s,e_)= w1l(ixc^s,e_) + phys_gamma /(phys_gamma - 1) * block%equi_vars(ixc^s,iw_equi_p,ip1) * &
621  (sm(ixc^s)-vlc(ixc^s,ip1))/(sl(ixc^s,ii)-sm(ixc^s))
622 #endif
623  endif
624  end if
625 
626  ! Miyoshi equation (49) and Guo equation (35)
627  w2r(ixc^s,rho_)=w1r(ixc^s,rho_)
628  w2l(ixc^s,rho_)=w1l(ixc^s,rho_)
629  w2r(ixc^s,mag(ip1))=w1r(ixc^s,mag(ip1))
630  w2l(ixc^s,mag(ip1))=w1l(ixc^s,mag(ip1))
631 
632  r1r(ixc^s)=sqrt(w1r(ixc^s,rho_))
633  r1l(ixc^s)=sqrt(w1l(ixc^s,rho_))
634  tmp(ixc^s)=1.d0/(r1r(ixc^s)+r1l(ixc^s))
635  signbx(ixc^s)=sign(1.d0,bx(ixc^s))
636  ! Miyoshi equation (51) and Guo equation (33)
637  s1r(ixc^s)=sm(ixc^s)+abs(bx(ixc^s))/r1r(ixc^s)
638  s1l(ixc^s)=sm(ixc^s)-abs(bx(ixc^s))/r1l(ixc^s)
639  ! Miyoshi equation (59) and Guo equation (41)
640  w2r(ixc^s,mom(ip2))=(r1l(ixc^s)*w1l(ixc^s,mom(ip2))+r1r(ixc^s)*w1r(ixc^s,mom(ip2))+&
641  (w1r(ixc^s,mag(ip2))-w1l(ixc^s,mag(ip2)))*signbx(ixc^s))*tmp(ixc^s)
642  w2l(ixc^s,mom(ip2))=w2r(ixc^s,mom(ip2))
643  ! Miyoshi equation (61) and Guo equation (43)
644  w2r(ixc^s,mag(ip2))=(r1l(ixc^s)*w1r(ixc^s,mag(ip2))+r1r(ixc^s)*w1l(ixc^s,mag(ip2))+&
645  r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip2))-w1l(ixc^s,mom(ip2)))*signbx(ixc^s))*tmp(ixc^s)
646  w2l(ixc^s,mag(ip2))=w2r(ixc^s,mag(ip2))
647  if(ndir==3) then
648  ! Miyoshi equation (60) and Guo equation (42)
649  w2r(ixc^s,mom(ip3))=(r1l(ixc^s)*w1l(ixc^s,mom(ip3))+r1r(ixc^s)*w1r(ixc^s,mom(ip3))+&
650  (w1r(ixc^s,mag(ip3))-w1l(ixc^s,mag(ip3)))*signbx(ixc^s))*tmp(ixc^s)
651  w2l(ixc^s,mom(ip3))=w2r(ixc^s,mom(ip3))
652  ! Miyoshi equation (62) and Guo equation (44)
653  w2r(ixc^s,mag(ip3))=(r1l(ixc^s)*w1r(ixc^s,mag(ip3))+r1r(ixc^s)*w1l(ixc^s,mag(ip3))+&
654  r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip3))-w1l(ixc^s,mom(ip3)))*signbx(ixc^s))*tmp(ixc^s)
655  w2l(ixc^s,mag(ip3))=w2r(ixc^s,mag(ip3))
656  end if
657  ! Miyoshi equation (63) and Guo equation (45)
658  if(phys_energy) then
659  w2r(ixc^s,e_)=w1r(ixc^s,e_)+r1r(ixc^s)*(sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)-&
660  sum(w2r(ixc^s,mom(:))*w2r(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
661  w2l(ixc^s,e_)=w1l(ixc^s,e_)-r1l(ixc^s)*(sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)-&
662  sum(w2l(ixc^s,mom(:))*w2l(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
663  end if
664 
665  ! convert velocity to momentum
666  do idir=1,ndir
667  w1r(ixc^s,mom(idir))=w1r(ixc^s,mom(idir))*w1r(ixc^s,rho_)
668  w1l(ixc^s,mom(idir))=w1l(ixc^s,mom(idir))*w1l(ixc^s,rho_)
669  w2r(ixc^s,mom(idir))=w2r(ixc^s,mom(idir))*w2r(ixc^s,rho_)
670  w2l(ixc^s,mom(idir))=w2l(ixc^s,mom(idir))*w2l(ixc^s,rho_)
671  end do
672  if(iw_equi_rho>0) then
673  w1r(ixc^s,rho_) = w1r(ixc^s,rho_) - block%equi_vars(ixc^s,iw_equi_rho,ip1)
674  w1l(ixc^s,rho_) = w1l(ixc^s,rho_) - block%equi_vars(ixc^s,iw_equi_rho,ip1)
675  w2r(ixc^s,rho_) = w2r(ixc^s,rho_) - block%equi_vars(ixc^s,iw_equi_rho,ip1)
676  w2l(ixc^s,rho_) = w2l(ixc^s,rho_) - block%equi_vars(ixc^s,iw_equi_rho,ip1)
677  endif
678  ! get fluxes of intermedate states
679  do iw=iws,iwe
680  if(flux_type(idims, iw) == flux_special) then
681  ! known flux (fLC=fRC) for normal B and psi_ in GLM method
682  f1l(ixc^s,iw)=flc(ixc^s,iw)
683  f1r(ixc^s,iw)=f1l(ixc^s,iw)
684  f2l(ixc^s,iw)=f1l(ixc^s,iw)
685  f2r(ixc^s,iw)=f1l(ixc^s,iw)
686  else if(flux_type(idims, iw) == flux_hll) then
687  ! using hll flux for tracers
688  f1l(ixc^s,iw)=(sr(ixc^s,ii)*flc(ixc^s, iw)-sl(ixc^s,ii)*frc(ixc^s, iw) &
689  +sr(ixc^s,ii)*sl(ixc^s,ii)*(wrc(ixc^s,iw)-wlc(ixc^s,iw)))/(sr(ixc^s,ii)-sl(ixc^s,ii))
690  f1r(ixc^s,iw)=f1l(ixc^s,iw)
691  f2l(ixc^s,iw)=f1l(ixc^s,iw)
692  f2r(ixc^s,iw)=f1l(ixc^s,iw)
693  else
694  ! construct hlld flux
695  f1l(ixc^s,iw)=flc(ixc^s,iw)+sl(ixc^s,ii)*(w1l(ixc^s,iw)-wlc(ixc^s,iw))
696  f1r(ixc^s,iw)=frc(ixc^s,iw)+sr(ixc^s,ii)*(w1r(ixc^s,iw)-wrc(ixc^s,iw))
697  f2l(ixc^s,iw)=f1l(ixc^s,iw)+s1l(ixc^s)*(w2l(ixc^s,iw)-w1l(ixc^s,iw))
698  f2r(ixc^s,iw)=f1r(ixc^s,iw)+s1r(ixc^s)*(w2r(ixc^s,iw)-w1r(ixc^s,iw))
699  end if
700  end do
701 
702  ! Miyoshi equation (66) and Guo equation (46)
703  {do ix^db=ixcmin^db,ixcmax^db\}
704  if(sl(ix^d,ii)>0.d0) then
705  fc(ix^d,iws:iwe,ip1)=flc(ix^d,iws:iwe)
706  else if(s1l(ix^d)>=0.d0) then
707  fc(ix^d,iws:iwe,ip1)=f1l(ix^d,iws:iwe)
708  else if(sm(ix^d)>=0.d0) then
709  fc(ix^d,iws:iwe,ip1)=f2l(ix^d,iws:iwe)
710  else if(s1r(ix^d)>=0.d0) then
711  fc(ix^d,iws:iwe,ip1)=f2r(ix^d,iws:iwe)
712  else if(sr(ix^d,ii)>=0.d0) then
713  fc(ix^d,iws:iwe,ip1)=f1r(ix^d,iws:iwe)
714  else if(sr(ix^d,ii)<0.d0) then
715  fc(ix^d,iws:iwe,ip1)=frc(ix^d,iws:iwe)
716  end if
717  {end do\}
718 
719  end associate
720  end subroutine get_riemann_flux_hlld
721 
722  !> HLLD Riemann flux from Miyoshi 2005 JCP, 208, 315 and Guo 2016 JCP, 327, 543
723  !> https://arxiv.org/pdf/2108.04991.pdf
724  subroutine get_riemann_flux_hlld_mag2()
725  !use mod_mhd_phys
726  use mod_variables
727  use mod_physics
728  implicit none
729  double precision, dimension(ixI^S,1:nwflux) :: w1R,w1L,f1R,f1L,f2R,f2L
730  double precision, dimension(ixI^S,1:nwflux) :: w2R,w2L
731  double precision, dimension(ixI^S) :: sm,s1R,s1L,suR,suL,Bx
732  double precision, dimension(ixI^S) :: pts,ptR,ptL,signBx,r1L,r1R,tmp
733  ! velocity from the right and the left reconstruction
734  double precision, dimension(ixI^S,ndir) :: vRC, vLC
735  ! magnetic field from the right and the left reconstruction
736  double precision, dimension(ixI^S,ndir) :: BR, BL
737  integer :: ip1,ip2,ip3,idir,ix^D
738  double precision :: phiPres, thetaSM, du, dv, dw
739  integer :: ixV^L, ixVb^L, ixVc^L, ixVd^L, ixVe^L, ixVf^L
740  integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
741  double precision, parameter :: aParam = 4d0
742 
743  rho_ = iw_rho
744  mom(:) = iw_mom(:)
745  mag(:) = iw_mag(:)
746  p_ = iw_e
747  e_ = iw_e
748 
749  associate(sr=>cmaxc,sl=>cminc)
750 
751  f1r=0.d0
752  f1l=0.d0
753  ip1=idims
754  ip3=3
755 
756  vrc(ixc^s,:)=wrp(ixc^s,mom(:))
757  vlc(ixc^s,:)=wlp(ixc^s,mom(:))
758 
759  ! reuse s1L s1R
760  call get_hlld2_modif_c(wlp,x,ixi^l,ixo^l,s1l)
761  call get_hlld2_modif_c(wrp,x,ixi^l,ixo^l,s1r)
762  !phiPres = min(1, maxval(max(s1L(ixO^S),s1R(ixO^S))/cmaxC(ixO^S,1)))
763  phipres = min(1d0, maxval(max(s1l(ixo^s),s1r(ixo^s)))/maxval(cmaxc(ixo^s,1)))
764  phipres = phipres*(2d0 - phipres)
765 
766  !we use here not reconstructed velocity: wprim?
767  ixv^l=ixo^l;
768  !first dim
769  ixvmin1=ixomin1+1
770  ixvmax1=ixomax1+1
771  du = minval(wprim(ixv^s,mom(1))-wprim(ixo^s,mom(1)))
772  if(du>0d0) du=0d0
773  dv = 0d0
774  dw = 0d0
775 
776  {^nooned
777  !second dim
778  !i,j-1,k
779  ixv^l=ixo^l;
780  ixvmin2=ixomin2-1
781  ixvmax2=ixomax2-1
782 
783  !i,j+1,k
784  ixvb^l=ixo^l;
785  ixvbmin2=ixomin2+1
786  ixvbmax2=ixomax2+1
787 
788  !i+1,j,k
789  ixvc^l=ixo^l;
790  ixvcmin1=ixomin1+1
791  ixvcmax1=ixomax1+1
792 
793  !i+1,j-1,k
794  ixvd^l=ixo^l;
795  ixvdmin1=ixomin1+1
796  ixvdmax1=ixomax1+1
797  ixvdmin2=ixomin2-1
798  ixvdmax2=ixomax2-1
799 
800  !i+1,j+1,k
801  ixve^l=ixo^l;
802  ixvemin1=ixomin1+1
803  ixvemax1=ixomax1+1
804  ixvemin2=ixomin2+1
805  ixvemax2=ixomax2+1
806 
807  dv = minval(min(wprim(ixo^s,mom(2))-wprim(ixv^s,mom(2)),&
808  wprim(ixvb^s,mom(2))-wprim(ixo^s,mom(2)),&
809  wprim(ixvc^s,mom(2))-wprim(ixvd^s,mom(2)),&
810  wprim(ixve^s,mom(2))-wprim(ixvc^s,mom(2))&
811  ))
812  if(dv>0d0) dv=0d0}
813 
814  {^ifthreed
815  !third dim
816  !i,j,k-1
817  ixv^l=ixo^l;
818  ixvmin3=ixomin3-1
819  ixvmax3=ixomax3-1
820 
821  !i,j,k+1
822  ixvb^l=ixo^l;
823  ixvbmin3=ixomin3+1
824  ixvbmax3=ixomax3+1
825 
826  !i+1,j,k
827  ixvc^l=ixo^l;
828  ixvcmin1=ixomin1+1
829  ixvcmax1=ixomax1+1
830 
831  !i+1,j,k-1
832  ixvd^l=ixo^l;
833  ixvdmin1=ixomin1+1
834  ixvdmax1=ixomax1+1
835  ixvdmin3=ixomin3-1
836  ixvdmax3=ixomax3-1
837 
838  !i+1,j,k+1
839  ixve^l=ixo^l;
840  ixvemin1=ixomin1+1
841  ixvemax1=ixomax1+1
842  ixvemin3=ixomin3+1
843  ixvemax3=ixomax3+1
844  dw = minval(min(wprim(ixo^s,mom(3))-wprim(ixv^s,mom(3)),&
845  wprim(ixvb^s,mom(3))-wprim(ixo^s,mom(3)),&
846  wprim(ixvc^s,mom(3))-wprim(ixvd^s,mom(3)),&
847  wprim(ixve^s,mom(3))-wprim(ixvc^s,mom(3))&
848  ))
849  if(dw>0d0) dw=0d0}
850  thetasm = maxval(cmaxc(ixo^s,1))
851 
852  thetasm = (min(1d0, (thetasm-du)/(thetasm-min(dv,dw))))**aparam
853  !print*, "HLLD2 ", du,dv,dw, thetaSM, phiPres
854 
855  if(b0field) then
856  br(ixc^s,:)=wrc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
857  bl(ixc^s,:)=wlc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
858  else
859  br(ixc^s,:)=wrc(ixc^s,mag(:))
860  bl(ixc^s,:)=wlc(ixc^s,mag(:))
861  end if
862  ! HLL estimation of normal magnetic field at cell interfaces
863  bx(ixc^s)=(sr(ixc^s,index_v_mag)*br(ixc^s,ip1)-sl(ixc^s,index_v_mag)*bl(ixc^s,ip1)-&
864  flc(ixc^s,mag(ip1))-frc(ixc^s,mag(ip1)))/(sr(ixc^s,index_v_mag)-sl(ixc^s,index_v_mag))
865  ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(br(ixc^s,:)**2,dim=ndim+1)
866  ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(bl(ixc^s,:)**2,dim=ndim+1)
867  sur(ixc^s)=(sr(ixc^s,index_v_mag)-vrc(ixc^s,ip1))*wrc(ixc^s,rho_)
868  sul(ixc^s)=(sl(ixc^s,index_v_mag)-vlc(ixc^s,ip1))*wlc(ixc^s,rho_)
869  ! Miyoshi equation (38) and Guo euqation (20)
870  sm(ixc^s)=(sur(ixc^s)*vrc(ixc^s,ip1)-sul(ixc^s)*vlc(ixc^s,ip1)-&
871  thetasm*(ptr(ixc^s)-ptl(ixc^s)) )/(sur(ixc^s)-sul(ixc^s))
872  ! Miyoshi equation (39) and Guo euqation (28)
873  w1r(ixc^s,mom(ip1))=sm(ixc^s)
874  w1l(ixc^s,mom(ip1))=sm(ixc^s)
875  w2r(ixc^s,mom(ip1))=sm(ixc^s)
876  w2l(ixc^s,mom(ip1))=sm(ixc^s)
877  ! Guo equation (22)
878  w1r(ixc^s,mag(ip1))=bx(ixc^s)
879  w1l(ixc^s,mag(ip1))=bx(ixc^s)
880  if(b0field) then
881  ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(wrc(ixc^s,mag(:))**2,dim=ndim+1)
882  ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(wlc(ixc^s,mag(:))**2,dim=ndim+1)
883  end if
884 
885  ! Miyoshi equation (43) and Guo equation (27)
886  w1r(ixc^s,rho_)=sur(ixc^s)/(sr(ixc^s,index_v_mag)-sm(ixc^s))
887  w1l(ixc^s,rho_)=sul(ixc^s)/(sl(ixc^s,index_v_mag)-sm(ixc^s))
888 
889  ip2=mod(ip1+1,ndir)
890  if(ip2==0) ip2=ndir
891  r1r(ixc^s)=sur(ixc^s)*(sr(ixc^s,index_v_mag)-sm(ixc^s))-bx(ixc^s)**2
892  where(r1r(ixc^s)/=0.d0)
893  r1r(ixc^s)=1.d0/r1r(ixc^s)
894  endwhere
895  r1l(ixc^s)=sul(ixc^s)*(sl(ixc^s,index_v_mag)-sm(ixc^s))-bx(ixc^s)**2
896  where(r1l(ixc^s)/=0.d0)
897  r1l(ixc^s)=1.d0/r1l(ixc^s)
898  endwhere
899  ! Miyoshi equation (44)
900  w1r(ixc^s,mom(ip2))=vrc(ixc^s,ip2)-bx(ixc^s)*br(ixc^s,ip2)*&
901  (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
902  w1l(ixc^s,mom(ip2))=vlc(ixc^s,ip2)-bx(ixc^s)*bl(ixc^s,ip2)*&
903  (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
904  ! partial solution for later usage
905  w1r(ixc^s,mag(ip2))=(sur(ixc^s)*(sr(ixc^s,index_v_mag)-vrc(ixc^s,ip1))-bx(ixc^s)**2)*r1r(ixc^s)
906  w1l(ixc^s,mag(ip2))=(sul(ixc^s)*(sl(ixc^s,index_v_mag)-vlc(ixc^s,ip1))-bx(ixc^s)**2)*r1l(ixc^s)
907  if(ndir==3) then
908  ip3=mod(ip1+2,ndir)
909  if(ip3==0) ip3=ndir
910  ! Miyoshi equation (46)
911  w1r(ixc^s,mom(ip3))=vrc(ixc^s,ip3)-bx(ixc^s)*br(ixc^s,ip3)*&
912  (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
913  w1l(ixc^s,mom(ip3))=vlc(ixc^s,ip3)-bx(ixc^s)*bl(ixc^s,ip3)*&
914  (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
915  ! Miyoshi equation (47)
916  w1r(ixc^s,mag(ip3))=br(ixc^s,ip3)*w1r(ixc^s,mag(ip2))
917  w1l(ixc^s,mag(ip3))=bl(ixc^s,ip3)*w1l(ixc^s,mag(ip2))
918  end if
919  ! Miyoshi equation (45)
920  w1r(ixc^s,mag(ip2))=br(ixc^s,ip2)*w1r(ixc^s,mag(ip2))
921  w1l(ixc^s,mag(ip2))=bl(ixc^s,ip2)*w1l(ixc^s,mag(ip2))
922  if(b0field) then
923  ! Guo equation (26)
924  w1r(ixc^s,mag(:))=w1r(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
925  w1l(ixc^s,mag(:))=w1l(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
926  end if
927  ! equation (48)
928  if(phys_energy) then
929  ! Guo equation (25) equivalent to Miyoshi equation (41)
930  w1r(ixc^s,p_)=(sur(ixc^s)*ptl(ixc^s) - sul(ixc^s)*ptr(ixc^s) +&
931  phipres * sur(ixc^s)*sul(ixc^s)*(vrc(ixc^s,ip1)-vlc(ixc^s,ip1)))/&
932  (sur(ixc^s)-sul(ixc^s))
933  w1l(ixc^s,p_)=w1r(ixc^s,p_)
934  if(b0field) then
935  ! Guo equation (32)
936  w1r(ixc^s,p_)=w1r(ixc^s,p_)+sum(block%B0(ixc^s,:,ip1)*(wrc(ixc^s,mag(:))-w1r(ixc^s,mag(:))),dim=ndim+1)
937  w1l(ixc^s,p_)=w1l(ixc^s,p_)+sum(block%B0(ixc^s,:,ip1)*(wlc(ixc^s,mag(:))-w1l(ixc^s,mag(:))),dim=ndim+1)
938  end if
939  ! Miyoshi equation (48) and main part of Guo euqation (31)
940  w1r(ixc^s,e_)=((sr(ixc^s,index_v_mag)-vrc(ixc^s,ip1))*wrc(ixc^s,e_)-ptr(ixc^s)*vrc(ixc^s,ip1)+&
941  w1r(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vrc(ixc^s,:)*wrc(ixc^s,mag(:)),dim=ndim+1)-&
942  sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)))/(sr(ixc^s,index_v_mag)-sm(ixc^s))
943  w1l(ixc^s,e_)=((sl(ixc^s,index_v_mag)-vlc(ixc^s,ip1))*wlc(ixc^s,e_)-ptl(ixc^s)*vlc(ixc^s,ip1)+&
944  w1l(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vlc(ixc^s,:)*wlc(ixc^s,mag(:)),dim=ndim+1)-&
945  sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)))/(sl(ixc^s,index_v_mag)-sm(ixc^s))
946  if(b0field) then
947  ! Guo equation (31)
948  w1r(ixc^s,e_)=w1r(ixc^s,e_)+(sum(w1r(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
949  sum(wrc(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*vrc(ixc^s,ip1))/(sr(ixc^s,index_v_mag)-sm(ixc^s))
950  w1l(ixc^s,e_)=w1l(ixc^s,e_)+(sum(w1l(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
951  sum(wlc(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*vlc(ixc^s,ip1))/(sl(ixc^s,index_v_mag)-sm(ixc^s))
952  end if
953  end if
954 
955  ! Miyoshi equation (49) and Guo equation (35)
956  w2r(ixc^s,rho_)=w1r(ixc^s,rho_)
957  w2l(ixc^s,rho_)=w1l(ixc^s,rho_)
958  w2r(ixc^s,mag(ip1))=w1r(ixc^s,mag(ip1))
959  w2l(ixc^s,mag(ip1))=w1l(ixc^s,mag(ip1))
960 
961  r1r(ixc^s)=sqrt(w1r(ixc^s,rho_))
962  r1l(ixc^s)=sqrt(w1l(ixc^s,rho_))
963  tmp(ixc^s)=1.d0/(r1r(ixc^s)+r1l(ixc^s))
964  signbx(ixc^s)=sign(1.d0,bx(ixc^s))
965  ! Miyoshi equation (51) and Guo equation (33)
966  s1r(ixc^s)=sm(ixc^s)+abs(bx(ixc^s))/r1r(ixc^s)
967  s1l(ixc^s)=sm(ixc^s)-abs(bx(ixc^s))/r1l(ixc^s)
968  ! Miyoshi equation (59) and Guo equation (41)
969  w2r(ixc^s,mom(ip2))=(r1l(ixc^s)*w1l(ixc^s,mom(ip2))+r1r(ixc^s)*w1r(ixc^s,mom(ip2))+&
970  (w1r(ixc^s,mag(ip2))-w1l(ixc^s,mag(ip2)))*signbx(ixc^s))*tmp(ixc^s)
971  w2l(ixc^s,mom(ip2))=w2r(ixc^s,mom(ip2))
972  ! Miyoshi equation (61) and Guo equation (43)
973  w2r(ixc^s,mag(ip2))=(r1l(ixc^s)*w1r(ixc^s,mag(ip2))+r1r(ixc^s)*w1l(ixc^s,mag(ip2))+&
974  r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip2))-w1l(ixc^s,mom(ip2)))*signbx(ixc^s))*tmp(ixc^s)
975  w2l(ixc^s,mag(ip2))=w2r(ixc^s,mag(ip2))
976  if(ndir==3) then
977  ! Miyoshi equation (60) and Guo equation (42)
978  w2r(ixc^s,mom(ip3))=(r1l(ixc^s)*w1l(ixc^s,mom(ip3))+r1r(ixc^s)*w1r(ixc^s,mom(ip3))+&
979  (w1r(ixc^s,mag(ip3))-w1l(ixc^s,mag(ip3)))*signbx(ixc^s))*tmp(ixc^s)
980  w2l(ixc^s,mom(ip3))=w2r(ixc^s,mom(ip3))
981  ! Miyoshi equation (62) and Guo equation (44)
982  w2r(ixc^s,mag(ip3))=(r1l(ixc^s)*w1r(ixc^s,mag(ip3))+r1r(ixc^s)*w1l(ixc^s,mag(ip3))+&
983  r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip3))-w1l(ixc^s,mom(ip3)))*signbx(ixc^s))*tmp(ixc^s)
984  w2l(ixc^s,mag(ip3))=w2r(ixc^s,mag(ip3))
985  end if
986  ! Miyoshi equation (63) and Guo equation (45)
987  if(phys_energy) then
988  w2r(ixc^s,e_)=w1r(ixc^s,e_)+r1r(ixc^s)*(sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)-&
989  sum(w2r(ixc^s,mom(:))*w2r(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
990  w2l(ixc^s,e_)=w1l(ixc^s,e_)-r1l(ixc^s)*(sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)-&
991  sum(w2l(ixc^s,mom(:))*w2l(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
992  end if
993 
994  ! convert velocity to momentum
995  do idir=1,ndir
996  w1r(ixc^s,mom(idir))=w1r(ixc^s,mom(idir))*w1r(ixc^s,rho_)
997  w1l(ixc^s,mom(idir))=w1l(ixc^s,mom(idir))*w1l(ixc^s,rho_)
998  w2r(ixc^s,mom(idir))=w2r(ixc^s,mom(idir))*w2r(ixc^s,rho_)
999  w2l(ixc^s,mom(idir))=w2l(ixc^s,mom(idir))*w2l(ixc^s,rho_)
1000  end do
1001 
1002  ! get fluxes of intermedate states
1003  do iw=1,nwflux
1004  ! CT MHD does not need normal B flux
1005  if(stagger_grid .and. flux_type(idims, iw) == flux_tvdlf) cycle
1006  if(flux_type(idims, iw) == flux_special) then
1007  ! known flux (fLC=fRC) for normal B and psi_ in GLM method
1008  f1l(ixc^s,iw)=flc(ixc^s,iw)
1009  f1r(ixc^s,iw)=f1l(ixc^s,iw)
1010  f2l(ixc^s,iw)=f1l(ixc^s,iw)
1011  f2r(ixc^s,iw)=f1l(ixc^s,iw)
1012  else if(flux_type(idims, iw) == flux_hll) then
1013  ! using hll flux for tracers
1014  f1l(ixc^s,iw)=(sr(ixc^s,index_v_mag)*flc(ixc^s, iw)-sl(ixc^s,index_v_mag)*frc(ixc^s, iw) &
1015  +sr(ixc^s,index_v_mag)*sl(ixc^s,index_v_mag)*(wrc(ixc^s,iw)-wlc(ixc^s,iw)))/(sr(ixc^s,index_v_mag)-sl(ixc^s,index_v_mag))
1016  f1r(ixc^s,iw)=f1l(ixc^s,iw)
1017  f2l(ixc^s,iw)=f1l(ixc^s,iw)
1018  f2r(ixc^s,iw)=f1l(ixc^s,iw)
1019  else
1020  f1l(ixc^s,iw)=flc(ixc^s,iw)+sl(ixc^s,index_v_mag)*(w1l(ixc^s,iw)-wlc(ixc^s,iw))
1021  f1r(ixc^s,iw)=frc(ixc^s,iw)+sr(ixc^s,index_v_mag)*(w1r(ixc^s,iw)-wrc(ixc^s,iw))
1022  f2l(ixc^s,iw)=f1l(ixc^s,iw)+s1l(ixc^s)*(w2l(ixc^s,iw)-w1l(ixc^s,iw))
1023  f2r(ixc^s,iw)=f1r(ixc^s,iw)+s1r(ixc^s)*(w2r(ixc^s,iw)-w1r(ixc^s,iw))
1024  end if
1025  end do
1026 
1027  ! Miyoshi equation (66) and Guo equation (46)
1028  {do ix^db=ixcmin^db,ixcmax^db\}
1029  if(sl(ix^d,index_v_mag)>0.d0) then
1030  fc(ix^d,1:nwflux,ip1)=flc(ix^d,1:nwflux)
1031  else if(s1l(ix^d)>=0.d0) then
1032  fc(ix^d,1:nwflux,ip1)=f1l(ix^d,1:nwflux)
1033  else if(sm(ix^d)>=0.d0) then
1034  fc(ix^d,1:nwflux,ip1)=f2l(ix^d,1:nwflux)
1035  else if(s1r(ix^d)>=0.d0) then
1036  fc(ix^d,1:nwflux,ip1)=f2r(ix^d,1:nwflux)
1037  else if(sr(ix^d,index_v_mag)>=0.d0) then
1038  fc(ix^d,1:nwflux,ip1)=f1r(ix^d,1:nwflux)
1039  else if(sr(ix^d,index_v_mag)<0.d0) then
1040  fc(ix^d,1:nwflux,ip1)=frc(ix^d,1:nwflux)
1041  end if
1042  {end do\}
1043 
1044  end associate
1045  end subroutine get_riemann_flux_hlld_mag2
1046 
1047  !> Calculate fast magnetosonic wave speed
1048  subroutine get_hlld2_modif_c(w,x,ixI^L,ixO^L,csound)
1050 
1051  integer, intent(in) :: ixI^L, ixO^L
1052  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1053  double precision, intent(out):: csound(ixI^S)
1054  double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
1055  double precision :: inv_rho(ixO^S), gamma_A2(ixO^S)
1056  integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
1057 
1058  rho_ = iw_rho
1059  mom(:) = iw_mom(:)
1060  mag(:) = iw_mag(:)
1061  p_ = iw_e
1062  e_ = iw_e
1063 
1064  inv_rho=1.d0/w(ixo^s,rho_)
1065 
1066  ! store |B|^2 in v
1067 
1068  if (b0field) then
1069  b2(ixo^s) = sum((w(ixo^s, mag(:))+block%B0(ixo^s,:,b0i))**2, dim=ndim+1)
1070  else
1071  b2(ixo^s) = sum(w(ixo^s, mag(:))**2, dim=ndim+1)
1072  end if
1073 
1074 
1075  if (b0field) then
1076  avmincs2= w(ixo^s, mag(idims))+block%B0(ixo^s,idims,b0i)
1077  else
1078  avmincs2= w(ixo^s, mag(idims))
1079  end if
1080 
1081 
1082  csound(ixo^s) = sum(w(ixo^s, mom(:))**2, dim=ndim+1)
1083 
1084  cfast2(ixo^s) = b2(ixo^s) * inv_rho+csound(ixo^s)
1085  avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
1086  * avmincs2(ixo^s)**2 &
1087  * inv_rho
1088 
1089  where(avmincs2(ixo^s)<zero)
1090  avmincs2(ixo^s)=zero
1091  end where
1092 
1093  avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
1094 
1095  csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
1096 
1097  end subroutine get_hlld2_modif_c
1098 
1099  end subroutine finite_volume
1100 
1101  !> Determine the upwinded wLC(ixL) and wRC(ixR) from w.
1102  !> the wCT is only used when PPM is exploited.
1103  subroutine reconstruct_lr(ixI^L,ixL^L,ixR^L,idims,w,wLC,wRC,wLp,wRp,x,dxdim)
1104  use mod_physics
1106  use mod_limiter
1107  use mod_comm_lib, only: mpistop
1108 
1109  integer, intent(in) :: ixi^l, ixl^l, ixr^l, idims
1110  double precision, intent(in) :: dxdim
1111  ! cell center w in primitive form
1112  double precision, dimension(ixI^S,1:nw) :: w
1113  ! left and right constructed status in conservative form
1114  double precision, dimension(ixI^S,1:nw) :: wlc, wrc
1115  ! left and right constructed status in primitive form
1116  double precision, dimension(ixI^S,1:nw) :: wlp, wrp
1117  double precision, dimension(ixI^S,1:ndim) :: x
1118 
1119  integer :: jxr^l, ixc^l, jxc^l, iw
1120  double precision :: ldw(ixi^s), rdw(ixi^s), dwc(ixi^s)
1121  double precision :: a2max
1122 
1123  select case (type_limiter(block%level))
1124  case (limiter_mp5)
1125  call mp5limiter(ixi^l,ixl^l,idims,w,wlp,wrp)
1126  case (limiter_weno3)
1127  call weno3limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1128  case (limiter_wenoyc3)
1129  call weno3limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1130  case (limiter_weno5)
1131  call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1132  case (limiter_weno5nm)
1133  call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1134  case (limiter_wenoz5)
1135  call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1136  case (limiter_wenoz5nm)
1137  call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1138  case (limiter_wenozp5)
1139  call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,3)
1140  case (limiter_wenozp5nm)
1141  call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,3)
1142  case (limiter_weno5cu6)
1143  call weno5cu6limiter(ixi^l,ixl^l,idims,w,wlp,wrp)
1144  case (limiter_teno5ad)
1145  call teno5adlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp)
1146  case (limiter_weno7)
1147  call weno7limiter(ixi^l,ixl^l,idims,w,wlp,wrp,1)
1148  case (limiter_mpweno7)
1149  call weno7limiter(ixi^l,ixl^l,idims,w,wlp,wrp,2)
1150  case (limiter_venk)
1151  call venklimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp)
1152  if(fix_small_values) then
1153  call phys_handle_small_values(.true.,wlp,x,ixi^l,ixl^l,'reconstruct left')
1154  call phys_handle_small_values(.true.,wrp,x,ixi^l,ixr^l,'reconstruct right')
1155  end if
1156  case (limiter_ppm)
1157  call ppmlimiter(ixi^l,ixm^ll,idims,w,w,wlp,wrp)
1158  if(fix_small_values) then
1159  call phys_handle_small_values(.true.,wlp,x,ixi^l,ixl^l,'reconstruct left')
1160  call phys_handle_small_values(.true.,wrp,x,ixi^l,ixr^l,'reconstruct right')
1161  end if
1162  case default
1163  jxr^l=ixr^l+kr(idims,^d);
1164  ixcmax^d=jxrmax^d; ixcmin^d=ixlmin^d-kr(idims,^d);
1165  jxc^l=ixc^l+kr(idims,^d);
1166  do iw=1,nwflux
1167  if (loglimit(iw)) then
1168  w(ixcmin^d:jxcmax^d,iw)=dlog10(w(ixcmin^d:jxcmax^d,iw))
1169  wlp(ixl^s,iw)=dlog10(wlp(ixl^s,iw))
1170  wrp(ixr^s,iw)=dlog10(wrp(ixr^s,iw))
1171  end if
1172 
1173  dwc(ixc^s)=w(jxc^s,iw)-w(ixc^s,iw)
1174  if(need_global_a2max) then
1175  a2max=a2max_global(idims)
1176  else
1177  select case(idims)
1178  case(1)
1179  a2max=schmid_rad1
1180  {^iftwod
1181  case(2)
1182  a2max=schmid_rad2}
1183  {^ifthreed
1184  case(2)
1185  a2max=schmid_rad2
1186  case(3)
1187  a2max=schmid_rad3}
1188  case default
1189  call mpistop("idims is wrong in mod_limiter")
1190  end select
1191  end if
1192 
1193  ! limit flux from left and/or right
1194  call dwlimiter2(dwc,ixi^l,ixc^l,idims,type_limiter(block%level),ldw,rdw,a2max=a2max)
1195  wlp(ixl^s,iw)=wlp(ixl^s,iw)+half*ldw(ixl^s)
1196  wrp(ixr^s,iw)=wrp(ixr^s,iw)-half*rdw(jxr^s)
1197 
1198  if (loglimit(iw)) then
1199  w(ixcmin^d:jxcmax^d,iw)=10.0d0**w(ixcmin^d:jxcmax^d,iw)
1200  wlp(ixl^s,iw)=10.0d0**wlp(ixl^s,iw)
1201  wrp(ixr^s,iw)=10.0d0**wrp(ixr^s,iw)
1202  end if
1203  end do
1204  if(fix_small_values) then
1205  call phys_handle_small_values(.true.,wlp,x,ixi^l,ixl^l,'reconstruct left')
1206  call phys_handle_small_values(.true.,wrp,x,ixi^l,ixr^l,'reconstruct right')
1207  end if
1208  end select
1209 
1210  wlc(ixl^s,1:nwflux) = wlp(ixl^s,1:nwflux)
1211  wrc(ixr^s,1:nwflux) = wrp(ixr^s,1:nwflux)
1212  call phys_to_conserved(ixi^l,ixl^l,wlc,x)
1213  call phys_to_conserved(ixi^l,ixr^l,wrc,x)
1214  if(nwaux>0)then
1215  wlp(ixl^s,nwflux+1:nwflux+nwaux) = wlc(ixl^s,nwflux+1:nwflux+nwaux)
1216  wrp(ixr^s,nwflux+1:nwflux+nwaux) = wrc(ixr^s,nwflux+1:nwflux+nwaux)
1217  endif
1218 
1219  end subroutine reconstruct_lr
1220 
1221 end module mod_finite_volume
subroutine get_hlld2_modif_c(w, x, ixIL, ixOL, csound)
Calculate fast magnetosonic wave speed.
subroutine get_riemann_flux_tvdmu()
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: mod_comm_lib.t:208
Module with finite volume methods for fluxes.
subroutine, public finite_volume(method, qdt, dtfactor, ixIL, ixOL, idimsLIM, qtC, sCT, qt, snew, fC, fE, dxs, x)
finite volume method
subroutine, public reconstruct_lr(ixIL, ixLL, ixRL, idims, w, wLC, wRC, wLp, wRp, x, dxdim)
Determine the upwinded wLC(ixL) and wRC(ixR) from w. the wCT is only used when PPM is exploited.
subroutine, public hancock(qdt, dtfactor, ixIL, ixOL, idimsLIM, qtC, sCT, qt, snew, dxs, x)
The non-conservative Hancock predictor for TVDLF.
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
logical h_correction
If true, do H-correction to fix the carbuncle problem at grid-aligned shocks.
integer, parameter fs_tvdlf
integer ixghi
Upper index of grid block arrays.
integer, parameter fs_hlld
integer, dimension(3, 3) kr
Kronecker delta tensor.
logical, dimension(:), allocatable loglimit
integer, parameter fs_hllcd
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical stagger_grid
True for using stagger grid.
integer, parameter fs_tvdmu
integer b0i
background magnetic field location indicator
integer, dimension(:), allocatable, parameter d
logical local_timestep
each cell has its own timestep or not
logical need_global_a2max
global value for schmid scheme
integer ixm
the mesh range of a physical block without ghost cells
logical slab
Cartesian geometry or not.
integer, parameter fs_hll
flux schemes
logical b0field
split magnetic field as background B0 field
integer, dimension(:), allocatable type_limiter
Type of slope limiter used for reconstructing variables on cell edges.
integer nghostcells
Number of ghost cells surrounding a grid.
logical crash
Save a snapshot before crash a run met unphysical values.
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer, parameter fs_hllc
double precision, dimension(ndim) a2max_global
global largest a2 for schmid scheme
integer, parameter ixglo
Lower index of grid block arrays (always 1)
Module with slope/flux limiters.
Definition: mod_limiter.t:2
integer, parameter limiter_weno5cu6
Definition: mod_limiter.t:37
integer, parameter limiter_mpweno7
Definition: mod_limiter.t:40
integer, parameter limiter_teno5ad
Definition: mod_limiter.t:38
integer, parameter limiter_weno3
Definition: mod_limiter.t:29
integer, parameter limiter_ppm
Definition: mod_limiter.t:27
subroutine dwlimiter2(dwC, ixIL, ixCL, idims, typelim, ldw, rdw, a2max)
Limit the centered dwC differences within ixC for iw in direction idim. The limiter is chosen accordi...
Definition: mod_limiter.t:129
double precision d
Definition: mod_limiter.t:14
integer, parameter limiter_wenozp5
Definition: mod_limiter.t:35
integer, parameter limiter_weno5
Definition: mod_limiter.t:31
integer, parameter limiter_wenoz5
Definition: mod_limiter.t:33
integer, parameter limiter_wenoz5nm
Definition: mod_limiter.t:34
integer, parameter limiter_weno7
Definition: mod_limiter.t:39
integer, parameter limiter_wenozp5nm
Definition: mod_limiter.t:36
integer, parameter limiter_mp5
Definition: mod_limiter.t:28
integer, parameter limiter_venk
Definition: mod_limiter.t:25
integer, parameter limiter_weno5nm
Definition: mod_limiter.t:32
integer, parameter limiter_wenoyc3
Definition: mod_limiter.t:30
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
procedure(sub_get_ct_velocity), pointer phys_get_ct_velocity
Definition: mod_physics.t:83
procedure(sub_convert), pointer phys_to_primitive
Definition: mod_physics.t:59
integer, parameter flux_tvdlf
Indicates the flux should be treated with tvdlf.
Definition: mod_physics.t:48
procedure(sub_small_values), pointer phys_handle_small_values
Definition: mod_physics.t:82
procedure(sub_get_flux), pointer phys_get_flux
Definition: mod_physics.t:68
procedure(sub_get_cbounds), pointer phys_get_cbounds
Definition: mod_physics.t:67
integer, parameter flux_hll
Indicates the flux should be treated with hll.
Definition: mod_physics.t:54
procedure(sub_add_source_geom), pointer phys_add_source_geom
Definition: mod_physics.t:72
integer, parameter flux_special
Indicates the flux should be specially treated.
Definition: mod_physics.t:52
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
integer phys_wider_stencil
To use wider stencils in flux calculations. A value of 1 will extend it by one cell in both direction...
Definition: mod_physics.t:20
procedure(sub_update_faces), pointer phys_update_faces
Definition: mod_physics.t:84
procedure(sub_convert), pointer phys_to_conserved
Definition: mod_physics.t:58
procedure(sub_face_to_center), pointer phys_face_to_center
Definition: mod_physics.t:85
procedure(sub_modify_wlr), pointer phys_modify_wlr
Definition: mod_physics.t:60
procedure(sub_get_h_speed), pointer phys_get_h_speed
Definition: mod_physics.t:66
logical phys_energy
Solve energy equation or not.
Definition: mod_physics.t:27
Module for handling split source terms (split from the fluxes)
Definition: mod_source.t:2
subroutine, public addsource2(qdt, dtfactor, ixIL, ixOL, iwLIM, qtC, wCT, wCTprim, qt, w, x, qsourcesplit, src_active)
Add source within ixO for iws: w=w+qdt*S[wCT].
Definition: mod_source.t:132
Subroutines for TVD-MUSCL schemes.
Definition: mod_tvd.t:2
subroutine, public tvdlimit2(method, qdt, ixIL, ixICL, ixOL, idims, wL, wR, wnew, x, fC, dxs)
Definition: mod_tvd.t:39
Module with all the methods that users can customize in AMRVAC.
integer nw
Total number of variables.
Definition: mod_variables.t:23
integer iwstart
Definition: mod_variables.t:38
integer number_species
number of species: each species has different characterictic speeds and should be used accordingly in...
Definition: mod_variables.t:75
integer, dimension(:), allocatable iw_mom
Indices of the momentum density.
Definition: mod_variables.t:55
integer, dimension(:), allocatable start_indices
the indices in 1:nwflux array are assumed consecutive for each species this array should be of size n...
Definition: mod_variables.t:84
integer, dimension(:), allocatable stop_indices
the indices in 1:nwflux array are assumed consecutive for each species this array should be of size n...
Definition: mod_variables.t:88
integer, dimension(:), allocatable, protected iw_mag
Indices of the magnetic field components.
Definition: mod_variables.t:67
integer iw_rho
Index of the (gas) density.
Definition: mod_variables.t:52
integer nwflux
Number of flux variables.
Definition: mod_variables.t:8
integer index_v_mag
index of the var whose velocity appears in the induction eq.
Definition: mod_variables.t:79
integer iw_e
Index of the energy density.
Definition: mod_variables.t:58