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