MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
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
11contains
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=.false.
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,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_limiter, only: limiter_cada3
123 use mod_source, only: addsource2
125 use mod_comm_lib, only: mpistop
126
127 integer, intent(in) :: method
128 double precision, intent(in) :: qdt, dtfactor, qtc, qt, dxs(ndim)
129 integer, intent(in) :: ixi^l, ixo^l, idims^lim
130 double precision, dimension(ixI^S,1:ndim), intent(in) :: x
131 double precision, dimension(ixI^S,1:nwflux,1:ndim) :: fc
132 double precision, dimension(ixI^S,sdim:3) :: fe
133 type(state) :: sct, snew
134
135 ! primitive w at cell center
136 double precision, dimension(ixI^S,1:nw) :: wprim
137 !> primitive w^n, used only for the slopes in the VAC-type MUSCL-Hancock corrector
138 double precision, dimension(ixI^S,1:nw) :: wprim_lim
139 logical :: lim_old
140 ! left and right constructed status in conservative form
141 double precision, dimension(ixI^S,1:nw) :: wlc, wrc
142 ! left and right constructed status in primitive form, needed for better performance
143 double precision, dimension(ixI^S,1:nw) :: wlp, wrp
144 double precision, dimension(ixI^S,1:nwflux) :: flc, frc
145 double precision, dimension(ixI^S,1:ndir,1:ndim) :: fc_mom
146 double precision, dimension(ixI^S,1:ndir) :: flc_mom, frc_mom
147 double precision, dimension(ixI^S,1:number_species) :: cmaxc
148 double precision, dimension(ixI^S,1:number_species) :: cminc
149 double precision, dimension(ixI^S) :: hspeed
150 double precision, dimension(ixO^S) :: inv_volume
151 double precision, dimension(1:ndim) :: dxinv
152 integer :: idims, iw, ix^d, hx^d, ix^l, hxo^l, ixc^l, ixcr^l, kxc^l, kxr^l, ii
153 integer :: jdims, jxc^l, hpc^l, hmc^l
154 !> undivided divergence of v at the interface, for the B19 diffusive flux
155 double precision, dimension(ixI^S) :: divvc
156 logical :: active=.false., need_hd_mom_flux=.false.
157 type(ct_velocity) :: vcts
158
159 associate(wct=>sct%w, wnew=>snew%w)
160
161 ! The flux calculation contracts by one in the idims direction it is applied.
162 ! The limiter contracts the same directions by one more, so expand ixO by 2.
163 ix^l=ixo^l;
164 do idims= idims^lim
165 ix^l=ix^l^ladd2*kr(idims,^d);
166 end do
167 if (ixi^l^ltix^l|.or.|.or.) &
168 call mpistop("Error in fv : Nonconforming input limits")
169
170 if(phys_hd_mom_conserve_fix) need_hd_mom_flux = levmax>levmin
171
172 wprim=wct
173 call phys_to_primitive(ixi^l,ixi^l,wprim,x)
174 ! typelimited='previous' (VAC): in the corrector of the Predictor_Corrector stepper with a
175 ! Hancock predictor, take cell centres from wCT = w^{n+1/2} but the limited slopes from
176 ! w^n, which snew%w still holds here. Only for the slope limiters (minmod ... cada3).
178 .and. istep==2 .and. typepred1(block%level)==fs_hancock &
179 .and. type_limiter(block%level)<=limiter_cada3 .and. .not.associated(phys_wb_transform)
180 if (lim_old) then
181 wprim_lim=wnew
182 call phys_to_primitive(ixi^l,ixi^l,wprim_lim,x)
183 end if
184 do idims= idims^lim
185 ! use interface value of w0 at idims
186 b0i=idims
187
188 kxcmin^d=iximin^d; kxcmax^d=iximax^d-kr(idims,^d);
189 kxr^l=kxc^l+kr(idims,^d);
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 do iw=1,nwflux
195 {do ix^db=iximin^db,iximax^db\}
196 ! fill all cells for averaging to fix small values
197 wrp(ix^d,iw)=wprim(ix^d,iw)
198 wlp(ix^d,iw)=wprim(ix^d,iw)
199 {end do\}
200 wrp(kxc^s,iw)=wprim(kxr^s,iw)
201 end do
202
203 hxo^l=ixo^l-kr(idims,^d);
204 if(stagger_grid) then
205 ! ct needs 1 or 2 (hll) ghost cells in the transverse dimensions
206 ixcmax^d=ixomax^d+transverse_ghost_cells-transverse_ghost_cells*kr(idims,^d);
207 ixcmin^d=hxomin^d-transverse_ghost_cells+transverse_ghost_cells*kr(idims,^d);
208 else
209 ! ixC is centered index in the idims direction from ixOmin-1/2 to ixOmax+1/2
210 ixcmax^d=ixomax^d; ixcmin^d=hxomin^d;
211 end if
212
213
214 ! Determine stencil size
215 {ixcrmin^d = max(ixcmin^d - phys_wider_stencil,ixglo^d)\}
216 {ixcrmax^d = min(ixcmax^d + phys_wider_stencil,ixghi^d)\}
217
218 ! apply limited reconstruction for left and right status at cell interfaces
219 if (lim_old) then
220 call reconstruct_lr(ixi^l,ixcr^l,ixcr^l,idims,wprim_lim,wlc,wrc,wlp,wrp,x,dxs(idims))
221 else
222 call reconstruct_lr(ixi^l,ixcr^l,ixcr^l,idims,wprim,wlc,wrc,wlp,wrp,x,dxs(idims))
223 end if
224
225 ! special modification of left and right status before flux evaluation
226 call phys_modify_wlr(ixi^l,ixcr^l,qt,wlc,wrc,wlp,wrp,sct,idims)
227
228 ! evaluate physical fluxes according to reconstructed status
229 call phys_get_flux(wlc,wlp,x,ixi^l,ixc^l,idims,flc)
230 call phys_get_flux(wrc,wrp,x,ixi^l,ixc^l,idims,frc)
231 if(need_hd_mom_flux) then
232 call phys_get_hd_mom_flux(wlc,wlp,x,ixi^l,ixc^l,idims,flc_mom)
233 call phys_get_hd_mom_flux(wrc,wrp,x,ixi^l,ixc^l,idims,frc_mom)
234 end if
235 if(h_correction) then
236 call phys_get_h_speed(wprim,x,ixi^l,ixo^l,idims,hspeed)
237 end if
238 ! estimating bounds for the minimum and maximum signal velocities
239 if(method==fs_tvdlf.or.method==fs_tvdmu) then
240 call phys_get_cbounds(wlc,wrc,wlp,wrp,x,ixi^l,ixc^l,idims,hspeed,cmaxc)
241 ! index of var velocity appears in the induction eq.
242 if(stagger_grid) call phys_get_ct_velocity(vcts,wlp,wrp,ixi^l,ixc^l,idims,cmaxc(ixi^s,index_v_mag))
243 else
244 call phys_get_cbounds(wlc,wrc,wlp,wrp,x,ixi^l,ixc^l,idims,hspeed,cmaxc,cminc)
245 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))
246 end if
247
248 ! use approximate Riemann solver to get flux at interfaces
249 select case(method)
250 case(fs_hll)
251 do ii=1,number_species
252 call get_riemann_flux_hll(start_indices(ii),stop_indices(ii),flc(ixi^s,start_indices(ii):stop_indices(ii)),frc(ixi^s,start_indices(ii):stop_indices(ii)),fc(ixi^s,start_indices(ii):stop_indices(ii),idims))
253 end do
254 if(need_hd_mom_flux) then
255 ii=1
256 call get_riemann_flux_hll(iw_mom(1),iw_mom(ndir),flc_mom,frc_mom,fc_mom(ixi^s,1:ndir,idims))
257 end if
258 case(fs_hllc,fs_hllcd)
259 do ii=1,number_species
260 call get_riemann_flux_hllc(start_indices(ii),stop_indices(ii))
261 end do
262 if(need_hd_mom_flux) then
263 ii=1
264 call get_riemann_flux_hll(iw_mom(1),iw_mom(ndir),flc_mom,frc_mom,fc_mom(ixi^s,1:ndir,idims))
265 end if
266 case(fs_hlld)
267 do ii=1,number_species
268 if(ii==index_v_mag) then
269 call get_riemann_flux_hlld(start_indices(ii),stop_indices(ii))
270 else
271 call get_riemann_flux_hll(start_indices(ii),stop_indices(ii),flc(ixi^s,start_indices(ii):stop_indices(ii)),frc(ixi^s,start_indices(ii):stop_indices(ii)),fc(ixi^s,start_indices(ii):stop_indices(ii),idims))
272 end if
273 end do
274 if(need_hd_mom_flux) then
275 ii=1
276 call get_riemann_flux_hll(iw_mom(1),iw_mom(ndir),flc_mom,frc_mom,fc_mom(ixi^s,1:ndir,idims))
277 end if
278 case(fs_tvdlf)
279 do ii=1,number_species
280 call get_riemann_flux_tvdlf(start_indices(ii),stop_indices(ii),flc(ixi^s,start_indices(ii):stop_indices(ii)),frc(ixi^s,start_indices(ii):stop_indices(ii)),fc(ixi^s,start_indices(ii):stop_indices(ii),idims))
281 end do
282 if(need_hd_mom_flux) then
283 ii=1
284 call get_riemann_flux_tvdlf(iw_mom(1),iw_mom(ndir),flc_mom,frc_mom,fc_mom(ixi^s,1:ndir,idims))
285 end if
286 case(fs_tvdmu)
288 case default
289 call mpistop('unkown Riemann flux in finite volume')
290 end select
291
292 ! Explicit diffusive flux, Mignone et al. 2005 eq. B19-B21 -- the half of PPM's
293 ! dissipation algorithm that this code has never had:
294 !
295 ! F_{i+1/2} -> F_{i+1/2} + k_nu (U_i - U_{i+1}) , k_nu = alpha*max(-D_{i+1/2},0)
296 !
297 ! Differencing that across a cell gives +k_nu*(U_{i+1}-2U_i+U_{i-1}), a genuine
298 ! diffusion. Two properties matter here. It uses the raw cell difference, not the
299 ! reconstructed face jump, so it is the only term in the scheme that can act on an
300 ! odd-even mode which a face-value reconstruction (ppm) annihilates. And it is gated
301 ! on convergence, so it vanishes identically for a state at rest and cannot perturb
302 ! a hydrostatic column.
303 !
304 ! D is B21's undivided multidimensional divergence of v. B21 assembles it from cell
305 ! corners; the equivalent used here is face-centred -- the normal difference across
306 ! the interface plus the mean of the transverse centred divergences of the two cells
307 ! straddling it. Identical in 1D, second-order equivalent in multi-D.
308 if (ppm_avisc > zero) then
309 jxc^l=ixc^l+kr(idims,^d);
310 divvc(ixc^s)=wprim(jxc^s,iw_mom(idims))-wprim(ixc^s,iw_mom(idims))
311 do jdims=1,ndim
312 if (jdims==idims) cycle
313 hpc^l=ixc^l+kr(jdims,^d); hmc^l=ixc^l-kr(jdims,^d);
314 divvc(ixc^s)=divvc(ixc^s) &
315 +0.25d0*(wprim(hpc^s,iw_mom(jdims))-wprim(hmc^s,iw_mom(jdims)))
316 hpc^l=hpc^l+kr(idims,^d); hmc^l=hmc^l+kr(idims,^d);
317 divvc(ixc^s)=divvc(ixc^s) &
318 +0.25d0*(wprim(hpc^s,iw_mom(jdims))-wprim(hmc^s,iw_mom(jdims)))
319 end do
320 divvc(ixc^s)=ppm_avisc*max(-divvc(ixc^s),zero)
321 do iw=iwstart,nwflux
322 fc(ixc^s,iw,idims)=fc(ixc^s,iw,idims) &
323 +divvc(ixc^s)*(wct(ixc^s,iw)-wct(jxc^s,iw))
324 end do
325 end if
326
327 end do ! Next idims
328 b0i=0
329 if(stagger_grid) call phys_update_faces(ixi^l,ixo^l,qt,qdt,wprim,fc,fe,sct,snew,vcts)
330 if(slab_uniform) then
331 if(local_timestep) then
332 dxinv(1:ndim)=-dtfactor/dxs(1:ndim)
333 do idims= idims^lim
334 hx^d=kr(idims,^d)\
335 hxomin^d=ixomin^d-hx^d\
336 do iw=iwstart,nwflux
337 {do ix^db=hxomin^db,ixomax^db\}
338 fc(ix^d,iw,idims)=block%dt(ix^d)*dxinv(idims)*fc(ix^d,iw,idims)
339 {end do\}
340 {do ix^db=ixomin^db,ixomax^db\}
341 wnew(ix^d,iw)=wnew(ix^d,iw)+fc(ix^d,iw,idims)-fc(ix^d-hx^d,iw,idims)
342 {end do\}
343 end do
344 ! For the MUSCL scheme apply the characteristic based limiter
345 if(method==fs_tvdmu) &
346 call tvdlimit2(method,qdt,ixi^l,ixc^l,ixo^l,idims,wlc,wrc,wnew,x,fc,dxs)
347 end do
348 else
349 dxinv(1:ndim)=-qdt/dxs(1:ndim)
350 do idims= idims^lim
351 hx^d=kr(idims,^d)\
352 hxomin^d=ixomin^d-hx^d\
353 do iw=iwstart,nwflux
354 {do ix^db=hxomin^db,ixomax^db\}
355 fc(ix^d,iw,idims)=dxinv(idims)*fc(ix^d,iw,idims)
356 {end do\}
357 {do ix^db=ixomin^db,ixomax^db\}
358 wnew(ix^d,iw)=wnew(ix^d,iw)+fc(ix^d,iw,idims)-fc(ix^d-hx^d,iw,idims)
359 {end do\}
360 end do
361 ! For the MUSCL scheme apply the characteristic based limiter
362 if(method==fs_tvdmu) &
363 call tvdlimit2(method,qdt,ixi^l,ixc^l,ixo^l,idims,wlc,wrc,wnew,x,fc,dxs)
364 if(need_hd_mom_flux) then
365 {do ix^db=hxomin^db,ixomax^db\}
366 ^c&fc(ix^d,iw_mom(^c),idims)=dxinv(idims)*fc_mom(ix^d,^c,idims)\
367 {end do\}
368 end if
369 end do
370 end if
371 else
372 inv_volume(ixo^s) = 1.d0/block%dvolume(ixo^s)
373 if(local_timestep) then
374 do idims= idims^lim
375 hx^d=kr(idims,^d)\
376 hxomin^d=ixomin^d-hx^d\
377 do iw=iwstart,nwflux
378 {do ix^db=hxomin^db,ixomax^db\}
379 fc(ix^d,iw,idims)=-block%dt(ix^d)*dtfactor*fc(ix^d,iw,idims)*block%surfaceC(ix^d,idims)
380 {end do\}
381 {do ix^db=ixomin^db,ixomax^db\}
382 wnew(ix^d,iw)=wnew(ix^d,iw)+(fc(ix^d,iw,idims)-fc(ix^d-hx^d,iw,idims))*inv_volume(ix^d)
383 {end do\}
384 end do
385 ! For the MUSCL scheme apply the characteristic based limiter
386 if (method==fs_tvdmu) &
387 call tvdlimit2(method,qdt,ixi^l,ixc^l,ixo^l,idims,wlc,wrc,wnew,x,fc,dxs)
388 end do
389 else
390 do idims= idims^lim
391 hx^d=kr(idims,^d)\
392 hxomin^d=ixomin^d-hx^d\
393 do iw=iwstart,nwflux
394 {do ix^db=hxomin^db,ixomax^db\}
395 fc(ix^d,iw,idims)=-qdt*fc(ix^d,iw,idims)*block%surfaceC(ix^d,idims)
396 {end do\}
397 {do ix^db=ixomin^db,ixomax^db\}
398 wnew(ix^d,iw)=wnew(ix^d,iw)+(fc(ix^d,iw,idims)-fc(ix^d-hx^d,iw,idims))*inv_volume(ix^d)
399 {end do\}
400 end do
401 if(need_hd_mom_flux) then
402 {do ix^db=hxomin^db,ixomax^db\}
403 ^c&fc(ix^d,iw_mom(^c),idims)=-qdt*fc_mom(ix^d,^c,idims)*block%surfaceC(ix^d,idims)\
404 {end do\}
405 end if
406 end do
407 end if
408 end if
409
410 if (.not.slab.and.idimsmin==1) &
411 call phys_add_source_geom(qdt,dtfactor,ixi^l,ixo^l,wct,wprim,wnew,x)
412
413 if(stagger_grid) call phys_face_to_center(ixo^l,snew)
414
415 ! check and optionally correct unphysical values
416 if(fix_small_values) then
417 call phys_handle_small_values(.false.,wnew,x,ixi^l,ixo^l,'multi-D finite_volume')
418 if(crash) then
419 ! replace erroneous values with values at previous step
420 wnew=wct
421 if(stagger_grid) snew%ws=sct%ws
422 end if
423 end if
424
425 call addsource2(qdt*dble(idimsmax-idimsmin+1)/dble(ndim),&
426 dtfactor*dble(idimsmax-idimsmin+1)/dble(ndim),&
427 ixi^l,ixo^l,1,nw,qtc,wct,wprim,qt,wnew,x,.false.,active)
428
429 end associate
430 contains
431
433 do iw=iwstart,nwflux
434 fc(ixc^s,iw,idims)=half*(flc(ixc^s,iw)+frc(ixc^s,iw))
435 end do
436 end subroutine get_riemann_flux_tvdmu
437
438 subroutine get_riemann_flux_tvdlf(iws,iwe,fL,fR,f)
439 integer, intent(in) :: iws,iwe
440 double precision, intent(in) :: fL(ixI^S,iws:iwe),fR(ixI^S,iws:iwe)
441 double precision, intent(out) :: f(ixI^S,iws:iwe)
442
443 double precision :: fac(ixC^S),phi
444 integer :: ix^D,jx^D
445
446 fac(ixc^s) = -0.5d0*tvdlfeps*cmaxc(ixc^s,ii)
447 do iw=iws,iwe
448 ! Add TVDLF dissipation to the flux
449 if(flux_type(idims, iw) /= flux_no_dissipation) then
450 if(flux_adaptive_diffusion) then
451 {do ix^db=ixcmin^db,ixcmax^db\}
452 jx^d=ix^d+kr(idims,^d)\
453 !> adaptive diffusion from Rempel et al. 2009, see also Rempel et al. 2014
454 !> the previous version is adopt
455 !if(((wRC(ix^D,iw)-wLC(ix^D,iw))*(sCT%w(jx^D,iw)-sCT%w(ix^D,iw))) .gt. 1.e-18) then
456 ! 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)
457 !else
458 ! phi=1.d0
459 !end if
460 phi = flux_adaptive_diffusion_min
461 if(((wrc(ix^d,iw)-wlc(ix^d,iw))*(sct%w(jx^d,iw)-sct%w(ix^d,iw))) .gt. 1.d-18) then
462 phi = max(flux_adaptive_diffusion_min, &
463 min(flux_adaptive_diffusion_scale * &
464 (wrc(ix^d,iw)-wlc(ix^d,iw))**2 / &
465 ((sct%w(jx^d,iw)-sct%w(ix^d,iw))**2 + 1.d-18), one))
466 else
467 phi = one
468 end if
469 f(ix^d,iw)=half*(fl(ix^d, iw)+fr(ix^d, iw))+fac(ix^d)*(wrc(ix^d,iw)-wlc(ix^d,iw))*phi
470 {end do\}
471 else
472 {do ix^db=ixcmin^db,ixcmax^db\}
473 f(ix^d,iw)=half*(fl(ix^d, iw)+fr(ix^d, iw))+fac(ix^d)*(wrc(ix^d,iw)-wlc(ix^d,iw))
474 {end do\}
475 end if
476 end if
477 end do
478 end subroutine get_riemann_flux_tvdlf
479
480 subroutine get_riemann_flux_hll(iws,iwe,fL,fR,f)
481 integer, intent(in) :: iws,iwe
482 double precision, intent(in) :: fL(ixI^S,iws:iwe),fR(ixI^S,iws:iwe)
483 double precision, intent(out) :: f(ixI^S,iws:iwe)
484
485 double precision :: phi
486 integer :: ix^D
487
488 if(flux_adaptive_diffusion) then
489 do iw=iws,iwe
490 if(flux_type(idims, iw) == flux_tvdlf) then
491 if(stagger_grid) then
492 ! CT MHD set zero normal B flux
493 f(ixc^s,iw)=0.d0
494 else
495 f(ixc^s,iw)=-tvdlfeps*half*max(cmaxc(ixc^s,ii),dabs(cminc(ixc^s,ii)))*&
496 (wrc(ixc^s,iw)-wlc(ixc^s,iw))
497 end if
498 else
499 {do ix^db=ixcmin^db,ixcmax^db\}
500 if(cminc(ix^d,ii) >= zero) then
501 f(ix^d,iw)=fl(ix^d,iw)
502 else if(cmaxc(ix^d,ii) <= zero) then
503 f(ix^d,iw)=fr(ix^d,iw)
504 else
505 !> reduced diffusion is from Wang et al. 2024
506 phi=max(abs(cmaxc(ix^d,ii)),abs(cminc(ix^d,ii)))/(cmaxc(ix^d,ii)-cminc(ix^d,ii))
507 f(ix^d,iw)=(cmaxc(ix^d,ii)*fl(ix^d, iw)-cminc(ix^d,ii)*fr(ix^d,iw)&
508 +phi*cminc(ix^d,ii)*cmaxc(ix^d,ii)*(wrc(ix^d,iw)-wlc(ix^d,iw)))&
509 /(cmaxc(ix^d,ii)-cminc(ix^d,ii))
510 end if
511 {end do\}
512 end if
513 end do
514 else
515 do iw=iws,iwe
516 if(flux_type(idims, iw) == flux_tvdlf) then
517 if(stagger_grid) then
518 ! CT MHD set zero normal B flux
519 f(ixc^s,iw)=0.d0
520 else
521 f(ixc^s,iw)=-tvdlfeps*half*max(cmaxc(ixc^s,ii),dabs(cminc(ixc^s,ii)))*&
522 (wrc(ixc^s,iw)-wlc(ixc^s,iw))
523 end if
524 else
525 {do ix^db=ixcmin^db,ixcmax^db\}
526 if(cminc(ix^d,ii) >= zero) then
527 f(ix^d,iw)=fl(ix^d,iw)
528 else if(cmaxc(ix^d,ii) <= zero) then
529 f(ix^d,iw)=fr(ix^d,iw)
530 else
531 f(ix^d,iw)=(cmaxc(ix^d,ii)*fl(ix^d, iw)-cminc(ix^d,ii)*fr(ix^d,iw)&
532 +cminc(ix^d,ii)*cmaxc(ix^d,ii)*(wrc(ix^d,iw)-wlc(ix^d,iw)))&
533 /(cmaxc(ix^d,ii)-cminc(ix^d,ii))
534 end if
535 {end do\}
536 end if
537 end do
538 end if
539 end subroutine get_riemann_flux_hll
540
541 subroutine get_riemann_flux_hllc(iws,iwe)
542 integer, intent(in) :: iws, iwe
543 double precision, dimension(ixI^S,1:nwflux) :: whll, Fhll, fCD
544 double precision, dimension(ixI^S) :: lambdaCD
545
546 integer, dimension(ixI^S) :: patchf
547 integer :: rho_, p_, e_, mom(1:ndir)
548
549 rho_ = iw_rho
550 if (allocated(iw_mom)) mom(:) = iw_mom(:)
551 e_ = iw_e
552
553 if(associated(phys_hllc_init_species)) then
554 call phys_hllc_init_species(ii, rho_, mom(:), e_)
555 endif
556
557 p_ = e_
558
559 patchf(ixc^s) = 1
560 where(cminc(ixc^s,1) >= zero)
561 patchf(ixc^s) = -2
562 elsewhere(cmaxc(ixc^s,1) <= zero)
563 patchf(ixc^s) = 2
564 endwhere
565 ! Use more diffusive scheme, is actually TVDLF and selected by patchf=4
566 if(method==fs_hllcd) &
567 call phys_diffuse_hllcd(ixi^l,ixc^l,idims,wlc,wrc,flc,frc,patchf)
568
569 !---- calculate speed lambda at CD ----!
570 if(any(patchf(ixc^s)==1)) &
571 call phys_get_lcd(wlc,wrc,flc,frc,cminc(ixi^s,ii),cmaxc(ixi^s,ii),idims,ixi^l,ixc^l, &
572 whll,fhll,lambdacd,patchf)
573
574 ! now patchf may be -1 or 1 due to phys_get_lCD
575 if(any(abs(patchf(ixc^s))== 1))then
576 !======== flux at intermediate state ========!
577 call phys_get_wcd(wlc,wrc,whll,frc,flc,fhll,patchf,lambdacd,&
578 cminc(ixi^s,ii),cmaxc(ixi^s,ii),ixi^l,ixc^l,idims,fcd)
579 endif ! Calculate the CD flux
580
581 do iw=iws,iwe
582 if (flux_type(idims, iw) == flux_tvdlf) then
583 flc(ixc^s,iw)=-tvdlfeps*half*max(cmaxc(ixc^s,ii),abs(cminc(ixc^s,ii))) * &
584 (wrc(ixc^s,iw) - wlc(ixc^s,iw))
585 else
586 where(patchf(ixc^s)==-2)
587 flc(ixc^s,iw)=flc(ixc^s,iw)
588 elsewhere(abs(patchf(ixc^s))==1)
589 flc(ixc^s,iw)=fcd(ixc^s,iw)
590 elsewhere(patchf(ixc^s)==2)
591 flc(ixc^s,iw)=frc(ixc^s,iw)
592 elsewhere(patchf(ixc^s)==3)
593 ! fallback option, reducing to HLL flux
594 flc(ixc^s,iw)=fhll(ixc^s,iw)
595 elsewhere(patchf(ixc^s)==4)
596 ! fallback option, reducing to TVDLF flux
597 flc(ixc^s,iw) = half*((flc(ixc^s,iw)+frc(ixc^s,iw)) &
598 -tvdlfeps * max(cmaxc(ixc^s,ii), dabs(cminc(ixc^s,ii))) * &
599 (wrc(ixc^s,iw)-wlc(ixc^s,iw)))
600 endwhere
601 end if
602
603 fc(ixc^s,iw,idims)=flc(ixc^s,iw)
604
605 end do ! Next iw
606 end subroutine get_riemann_flux_hllc
607
608 !> HLLD Riemann flux from Miyoshi 2005 JCP, 208, 315 and Guo 2016 JCP, 327, 543
609 subroutine get_riemann_flux_hlld(iws,iwe)
610 integer, intent(in) :: iws, iwe
611 double precision, dimension(ixI^S,1:nwflux) :: w1R,w1L,w2R,w2L
612 double precision, dimension(ixI^S) :: sm,s1R,s1L,suR,suL,Bx
613 double precision, dimension(ixI^S) :: pts,ptR,ptL,signBx,r1L,r1R,tmp
614 ! magnetic field from the right and the left reconstruction
615 double precision, dimension(ixI^S,ndir) :: BR, BL
616 integer :: ip1,ip2,ip3,idir,ix^D,^C&b^C_,^C&m^C_
617 integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
618
619 associate(sr=>cmaxc,sl=>cminc)
620
621 rho_=iw_rho
622 ^c&mom(^c)=iw_mom(^c)\
623 m^c_=mom(^c);
624 ^c&mag(^c)=iw_mag(^c)\
625 b^c_=mag(^c);
626 e_ = iw_e
627 p_ = e_
628
629 ip1=idims
630 ip3=3
631 if(b0field) then
632 br(ixc^s,:)=wrc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
633 bl(ixc^s,:)=wlc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
634 else
635 br(ixc^s,:)=wrc(ixc^s,mag(:))
636 bl(ixc^s,:)=wlc(ixc^s,mag(:))
637 end if
638 if(stagger_grid) then
639 bx(ixc^s)=block%ws(ixc^s,ip1)
640 else
641 ! HLL estimation of normal magnetic field at cell interfaces
642 ! Li, Shenghai, 2005 JCP, 203, 344, equation (33)
643 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))
644 end if
645 {!DEC$ VECTOR ALWAYS
646 do ix^db=ixcmin^db,ixcmax^db\}
647 ptr(ix^d)=wrp(ix^d,p_)+0.5d0*(^c&br(ix^d,^c)**2+)
648 ptl(ix^d)=wlp(ix^d,p_)+0.5d0*(^c&bl(ix^d,^c)**2+)
649 if(iw_equi_rho>0) then
650 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))
651 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))
652 else
653 sur(ix^d)=(sr(ix^d,ii)-wrp(ix^d,mom(ip1)))*wrc(ix^d,rho_)
654 sul(ix^d)=(sl(ix^d,ii)-wlp(ix^d,mom(ip1)))*wlc(ix^d,rho_)
655 end if
656 ! Miyoshi equation (38) and Guo euqation (20)
657 sm(ix^d)=(sur(ix^d)*wrp(ix^d,mom(ip1))-sul(ix^d)*wlp(ix^d,mom(ip1))-&
658 ptr(ix^d)+ptl(ix^d))/(sur(ix^d)-sul(ix^d))
659 ! Miyoshi equation (39) and Guo euqation (28)
660 w1r(ix^d,mom(ip1))=sm(ix^d)
661 w1l(ix^d,mom(ip1))=sm(ix^d)
662 w2r(ix^d,mom(ip1))=sm(ix^d)
663 w2l(ix^d,mom(ip1))=sm(ix^d)
664 ! Guo equation (22)
665 w1r(ix^d,mag(ip1))=bx(ix^d)
666 w1l(ix^d,mag(ip1))=bx(ix^d)
667 if(b0field) then
668 ptr(ix^d)=wrp(ix^d,p_)+0.5d0*(^c&wrc(ix^d,b^c_)**2+)
669 ptl(ix^d)=wlp(ix^d,p_)+0.5d0*(^c&wlc(ix^d,b^c_)**2+)
670 end if
671 ! Miyoshi equation (43) and Guo equation (27)
672 w1r(ix^d,rho_)=sur(ix^d)/(sr(ix^d,ii)-sm(ix^d))
673 w1l(ix^d,rho_)=sul(ix^d)/(sl(ix^d,ii)-sm(ix^d))
674 ip2=mod(ip1+1,ndir)
675 if(ip2==0) ip2=ndir
676 r1r(ix^d)=sur(ix^d)*(sr(ix^d,ii)-sm(ix^d))-bx(ix^d)**2
677 if(r1r(ix^d)/=0.d0) r1r(ix^d)=1.d0/r1r(ix^d)
678 r1l(ix^d)=sul(ix^d)*(sl(ix^d,ii)-sm(ix^d))-bx(ix^d)**2
679 if(r1l(ix^d)/=0.d0) r1l(ix^d)=1.d0/r1l(ix^d)
680 ! Miyoshi equation (44)
681 w1r(ix^d,mom(ip2))=wrp(ix^d,mom(ip2))-bx(ix^d)*br(ix^d,ip2)*&
682 (sm(ix^d)-wrp(ix^d,mom(ip1)))*r1r(ix^d)
683 w1l(ix^d,mom(ip2))=wlp(ix^d,mom(ip2))-bx(ix^d)*bl(ix^d,ip2)*&
684 (sm(ix^d)-wlp(ix^d,mom(ip1)))*r1l(ix^d)
685 ! partial solution for later usage
686 w1r(ix^d,mag(ip2))=(sur(ix^d)*(sr(ix^d,ii)-wrp(ix^d,mom(ip1)))-bx(ix^d)**2)*r1r(ix^d)
687 w1l(ix^d,mag(ip2))=(sul(ix^d)*(sl(ix^d,ii)-wlp(ix^d,mom(ip1)))-bx(ix^d)**2)*r1l(ix^d)
688 {^ifthreec
689 ip3=mod(ip1+2,ndir)
690 if(ip3==0) ip3=ndir
691 ! Miyoshi equation (46)
692 w1r(ix^d,mom(ip3))=wrp(ix^d,mom(ip3))-bx(ix^d)*br(ix^d,ip3)*&
693 (sm(ix^d)-wrp(ix^d,mom(ip1)))*r1r(ix^d)
694 w1l(ix^d,mom(ip3))=wlp(ix^d,mom(ip3))-bx(ix^d)*bl(ix^d,ip3)*&
695 (sm(ix^d)-wlp(ix^d,mom(ip1)))*r1l(ix^d)
696 ! Miyoshi equation (47)
697 w1r(ix^d,mag(ip3))=br(ix^d,ip3)*w1r(ix^d,mag(ip2))
698 w1l(ix^d,mag(ip3))=bl(ix^d,ip3)*w1l(ix^d,mag(ip2))
699 }
700 ! Miyoshi equation (45)
701 w1r(ix^d,mag(ip2))=br(ix^d,ip2)*w1r(ix^d,mag(ip2))
702 w1l(ix^d,mag(ip2))=bl(ix^d,ip2)*w1l(ix^d,mag(ip2))
703 if(b0field) then
704 ! Guo equation (26)
705 ^c&w1r(ix^d,b^c_)=w1r(ix^d,b^c_)-block%B0(ix^d,^c,ip1)\
706 ^c&w1l(ix^d,b^c_)=w1l(ix^d,b^c_)-block%B0(ix^d,^c,ip1)\
707 end if
708 ! equation (48)
709 if(phys_energy) then
710 ! Guo equation (25) equivalent to Miyoshi equation (41)
711 w1r(ix^d,p_)=sur(ix^d)*(sm(ix^d)-wrp(ix^d,mom(ip1)))+ptr(ix^d)
712 w1l(ix^d,p_)=w1r(ix^d,p_)
713 if(b0field) then
714 ! Guo equation (32)
715 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_))+)
716 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_))+)
717 end if
718 ! Miyoshi equation (48) and main part of Guo euqation (31)
719 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))+&
720 w1r(ix^d,p_)*sm(ix^d)+bx(ix^d)*((^c&wrp(ix^d,m^c_)*wrc(ix^d,b^c_)+)-&
721 (^c&w1r(ix^d,m^c_)*w1r(ix^d,b^c_)+)))/(sr(ix^d,ii)-sm(ix^d))
722 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))+&
723 w1l(ix^d,p_)*sm(ix^d)+bx(ix^d)*((^c&wlp(ix^d,m^c_)*wlc(ix^d,b^c_)+)-&
724 (^c&w1l(ix^d,m^c_)*w1l(ix^d,b^c_)+)))/(sl(ix^d,ii)-sm(ix^d))
725 if(b0field) then
726 ! Guo equation (31)
727 w1r(ix^d,e_)=w1r(ix^d,e_)+((^c&w1r(ix^d,b^c_)*block%B0(ix^d,^c,ip1)+)*sm(ix^d)-&
728 (^c&wrc(ix^d,b^c_)*block%B0(ix^d,^c,ip1)+)*wrp(ix^d,mom(ip1)))/(sr(ix^d,ii)-sm(ix^d))
729 w1l(ix^d,e_)=w1l(ix^d,e_)+((^c&w1l(ix^d,b^c_)*block%B0(ix^d,^c,ip1)+)*sm(ix^d)-&
730 (^c&wlc(ix^d,b^c_)*block%B0(ix^d,^c,ip1)+)*wlp(ix^d,mom(ip1)))/(sl(ix^d,ii)-sm(ix^d))
731 end if
732 if(iw_equi_p>0) then
733 w1r(ix^d,e_)=w1r(ix^d,e_)+1d0/(phys_gamma-1)*block%equi_vars(ix^d,iw_equi_p,ip1)*&
734 (sm(ix^d)-wrp(ix^d,mom(ip1)))/(sr(ix^d,ii)-sm(ix^d))
735 w1l(ix^d,e_)=w1l(ix^d,e_)+1d0/(phys_gamma-1)*block%equi_vars(ix^d,iw_equi_p,ip1)*&
736 (sm(ix^d)-wlp(ix^d,mom(ip1)))/(sl(ix^d,ii)-sm(ix^d))
737 end if
738 end if
739
740 ! Miyoshi equation (49) and Guo equation (35)
741 w2r(ix^d,rho_)=w1r(ix^d,rho_)
742 w2l(ix^d,rho_)=w1l(ix^d,rho_)
743 w2r(ix^d,mag(ip1))=w1r(ix^d,mag(ip1))
744 w2l(ix^d,mag(ip1))=w1l(ix^d,mag(ip1))
745 r1r(ix^d)=sqrt(w1r(ix^d,rho_))
746 r1l(ix^d)=sqrt(w1l(ix^d,rho_))
747 tmp(ix^d)=1.d0/(r1r(ix^d)+r1l(ix^d))
748 signbx(ix^d)=sign(1.d0,bx(ix^d))
749 ! Miyoshi equation (51) and Guo equation (33)
750 s1r(ix^d)=sm(ix^d)+abs(bx(ix^d))/r1r(ix^d)
751 s1l(ix^d)=sm(ix^d)-abs(bx(ix^d))/r1l(ix^d)
752 ! Miyoshi equation (59) and Guo equation (41)
753 w2r(ix^d,mom(ip2))=(r1l(ix^d)*w1l(ix^d,mom(ip2))+r1r(ix^d)*w1r(ix^d,mom(ip2))+&
754 (w1r(ix^d,mag(ip2))-w1l(ix^d,mag(ip2)))*signbx(ix^d))*tmp(ix^d)
755 w2l(ix^d,mom(ip2))=w2r(ix^d,mom(ip2))
756 ! Miyoshi equation (61) and Guo equation (43)
757 w2r(ix^d,mag(ip2))=(r1l(ix^d)*w1r(ix^d,mag(ip2))+r1r(ix^d)*w1l(ix^d,mag(ip2))+&
758 r1l(ix^d)*r1r(ix^d)*(w1r(ix^d,mom(ip2))-w1l(ix^d,mom(ip2)))*signbx(ix^d))*tmp(ix^d)
759 w2l(ix^d,mag(ip2))=w2r(ix^d,mag(ip2))
760 {^ifthreec
761 ! Miyoshi equation (60) and Guo equation (42)
762 w2r(ix^d,mom(ip3))=(r1l(ix^d)*w1l(ix^d,mom(ip3))+r1r(ix^d)*w1r(ix^d,mom(ip3))+&
763 (w1r(ix^d,mag(ip3))-w1l(ix^d,mag(ip3)))*signbx(ix^d))*tmp(ix^d)
764 w2l(ix^d,mom(ip3))=w2r(ix^d,mom(ip3))
765 ! Miyoshi equation (62) and Guo equation (44)
766 w2r(ix^d,mag(ip3))=(r1l(ix^d)*w1r(ix^d,mag(ip3))+r1r(ix^d)*w1l(ix^d,mag(ip3))+&
767 r1l(ix^d)*r1r(ix^d)*(w1r(ix^d,mom(ip3))-w1l(ix^d,mom(ip3)))*signbx(ix^d))*tmp(ix^d)
768 w2l(ix^d,mag(ip3))=w2r(ix^d,mag(ip3))
769 }
770 ! Miyoshi equation (63) and Guo equation (45)
771 if(phys_energy) then
772 w2r(ix^d,e_)=w1r(ix^d,e_)+r1r(ix^d)*((^c&w1r(ix^d,m^c_)*w1r(ix^d,b^c_)+)-&
773 (^c&w2r(ix^d,m^c_)*w2r(ix^d,b^c_)+))*signbx(ix^d)
774 w2l(ix^d,e_)=w1l(ix^d,e_)-r1l(ix^d)*((^c&w1l(ix^d,m^c_)*w1l(ix^d,b^c_)+)-&
775 (^c&w2l(ix^d,m^c_)*w2l(ix^d,b^c_)+))*signbx(ix^d)
776 end if
777
778 ! convert velocity to momentum
779 ^c&w1r(ix^d,m^c_)=w1r(ix^d,m^c_)*w1r(ix^d,rho_)\
780 ^c&w1l(ix^d,m^c_)=w1l(ix^d,m^c_)*w1l(ix^d,rho_)\
781 ^c&w2r(ix^d,m^c_)=w2r(ix^d,m^c_)*w2r(ix^d,rho_)\
782 ^c&w2l(ix^d,m^c_)=w2l(ix^d,m^c_)*w2l(ix^d,rho_)\
783 if(iw_equi_rho>0) then
784 w1r(ix^d,rho_)=w1r(ix^d,rho_)-block%equi_vars(ix^d,iw_equi_rho,ip1)
785 w1l(ix^d,rho_)=w1l(ix^d,rho_)-block%equi_vars(ix^d,iw_equi_rho,ip1)
786 w2r(ix^d,rho_)=w2r(ix^d,rho_)-block%equi_vars(ix^d,iw_equi_rho,ip1)
787 w2l(ix^d,rho_)=w2l(ix^d,rho_)-block%equi_vars(ix^d,iw_equi_rho,ip1)
788 end if
789 {end do\}
790
791 do iw=iws,iwe
792 if(flux_type(idims, iw)==flux_special) then
793 ! known flux (fLC=fRC) for normal B and psi_ in GLM method
794 {!dir$ ivdep
795 do ix^db=ixcmin^db,ixcmax^db\}
796 fc(ix^d,iw,ip1)=flc(ix^d,iw)
797 {end do\}
798 else if(flux_type(idims, iw)==flux_hll) then
799 ! using hll flux for tracers
800 {!dir$ ivdep
801 do ix^db=ixcmin^db,ixcmax^db\}
802 fc(ix^d,iw,ip1)=(sr(ix^d,ii)*flc(ix^d,iw)-sl(ix^d,ii)*frc(ix^d,iw) &
803 +sr(ix^d,ii)*sl(ix^d,ii)*(wrc(ix^d,iw)-wlc(ix^d,iw)))/(sr(ix^d,ii)-sl(ix^d,ii))
804 {end do\}
805 else
806 ! construct hlld flux
807 ! Miyoshi equation (66) and Guo equation (46)
808 {!dir$ ivdep
809 !DEC$ VECTOR ALWAYS
810 do ix^db=ixcmin^db,ixcmax^db\}
811 if(sl(ix^d,ii)>0.d0) then
812 fc(ix^d,iw,ip1)=flc(ix^d,iw)
813 else if(s1l(ix^d)>=0.d0) then
814 fc(ix^d,iw,ip1)=flc(ix^d,iw)+sl(ix^d,ii)*(w1l(ix^d,iw)-wlc(ix^d,iw))
815 else if(sm(ix^d)>=0.d0) then
816 fc(ix^d,iw,ip1)=flc(ix^d,iw)+sl(ix^d,ii)*(w1l(ix^d,iw)-wlc(ix^d,iw))+&
817 s1l(ix^d)*(w2l(ix^d,iw)-w1l(ix^d,iw))
818 else if(s1r(ix^d)>=0.d0) then
819 fc(ix^d,iw,ip1)=frc(ix^d,iw)+sr(ix^d,ii)*(w1r(ix^d,iw)-wrc(ix^d,iw))+&
820 s1r(ix^d)*(w2r(ix^d,iw)-w1r(ix^d,iw))
821 else if(sr(ix^d,ii)>=0.d0) then
822 fc(ix^d,iw,ip1)=frc(ix^d,iw)+sr(ix^d,ii)*(w1r(ix^d,iw)-wrc(ix^d,iw))
823 else if(sr(ix^d,ii)<0.d0) then
824 fc(ix^d,iw,ip1)=frc(ix^d,iw)
825 end if
826 {end do\}
827 end if
828 end do
829
830 end associate
831 end subroutine get_riemann_flux_hlld
832
833 !> HLLD Riemann flux from Miyoshi 2005 JCP, 208, 315 and Guo 2016 JCP, 327, 543
834 !> https://arxiv.org/pdf/2108.04991.pdf
835 subroutine get_riemann_flux_hlld_mag2(iws,iwe)
836 implicit none
837 integer, intent(in) :: iws, iwe
838
839 double precision, dimension(ixI^S,1:nwflux) :: w1R,w1L,f1R,f1L,f2R,f2L
840 double precision, dimension(ixI^S,1:nwflux) :: w2R,w2L
841 double precision, dimension(ixI^S) :: sm,s1R,s1L,suR,suL,Bx
842 double precision, dimension(ixI^S) :: pts,ptR,ptL,signBx,r1L,r1R,tmp
843 ! velocity from the right and the left reconstruction
844 double precision, dimension(ixI^S,ndir) :: vRC, vLC
845 ! magnetic field from the right and the left reconstruction
846 double precision, dimension(ixI^S,ndir) :: BR, BL
847 integer :: ip1,ip2,ip3,idir,ix^D
848 double precision :: phiPres, thetaSM, du, dv, dw
849 integer :: ixV^L, ixVb^L, ixVc^L, ixVd^L, ixVe^L, ixVf^L
850 integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
851 double precision, parameter :: aParam = 4d0
852
853 rho_ = iw_rho
854 mom(:) = iw_mom(:)
855 mag(:) = iw_mag(:)
856 p_ = iw_e
857 e_ = iw_e
858
859 associate(sr=>cmaxc,sl=>cminc)
860
861 f1r=0.d0
862 f1l=0.d0
863 ip1=idims
864 ip3=3
865
866 vrc(ixc^s,:)=wrp(ixc^s,mom(:))
867 vlc(ixc^s,:)=wlp(ixc^s,mom(:))
868
869 ! reuse s1L s1R
870 call get_hlld2_modif_c(wlp,x,ixi^l,ixo^l,s1l)
871 call get_hlld2_modif_c(wrp,x,ixi^l,ixo^l,s1r)
872 !phiPres = min(1, maxval(max(s1L(ixO^S),s1R(ixO^S))/cmaxC(ixO^S,1)))
873 phipres = min(1d0, maxval(max(s1l(ixo^s),s1r(ixo^s)))/maxval(cmaxc(ixo^s,1)))
874 phipres = phipres*(2d0 - phipres)
875
876 !we use here not reconstructed velocity: wprim?
877 ixv^l=ixo^l;
878 !first dim
879 ixvmin1=ixomin1+1
880 ixvmax1=ixomax1+1
881 du = minval(wprim(ixv^s,mom(1))-wprim(ixo^s,mom(1)))
882 if(du>0d0) du=0d0
883 dv = 0d0
884 dw = 0d0
885
886 {^nooned
887 !second dim
888 !i,j-1,k
889 ixv^l=ixo^l;
890 ixvmin2=ixomin2-1
891 ixvmax2=ixomax2-1
892
893 !i,j+1,k
894 ixvb^l=ixo^l;
895 ixvbmin2=ixomin2+1
896 ixvbmax2=ixomax2+1
897
898 !i+1,j,k
899 ixvc^l=ixo^l;
900 ixvcmin1=ixomin1+1
901 ixvcmax1=ixomax1+1
902
903 !i+1,j-1,k
904 ixvd^l=ixo^l;
905 ixvdmin1=ixomin1+1
906 ixvdmax1=ixomax1+1
907 ixvdmin2=ixomin2-1
908 ixvdmax2=ixomax2-1
909
910 !i+1,j+1,k
911 ixve^l=ixo^l;
912 ixvemin1=ixomin1+1
913 ixvemax1=ixomax1+1
914 ixvemin2=ixomin2+1
915 ixvemax2=ixomax2+1
916
917 dv = minval(min(wprim(ixo^s,mom(2))-wprim(ixv^s,mom(2)),&
918 wprim(ixvb^s,mom(2))-wprim(ixo^s,mom(2)),&
919 wprim(ixvc^s,mom(2))-wprim(ixvd^s,mom(2)),&
920 wprim(ixve^s,mom(2))-wprim(ixvc^s,mom(2))&
921 ))
922 if(dv>0d0) dv=0d0}
923
924 {^ifthreed
925 !third dim
926 !i,j,k-1
927 ixv^l=ixo^l;
928 ixvmin3=ixomin3-1
929 ixvmax3=ixomax3-1
930
931 !i,j,k+1
932 ixvb^l=ixo^l;
933 ixvbmin3=ixomin3+1
934 ixvbmax3=ixomax3+1
935
936 !i+1,j,k
937 ixvc^l=ixo^l;
938 ixvcmin1=ixomin1+1
939 ixvcmax1=ixomax1+1
940
941 !i+1,j,k-1
942 ixvd^l=ixo^l;
943 ixvdmin1=ixomin1+1
944 ixvdmax1=ixomax1+1
945 ixvdmin3=ixomin3-1
946 ixvdmax3=ixomax3-1
947
948 !i+1,j,k+1
949 ixve^l=ixo^l;
950 ixvemin1=ixomin1+1
951 ixvemax1=ixomax1+1
952 ixvemin3=ixomin3+1
953 ixvemax3=ixomax3+1
954 dw = minval(min(wprim(ixo^s,mom(3))-wprim(ixv^s,mom(3)),&
955 wprim(ixvb^s,mom(3))-wprim(ixo^s,mom(3)),&
956 wprim(ixvc^s,mom(3))-wprim(ixvd^s,mom(3)),&
957 wprim(ixve^s,mom(3))-wprim(ixvc^s,mom(3))&
958 ))
959 if(dw>0d0) dw=0d0}
960 thetasm = maxval(cmaxc(ixo^s,1))
961
962 thetasm = (min(1d0, (thetasm-du)/(thetasm-min(dv,dw))))**aparam
963
964 if(b0field) then
965 br(ixc^s,:)=wrc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
966 bl(ixc^s,:)=wlc(ixc^s,mag(:))+block%B0(ixc^s,:,ip1)
967 else
968 br(ixc^s,:)=wrc(ixc^s,mag(:))
969 bl(ixc^s,:)=wlc(ixc^s,mag(:))
970 end if
971 ! HLL estimation of normal magnetic field at cell interfaces
972 bx(ixc^s)=(sr(ixc^s,index_v_mag)*br(ixc^s,ip1)-sl(ixc^s,index_v_mag)*bl(ixc^s,ip1)-&
973 flc(ixc^s,mag(ip1))-frc(ixc^s,mag(ip1)))/(sr(ixc^s,index_v_mag)-sl(ixc^s,index_v_mag))
974 ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(br(ixc^s,:)**2,dim=ndim+1)
975 ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(bl(ixc^s,:)**2,dim=ndim+1)
976 sur(ixc^s)=(sr(ixc^s,index_v_mag)-vrc(ixc^s,ip1))*wrc(ixc^s,rho_)
977 sul(ixc^s)=(sl(ixc^s,index_v_mag)-vlc(ixc^s,ip1))*wlc(ixc^s,rho_)
978 ! Miyoshi equation (38) and Guo euqation (20)
979 sm(ixc^s)=(sur(ixc^s)*vrc(ixc^s,ip1)-sul(ixc^s)*vlc(ixc^s,ip1)-&
980 thetasm*(ptr(ixc^s)-ptl(ixc^s)) )/(sur(ixc^s)-sul(ixc^s))
981 ! Miyoshi equation (39) and Guo euqation (28)
982 w1r(ixc^s,mom(ip1))=sm(ixc^s)
983 w1l(ixc^s,mom(ip1))=sm(ixc^s)
984 w2r(ixc^s,mom(ip1))=sm(ixc^s)
985 w2l(ixc^s,mom(ip1))=sm(ixc^s)
986 ! Guo equation (22)
987 w1r(ixc^s,mag(ip1))=bx(ixc^s)
988 w1l(ixc^s,mag(ip1))=bx(ixc^s)
989 if(b0field) then
990 ptr(ixc^s)=wrp(ixc^s,p_)+0.5d0*sum(wrc(ixc^s,mag(:))**2,dim=ndim+1)
991 ptl(ixc^s)=wlp(ixc^s,p_)+0.5d0*sum(wlc(ixc^s,mag(:))**2,dim=ndim+1)
992 end if
993
994 ! Miyoshi equation (43) and Guo equation (27)
995 w1r(ixc^s,rho_)=sur(ixc^s)/(sr(ixc^s,index_v_mag)-sm(ixc^s))
996 w1l(ixc^s,rho_)=sul(ixc^s)/(sl(ixc^s,index_v_mag)-sm(ixc^s))
997
998 ip2=mod(ip1+1,ndir)
999 if(ip2==0) ip2=ndir
1000 r1r(ixc^s)=sur(ixc^s)*(sr(ixc^s,index_v_mag)-sm(ixc^s))-bx(ixc^s)**2
1001 where(r1r(ixc^s)/=0.d0)
1002 r1r(ixc^s)=1.d0/r1r(ixc^s)
1003 endwhere
1004 r1l(ixc^s)=sul(ixc^s)*(sl(ixc^s,index_v_mag)-sm(ixc^s))-bx(ixc^s)**2
1005 where(r1l(ixc^s)/=0.d0)
1006 r1l(ixc^s)=1.d0/r1l(ixc^s)
1007 endwhere
1008 ! Miyoshi equation (44)
1009 w1r(ixc^s,mom(ip2))=vrc(ixc^s,ip2)-bx(ixc^s)*br(ixc^s,ip2)*&
1010 (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
1011 w1l(ixc^s,mom(ip2))=vlc(ixc^s,ip2)-bx(ixc^s)*bl(ixc^s,ip2)*&
1012 (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
1013 ! partial solution for later usage
1014 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)
1015 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)
1016 if(ndir==3) then
1017 ip3=mod(ip1+2,ndir)
1018 if(ip3==0) ip3=ndir
1019 ! Miyoshi equation (46)
1020 w1r(ixc^s,mom(ip3))=vrc(ixc^s,ip3)-bx(ixc^s)*br(ixc^s,ip3)*&
1021 (sm(ixc^s)-vrc(ixc^s,ip1))*r1r(ixc^s)
1022 w1l(ixc^s,mom(ip3))=vlc(ixc^s,ip3)-bx(ixc^s)*bl(ixc^s,ip3)*&
1023 (sm(ixc^s)-vlc(ixc^s,ip1))*r1l(ixc^s)
1024 ! Miyoshi equation (47)
1025 w1r(ixc^s,mag(ip3))=br(ixc^s,ip3)*w1r(ixc^s,mag(ip2))
1026 w1l(ixc^s,mag(ip3))=bl(ixc^s,ip3)*w1l(ixc^s,mag(ip2))
1027 end if
1028 ! Miyoshi equation (45)
1029 w1r(ixc^s,mag(ip2))=br(ixc^s,ip2)*w1r(ixc^s,mag(ip2))
1030 w1l(ixc^s,mag(ip2))=bl(ixc^s,ip2)*w1l(ixc^s,mag(ip2))
1031 if(b0field) then
1032 ! Guo equation (26)
1033 w1r(ixc^s,mag(:))=w1r(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
1034 w1l(ixc^s,mag(:))=w1l(ixc^s,mag(:))-block%B0(ixc^s,:,ip1)
1035 end if
1036 ! equation (48)
1037 if(phys_energy) then
1038 ! Guo equation (25) equivalent to Miyoshi equation (41)
1039 w1r(ixc^s,p_)=(sur(ixc^s)*ptl(ixc^s) - sul(ixc^s)*ptr(ixc^s) +&
1040 phipres * sur(ixc^s)*sul(ixc^s)*(vrc(ixc^s,ip1)-vlc(ixc^s,ip1)))/&
1041 (sur(ixc^s)-sul(ixc^s))
1042 w1l(ixc^s,p_)=w1r(ixc^s,p_)
1043 if(b0field) then
1044 ! Guo equation (32)
1045 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)
1046 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)
1047 end if
1048 ! Miyoshi equation (48) and main part of Guo euqation (31)
1049 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)+&
1050 w1r(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vrc(ixc^s,:)*wrc(ixc^s,mag(:)),dim=ndim+1)-&
1051 sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)))/(sr(ixc^s,index_v_mag)-sm(ixc^s))
1052 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)+&
1053 w1l(ixc^s,p_)*sm(ixc^s)+bx(ixc^s)*(sum(vlc(ixc^s,:)*wlc(ixc^s,mag(:)),dim=ndim+1)-&
1054 sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)))/(sl(ixc^s,index_v_mag)-sm(ixc^s))
1055 if(b0field) then
1056 ! Guo equation (31)
1057 w1r(ixc^s,e_)=w1r(ixc^s,e_)+(sum(w1r(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
1058 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))
1059 w1l(ixc^s,e_)=w1l(ixc^s,e_)+(sum(w1l(ixc^s,mag(:))*block%B0(ixc^s,:,ip1),dim=ndim+1)*sm(ixc^s)-&
1060 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))
1061 end if
1062 end if
1063
1064 ! Miyoshi equation (49) and Guo equation (35)
1065 w2r(ixc^s,rho_)=w1r(ixc^s,rho_)
1066 w2l(ixc^s,rho_)=w1l(ixc^s,rho_)
1067 w2r(ixc^s,mag(ip1))=w1r(ixc^s,mag(ip1))
1068 w2l(ixc^s,mag(ip1))=w1l(ixc^s,mag(ip1))
1069
1070 r1r(ixc^s)=sqrt(w1r(ixc^s,rho_))
1071 r1l(ixc^s)=sqrt(w1l(ixc^s,rho_))
1072 tmp(ixc^s)=1.d0/(r1r(ixc^s)+r1l(ixc^s))
1073 signbx(ixc^s)=sign(1.d0,bx(ixc^s))
1074 ! Miyoshi equation (51) and Guo equation (33)
1075 s1r(ixc^s)=sm(ixc^s)+abs(bx(ixc^s))/r1r(ixc^s)
1076 s1l(ixc^s)=sm(ixc^s)-abs(bx(ixc^s))/r1l(ixc^s)
1077 ! Miyoshi equation (59) and Guo equation (41)
1078 w2r(ixc^s,mom(ip2))=(r1l(ixc^s)*w1l(ixc^s,mom(ip2))+r1r(ixc^s)*w1r(ixc^s,mom(ip2))+&
1079 (w1r(ixc^s,mag(ip2))-w1l(ixc^s,mag(ip2)))*signbx(ixc^s))*tmp(ixc^s)
1080 w2l(ixc^s,mom(ip2))=w2r(ixc^s,mom(ip2))
1081 ! Miyoshi equation (61) and Guo equation (43)
1082 w2r(ixc^s,mag(ip2))=(r1l(ixc^s)*w1r(ixc^s,mag(ip2))+r1r(ixc^s)*w1l(ixc^s,mag(ip2))+&
1083 r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip2))-w1l(ixc^s,mom(ip2)))*signbx(ixc^s))*tmp(ixc^s)
1084 w2l(ixc^s,mag(ip2))=w2r(ixc^s,mag(ip2))
1085 if(ndir==3) then
1086 ! Miyoshi equation (60) and Guo equation (42)
1087 w2r(ixc^s,mom(ip3))=(r1l(ixc^s)*w1l(ixc^s,mom(ip3))+r1r(ixc^s)*w1r(ixc^s,mom(ip3))+&
1088 (w1r(ixc^s,mag(ip3))-w1l(ixc^s,mag(ip3)))*signbx(ixc^s))*tmp(ixc^s)
1089 w2l(ixc^s,mom(ip3))=w2r(ixc^s,mom(ip3))
1090 ! Miyoshi equation (62) and Guo equation (44)
1091 w2r(ixc^s,mag(ip3))=(r1l(ixc^s)*w1r(ixc^s,mag(ip3))+r1r(ixc^s)*w1l(ixc^s,mag(ip3))+&
1092 r1l(ixc^s)*r1r(ixc^s)*(w1r(ixc^s,mom(ip3))-w1l(ixc^s,mom(ip3)))*signbx(ixc^s))*tmp(ixc^s)
1093 w2l(ixc^s,mag(ip3))=w2r(ixc^s,mag(ip3))
1094 end if
1095 ! Miyoshi equation (63) and Guo equation (45)
1096 if(phys_energy) then
1097 w2r(ixc^s,e_)=w1r(ixc^s,e_)+r1r(ixc^s)*(sum(w1r(ixc^s,mom(:))*w1r(ixc^s,mag(:)),dim=ndim+1)-&
1098 sum(w2r(ixc^s,mom(:))*w2r(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
1099 w2l(ixc^s,e_)=w1l(ixc^s,e_)-r1l(ixc^s)*(sum(w1l(ixc^s,mom(:))*w1l(ixc^s,mag(:)),dim=ndim+1)-&
1100 sum(w2l(ixc^s,mom(:))*w2l(ixc^s,mag(:)),dim=ndim+1))*signbx(ixc^s)
1101 end if
1102
1103 ! convert velocity to momentum
1104 do idir=1,ndir
1105 w1r(ixc^s,mom(idir))=w1r(ixc^s,mom(idir))*w1r(ixc^s,rho_)
1106 w1l(ixc^s,mom(idir))=w1l(ixc^s,mom(idir))*w1l(ixc^s,rho_)
1107 w2r(ixc^s,mom(idir))=w2r(ixc^s,mom(idir))*w2r(ixc^s,rho_)
1108 w2l(ixc^s,mom(idir))=w2l(ixc^s,mom(idir))*w2l(ixc^s,rho_)
1109 end do
1110
1111 ! get fluxes of intermedate states
1112 do iw=iws,iwe
1113 ! CT MHD does not need normal B flux
1114 if(stagger_grid .and. flux_type(idims, iw) == flux_tvdlf) cycle
1115 if(flux_type(idims, iw) == flux_special) then
1116 ! known flux (fLC=fRC) for normal B and psi_ in GLM method
1117 f1l(ixc^s,iw)=flc(ixc^s,iw)
1118 f1r(ixc^s,iw)=f1l(ixc^s,iw)
1119 f2l(ixc^s,iw)=f1l(ixc^s,iw)
1120 f2r(ixc^s,iw)=f1l(ixc^s,iw)
1121 else if(flux_type(idims, iw) == flux_hll) then
1122 ! using hll flux for tracers
1123 f1l(ixc^s,iw)=(sr(ixc^s,index_v_mag)*flc(ixc^s, iw)-sl(ixc^s,index_v_mag)*frc(ixc^s, iw) &
1124 +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))
1125 f1r(ixc^s,iw)=f1l(ixc^s,iw)
1126 f2l(ixc^s,iw)=f1l(ixc^s,iw)
1127 f2r(ixc^s,iw)=f1l(ixc^s,iw)
1128 else
1129 f1l(ixc^s,iw)=flc(ixc^s,iw)+sl(ixc^s,index_v_mag)*(w1l(ixc^s,iw)-wlc(ixc^s,iw))
1130 f1r(ixc^s,iw)=frc(ixc^s,iw)+sr(ixc^s,index_v_mag)*(w1r(ixc^s,iw)-wrc(ixc^s,iw))
1131 f2l(ixc^s,iw)=f1l(ixc^s,iw)+s1l(ixc^s)*(w2l(ixc^s,iw)-w1l(ixc^s,iw))
1132 f2r(ixc^s,iw)=f1r(ixc^s,iw)+s1r(ixc^s)*(w2r(ixc^s,iw)-w1r(ixc^s,iw))
1133 end if
1134 end do
1135
1136 ! Miyoshi equation (66) and Guo equation (46)
1137 {do ix^db=ixcmin^db,ixcmax^db\}
1138 if(sl(ix^d,index_v_mag)>0.d0) then
1139 fc(ix^d,iws:iwe,ip1)=flc(ix^d,iws:iwe)
1140 else if(s1l(ix^d)>=0.d0) then
1141 fc(ix^d,iws:iwe,ip1)=f1l(ix^d,iws:iwe)
1142 else if(sm(ix^d)>=0.d0) then
1143 fc(ix^d,iws:iwe,ip1)=f2l(ix^d,iws:iwe)
1144 else if(s1r(ix^d)>=0.d0) then
1145 fc(ix^d,iws:iwe,ip1)=f2r(ix^d,iws:iwe)
1146 else if(sr(ix^d,index_v_mag)>=0.d0) then
1147 fc(ix^d,iws:iwe,ip1)=f1r(ix^d,iws:iwe)
1148 else if(sr(ix^d,index_v_mag)<0.d0) then
1149 fc(ix^d,iws:iwe,ip1)=frc(ix^d,iws:iwe)
1150 end if
1151 {end do\}
1152
1153 end associate
1154 end subroutine get_riemann_flux_hlld_mag2
1155
1156 !> Calculate fast magnetosonic wave speed
1157 subroutine get_hlld2_modif_c(w,x,ixI^L,ixO^L,csound)
1159
1160 integer, intent(in) :: ixI^L, ixO^L
1161 double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1162 double precision, intent(out):: csound(ixI^S)
1163 double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
1164 double precision :: inv_rho(ixO^S), gamma_A2(ixO^S)
1165 integer :: rho_, p_, e_, mom(1:ndir), mag(1:ndir)
1166
1167 rho_ = iw_rho
1168 mom(:) = iw_mom(:)
1169 mag(:) = iw_mag(:)
1170 p_ = iw_e
1171 e_ = iw_e
1172
1173 inv_rho=1.d0/w(ixo^s,rho_)
1174
1175 ! store |B|^2 in v
1176
1177 if (b0field) then
1178 b2(ixo^s) = sum((w(ixo^s, mag(:))+block%B0(ixo^s,:,b0i))**2, dim=ndim+1)
1179 else
1180 b2(ixo^s) = sum(w(ixo^s, mag(:))**2, dim=ndim+1)
1181 end if
1182
1183
1184 if (b0field) then
1185 avmincs2= w(ixo^s, mag(idims))+block%B0(ixo^s,idims,b0i)
1186 else
1187 avmincs2= w(ixo^s, mag(idims))
1188 end if
1189
1190
1191 csound(ixo^s) = sum(w(ixo^s, mom(:))**2, dim=ndim+1)
1192
1193 cfast2(ixo^s) = b2(ixo^s) * inv_rho+csound(ixo^s)
1194 avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
1195 * avmincs2(ixo^s)**2 &
1196 * inv_rho
1197
1198 where(avmincs2(ixo^s)<zero)
1199 avmincs2(ixo^s)=zero
1200 end where
1201
1202 avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
1203
1204 csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
1205
1206 end subroutine get_hlld2_modif_c
1207
1208 end subroutine finite_volume
1209
1210 !> Determine the upwinded wLC(ixL) and wRC(ixR) from w.
1211 !> the wCT is only used when PPM is exploited.
1212 subroutine reconstruct_lr(ixI^L,ixL^L,ixR^L,idims,w,wLC,wRC,wLp,wRp,x,dxdim)
1213 use mod_physics
1215 use mod_limiter
1216 use mod_comm_lib, only: mpistop
1218
1219 integer, intent(in) :: ixi^l, ixl^l, ixr^l, idims
1220 double precision, intent(in) :: dxdim
1221 ! cell center w in primitive form
1222 double precision, dimension(ixI^S,1:nw) :: w
1223 ! left and right constructed status in conservative form
1224 double precision, dimension(ixI^S,1:nw) :: wlc, wrc
1225 ! left and right constructed status in primitive form
1226 double precision, dimension(ixI^S,1:nw) :: wlp, wrp
1227 double precision, dimension(ixI^S,1:ndim) :: x
1228
1229 integer :: jxr^l, ixc^l, jxc^l, hxc^l, ixo^l, hxo^l, iw, idir
1230 !> RJV: the PPM reconstruction residual and the alternation switch
1231 double precision :: rjve(ixi^s), rjvs(ixi^s)
1232 double precision :: ldw(ixi^s), rdw(ixi^s), dwc(ixi^s)
1233 double precision :: wb_phi(ixi^s), wb_phi_face(ixi^s), wb_t(ixi^s)
1234 double precision :: tw(3)
1235
1236 jxr^l=ixr^l+kr(idims,^d);
1237 ! Well-balanced transform: subtract local HSE from pressure before limiting
1238 call timer_open(tw)
1239 if (associated(phys_wb_transform)) then
1240 call phys_wb_transform(ixi^l, ixi^l, idims, w, x, wb_phi, &
1241 wb_phi_face, wb_t)
1242 ! Re-initialise wLp/wRp to transformed cell-centre values.
1243 wlp(ixl^s, 1:nwflux) = w(ixl^s, 1:nwflux)
1244 wrp(ixr^s, 1:nwflux) = w(jxr^s, 1:nwflux)
1245 end if
1247
1248 call timer_open(tw)
1249 select case (type_limiter(block%level))
1250 case (limiter_mp5)
1251 call mp5limiter(ixi^l,ixl^l,idims,w,wlp,wrp)
1252 case (limiter_weno3)
1253 call weno3limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1254 case (limiter_wenoyc3)
1255 call weno3limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1256 case (limiter_weno5)
1257 call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1258 case (limiter_weno5nm)
1259 call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,1)
1260 case (limiter_wenoz5)
1261 call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1262 case (limiter_wenoz5nm)
1263 call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,2)
1264 case (limiter_wenozp5)
1265 call weno5limiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,3)
1266 case (limiter_wenozp5nm)
1267 call weno5nmlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp,3)
1268 case (limiter_weno5cu6)
1269 call weno5cu6limiter(ixi^l,ixl^l,idims,w,wlp,wrp)
1270 case (limiter_teno5ad)
1271 call teno5adlimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp)
1272 case (limiter_weno7)
1273 call weno7limiter(ixi^l,ixl^l,idims,w,wlp,wrp,1)
1274 case (limiter_mpweno7)
1275 call weno7limiter(ixi^l,ixl^l,idims,w,wlp,wrp,2)
1276 case (limiter_venk)
1277 call venklimiter(ixi^l,ixl^l,idims,dxdim,w,wlp,wrp)
1278 if(fix_small_values) then
1279 call phys_handle_small_values(.true.,wlp,x,ixi^l,ixl^l,'reconstruct left')
1280 call phys_handle_small_values(.true.,wrp,x,ixi^l,ixr^l,'reconstruct right')
1281 end if
1282 case (limiter_ppm)
1283 ixcmin^d=ixlmin^d+kr(idims,^d);
1284 ixcmax^d=ixlmax^d;
1285 call ppmlimiter(ixi^l,ixc^l,idims,w,w,wlp,wrp)
1286 ! Residual-jump velocity: restore the ripple the PPM face values remove, so that the
1287 ! Riemann solver damps it. e lives on ixO = [ixLmin, ixLmax+1] and the switch on ixC
1288 if (ppm_rjv > zero) then
1289 ixomin^d=ixlmin^d; ixomax^d=ixlmax^d+kr(idims,^d);
1290 hxo^l=ixo^l-kr(idims,^d); hxc^l=ixc^l-kr(idims,^d); jxc^l=ixc^l+kr(idims,^d);
1291 do idir=1,ndir
1292 iw = iw_mom(idir)
1293 ! e_i = v_i - (P_{i+1/2} + P_{i-1/2})/2 from the cell's own limited edges, wLp(i) on
1294 ! the right and wRp(i-1) on the left, which is a6/6 of the PPM parabola
1295 rjve(ixo^s)=w(ixo^s,iw)-half*(wlp(ixo^s,iw)+wrp(hxo^s,iw))
1296 ! s_i = ppm_rjv where e alternates across three cells, and zero elsewhere
1297 rjvs(ixo^s)=zero
1298 where (rjve(hxc^s)*rjve(ixc^s) < zero .and. rjve(ixc^s)*rjve(jxc^s) < zero)
1299 rjvs(ixc^s)=ppm_rjv
1300 end where
1301 wlp(ixl^s,iw)=wlp(ixl^s,iw)+rjvs(ixl^s)*rjve(ixl^s)
1302 wrp(ixr^s,iw)=wrp(ixr^s,iw)+rjvs(jxr^s)*rjve(jxr^s)
1303 ! cap at the piecewise-constant jump, since e grows once the PPM clips fire
1304 wlp(ixl^s,iw)=min(max(wlp(ixl^s,iw),min(w(ixl^s,iw),w(jxr^s,iw))), &
1305 max(w(ixl^s,iw),w(jxr^s,iw)))
1306 wrp(ixr^s,iw)=min(max(wrp(ixr^s,iw),min(w(ixr^s,iw),w(jxr^s,iw))), &
1307 max(w(ixr^s,iw),w(jxr^s,iw)))
1308 end do
1309 end if
1310 if(fix_small_values) then
1311 call phys_handle_small_values(.true.,wlp,x,ixi^l,ixc^l,'reconstruct left')
1312 call phys_handle_small_values(.true.,wrp,x,ixi^l,ixc^l,'reconstruct right')
1313 end if
1314 case default
1315 ixcmax^d=jxrmax^d; ixcmin^d=ixlmin^d-kr(idims,^d);
1316 jxc^l=ixc^l+kr(idims,^d);
1317 do iw=1,nwflux
1318 if (loglimit(iw)) then
1319 w(ixcmin^d:jxcmax^d,iw)=dlog10(w(ixcmin^d:jxcmax^d,iw))
1320 wlp(ixl^s,iw)=dlog10(wlp(ixl^s,iw))
1321 wrp(ixr^s,iw)=dlog10(wrp(ixr^s,iw))
1322 end if
1323
1324 dwc(ixc^s)=w(jxc^s,iw)-w(ixc^s,iw)
1325
1326 ! limit flux from left and/or right
1327 call dwlimiter2(dwc,ixi^l,ixc^l,idims,type_limiter(block%level),ldw,rdw)
1328 wlp(ixl^s,iw)=wlp(ixl^s,iw)+half*ldw(ixl^s)
1329 wrp(ixr^s,iw)=wrp(ixr^s,iw)-half*rdw(jxr^s)
1330
1331 if (loglimit(iw)) then
1332 w(ixcmin^d:jxcmax^d,iw)=10.0d0**w(ixcmin^d:jxcmax^d,iw)
1333 wlp(ixl^s,iw)=10.0d0**wlp(ixl^s,iw)
1334 wrp(ixr^s,iw)=10.0d0**wrp(ixr^s,iw)
1335 end if
1336 end do
1337 if(fix_small_values) then
1338 call phys_handle_small_values(.true.,wlp,x,ixi^l,ixl^l,'reconstruct left')
1339 call phys_handle_small_values(.true.,wrp,x,ixi^l,ixr^l,'reconstruct right')
1340 end if
1341 end select
1343
1344 ! Well-balanced inverse: add back HSE at interface positions
1345 call timer_open(tw)
1346 if (associated(phys_wb_inverse)) then
1347 call phys_wb_inverse(ixi^l, ixl^l, ixr^l, idims, wlp, wrp, w, &
1348 wb_phi, wb_phi_face, wb_t)
1349 end if
1350
1351 wlc(ixl^s,1:nwflux)=wlp(ixl^s,1:nwflux)
1352 wrc(ixr^s,1:nwflux)=wrp(ixr^s,1:nwflux)
1353 call phys_to_conserved(ixi^l,ixl^l,wlc,x)
1354 call phys_to_conserved(ixi^l,ixr^l,wrc,x)
1356 if(nwaux>0)then
1357 wlp(ixl^s,nwflux+1:nwflux+nwaux)=wlc(ixl^s,nwflux+1:nwflux+nwaux)
1358 wrp(ixr^s,nwflux+1:nwflux+nwaux)=wrc(ixr^s,nwflux+1:nwflux+nwaux)
1359 endif
1360
1361 end subroutine reconstruct_lr
1362
1363end module mod_finite_volume
subroutine get_riemann_flux_tvdmu()
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
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.
double precision ppm_rjv
Residual-jump velocity reconstruction (RJV). 0 = off (default), 1 = full strength.
integer, dimension(:), allocatable typepred1
The spatial discretization for the predictor step when using a two step PC method.
integer istep
Index of the sub-step in a multi-step time integrator.
integer, dimension(3, 3) kr
Kronecker delta tensor.
logical, dimension(:), allocatable loglimit
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer b0i
background magnetic field location indicator
logical local_timestep
each cell has its own timestep or not
integer ndir
Number of spatial dimensions (components) for vector variables.
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
logical limit_on_wold
VAC-type MUSCL-Hancock: limit the corrector slopes on w^n (typelimited='previous'),...
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, parameter predictor_corrector
logical fix_small_values
fix small values with average or replace methods
integer t_stepper
time stepper type
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer t_integrator
time integrator method
integer, parameter fs_hancock
Module with slope/flux limiters.
Definition mod_limiter.t:2
integer, parameter limiter_weno5cu6
Definition mod_limiter.t:35
integer, parameter limiter_mpweno7
Definition mod_limiter.t:38
integer, parameter limiter_teno5ad
Definition mod_limiter.t:36
integer, parameter limiter_weno3
Definition mod_limiter.t:27
integer, parameter limiter_ppm
Definition mod_limiter.t:25
integer, parameter limiter_cada3
Definition mod_limiter.t:22
subroutine dwlimiter2(dwc, ixil, ixcl, idims, typelim, ldw, rdw)
Limit the centered dwC differences within ixC for iw in direction idim. The limiter is chosen accordi...
integer, parameter limiter_wenozp5
Definition mod_limiter.t:33
integer, parameter limiter_weno5
Definition mod_limiter.t:29
integer, parameter limiter_wenoz5
Definition mod_limiter.t:31
integer, parameter limiter_wenoz5nm
Definition mod_limiter.t:32
integer, parameter limiter_weno7
Definition mod_limiter.t:37
integer, parameter limiter_wenozp5nm
Definition mod_limiter.t:34
integer, parameter limiter_mp5
Definition mod_limiter.t:26
integer, parameter limiter_venk
Definition mod_limiter.t:23
integer, parameter limiter_weno5nm
Definition mod_limiter.t:30
integer, parameter limiter_wenoyc3
Definition mod_limiter.t:28
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_convert), pointer phys_to_primitive
Definition mod_physics.t:54
procedure(sub_wb_transform), pointer phys_wb_transform
Definition mod_physics.t:59
procedure(sub_small_values), pointer phys_handle_small_values
Definition mod_physics.t:86
procedure(sub_get_flux), pointer phys_get_flux
Definition mod_physics.t:67
logical phys_hd_mom_conserve_fix
exclude Maxwell stress flux from momentum flux (use hydrodynamic momentum flux) for conservation fix ...
Definition mod_physics.t:46
procedure(sub_wb_inverse), pointer phys_wb_inverse
Definition mod_physics.t:60
procedure(sub_add_source_geom), pointer phys_add_source_geom
Definition mod_physics.t:74
procedure(sub_convert), pointer phys_to_conserved
Definition mod_physics.t:53
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:138
double precision time_wb_inverse
Definition mod_timing.t:17
double precision time_wb_recon
Definition mod_timing.t:18
subroutine timer_open(t0)
Open a timing window, whose length leaves out the EoS and ghost-cell time spent inside it,...
Definition mod_timing.t:66
double precision time_wb_transform
Definition mod_timing.t:17
double precision function timer_close(t0)
Wall time since timer_open, less the EoS and ghost-cell time spent in between.
Definition mod_timing.t:73
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 nwflux
Number of flux variables.