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