SCHEMES: Fix adiabatic HLLD solver for weak Bx.

If the parallel component of magnetic field is too small, the
intermediate states might produce numerical instabilities, since they
are obtained by the division by a small factor.

In order to remove this situation, we apply full HLLD solver for strong
enough Alfvén wave. If it is weak, the HLLC solver is applied.

Signed-off-by: Grzegorz Kowal <grzegorz@amuncode.org>
This commit is contained in:
Grzegorz Kowal 2017-04-10 08:03:50 -03:00
parent 8dc157620c
commit da2f2a1bf0

View File

@ -3668,35 +3668,35 @@ module schemes
dn = wr(idn) - wl(idn) dn = wr(idn) - wl(idn)
sm = (wr(imx) - wl(imx)) / dn sm = (wr(imx) - wl(imx)) / dn
! speed differences
!
slmm = sl - sm
srmm = sr - sm
! left and right state densities
!
dnl = wl(idn) / slmm
dnr = wr(idn) / srmm
! square of Bₓ, i.e. Bₓ² ! square of Bₓ, i.e. Bₓ²
! !
bx = ql(ibx,i) bx = ql(ibx,i)
b2 = ql(ibx,i) * qr(ibx,i) b2 = ql(ibx,i) * qr(ibx,i)
! if there is an Alvén wave, apply the full HLLD solver, otherwise revert to
! the HLLC solver
!
if (b2 > 0.0d+00) then ! Bₓ² > 0
! the total pressure, constant across the contact discontinuity and Alfvén waves ! the total pressure, constant across the contact discontinuity and Alfvén waves
! !
pt = (wl(idn) * wr(imx) - wr(idn) * wl(imx)) / dn + b2 pt = (wl(idn) * wr(imx) - wr(idn) * wl(imx)) / dn + b2
! speed differences ! if Alfvén wave is strong enough, apply the full HLLD solver, otherwise
! revert to the HLLC one
! !
slmm = sl - sm if (b2 > 1.0d-08 * max(dnl * sl**2, dnr * sr**2)) then ! Bₓ² > ε
srmm = sr - sm
! left and right state densities
!
dnl = wl(idn) / slmm
dnr = wr(idn) / srmm
! left and right Alfvén speeds ! left and right Alfvén speeds
! !
cal = - sqrt(b2 / dnl) cal = sqrt(b2 / dnl)
car = sqrt(b2 / dnr) car = sqrt(b2 / dnr)
sml = sm + cal sml = sm - cal
smr = sm + car smr = sm + car
! calculate division factors (also used to determine degeneracies) ! calculate division factors (also used to determine degeneracies)
@ -3814,10 +3814,10 @@ module schemes
! prepare constant primitive variables of the intermediate states ! prepare constant primitive variables of the intermediate states
! !
dv = car * dnr - cal * dnl dv = car * dnr + cal * dnl
vy = (wcr(imy) - wcl(imy)) / dv vy = (wcr(imy) - wcl(imy)) / dv
vz = (wcr(imz) - wcl(imz)) / dv vz = (wcr(imz) - wcl(imz)) / dv
dv = car - cal dv = car + cal
by = (wcr(iby) - wcl(iby)) / dv by = (wcr(iby) - wcl(iby)) / dv
bz = (wcr(ibz) - wcl(ibz)) / dv bz = (wcr(ibz) - wcl(ibz)) / dv
vb = sm * bx + vy * by + vz * bz vb = sm * bx + vy * by + vz * bz
@ -3837,7 +3837,7 @@ module schemes
ui(iby) = by ui(iby) = by
ui(ibz) = bz ui(ibz) = bz
ui(ibp) = ul(ibp,i) ui(ibp) = ul(ibp,i)
ui(ien) = (wcl(ien) + sm * pt - bx * vb) / cal ui(ien) = (wcl(ien) + sm * pt - bx * vb) / (sml - sm)
! the inmost left intermediate flux ! the inmost left intermediate flux
! !
@ -3855,7 +3855,7 @@ module schemes
ui(iby) = by ui(iby) = by
ui(ibz) = bz ui(ibz) = bz
ui(ibp) = ur(ibp,i) ui(ibp) = ur(ibp,i)
ui(ien) = (wcr(ien) + sm * pt - bx * vb) / car ui(ien) = (wcr(ien) + sm * pt - bx * vb) / (smr - sm)
! the inmost right intermediate flux ! the inmost right intermediate flux
! !
@ -3914,7 +3914,7 @@ module schemes
! primitive variables for the inner left intermediate state ! primitive variables for the inner left intermediate state
! !
dv = srmm * dnr - cal * dnl dv = srmm * dnr + cal * dnl
vy = (wr(imy) - wcl(imy)) / dv vy = (wr(imy) - wcl(imy)) / dv
vz = (wr(imz) - wcl(imz)) / dv vz = (wr(imz) - wcl(imz)) / dv
dv = sr - sml dv = sr - sml
@ -3932,7 +3932,7 @@ module schemes
ui(iby) = by ui(iby) = by
ui(ibz) = bz ui(ibz) = bz
ui(ibp) = ul(ibp,i) ui(ibp) = ul(ibp,i)
ui(ien) = (wcl(ien) + sm * pt - bx * vb) / cal ui(ien) = (wcl(ien) + sm * pt - bx * vb) / (sml - sm)
! choose the correct state depending on the sign of contact discontinuity ! choose the correct state depending on the sign of contact discontinuity
! advection speed ! advection speed
@ -4013,7 +4013,7 @@ module schemes
ui(iby) = by ui(iby) = by
ui(ibz) = bz ui(ibz) = bz
ui(ibp) = ur(ibp,i) ui(ibp) = ur(ibp,i)
ui(ien) = (wcr(ien) + sm * pt - bx * vb) / car ui(ien) = (wcr(ien) + sm * pt - bx * vb) / (smr - sm)
! choose the correct state depending on the sign of contact discontinuity ! choose the correct state depending on the sign of contact discontinuity
! advection speed ! advection speed
@ -4048,24 +4048,77 @@ module schemes
end if ! one degeneracy end if ! one degeneracy
else ! Bₓ² = 0 else if (b2 > 0.0d+00) then ! Bₓ² > 0
! the total pressure, constant across the contact discontinuity ! constant intermediate state tangential components of velocity and
! magnetic field
! !
pt = (wl(idn) * wr(imx) - wr(idn) * wl(imx)) / dn vy = (wr(imy) - wl(imy)) / dn
vz = (wr(imz) - wl(imz)) / dn
by = (wr(iby) - wl(iby)) / srml
bz = (wr(ibz) - wl(ibz)) / srml
! scalar product of velocity and magnetic field for the intermediate states
!
vb = sm * bx + vy * by + vz * bz
! separate intermediate states depending on the sign of the advection speed ! separate intermediate states depending on the sign of the advection speed
! !
if (sm > 0.0d+00) then ! sm > 0 if (sm > 0.0d+00) then ! sm > 0
! the left speed difference ! conservative variables for the left intermediate state
! !
slmm = sl - sm ui(idn) = dnl
ui(imx) = dnl * sm
ui(imy) = dnl * vy
ui(imz) = dnl * vz
ui(ibx) = bx
ui(iby) = by
ui(ibz) = bz
ui(ibp) = ul(ibp,i)
ui(ien) = (wl(ien) + sm * pt - bx * vb) / slmm
! the left intermediate flux
!
f(:,i) = sl * ui(:) - wl(:)
else if (sm < 0.0d+00) then ! sm < 0
! conservative variables for the right intermediate state
!
ui(idn) = dnr
ui(imx) = dnr * sm
ui(imy) = dnr * vy
ui(imz) = dnr * vz
ui(ibx) = bx
ui(iby) = by
ui(ibz) = bz
ui(ibp) = ur(ibp,i)
ui(ien) = (wr(ien) + sm * pt - bx * vb) / srmm
! the right intermediate flux
!
f(:,i) = sr * ui(:) - wr(:)
else ! sm = 0
! when Sₘ = 0 all variables are continuous, therefore the flux reduces
! to the HLL one
!
f(:,i) = (sl * wr(:) - sr * wl(:)) / srml
end if ! sm = 0
else ! Bₓ² = 0
! separate intermediate states depending on the sign of the advection speed
!
if (sm > 0.0d+00) then ! sm > 0
! conservative variables for the left intermediate state ! conservative variables for the left intermediate state
! !
ui(idn) = wl(idn) / slmm ui(idn) = dnl
ui(imx) = ui(idn) * sm ui(imx) = dnl * sm
ui(imy) = wl(imy) / slmm ui(imy) = wl(imy) / slmm
ui(imz) = wl(imz) / slmm ui(imz) = wl(imz) / slmm
ui(ibx) = 0.0d+00 ui(ibx) = 0.0d+00
@ -4080,14 +4133,10 @@ module schemes
else if (sm < 0.0d+00) then ! sm < 0 else if (sm < 0.0d+00) then ! sm < 0
! the right speed difference
!
srmm = sr - sm
! conservative variables for the right intermediate state ! conservative variables for the right intermediate state
! !
ui(idn) = wr(idn) / srmm ui(idn) = dnr
ui(imx) = ui(idn) * sm ui(imx) = dnr * sm
ui(imy) = wr(imy) / srmm ui(imy) = wr(imy) / srmm
ui(imz) = wr(imz) / srmm ui(imz) = wr(imz) / srmm
ui(ibx) = 0.0d+00 ui(ibx) = 0.0d+00
@ -4102,8 +4151,8 @@ module schemes
else ! sm = 0 else ! sm = 0
! intermediate flux is constant across the contact discontinuity, so we end up ! when Sₘ = 0 all variables are continuous, therefore the flux reduces
! having only one intermediate state, which is equivalent to the HLL solver ! to the HLL one
! !
f(:,i) = (sl * wr(:) - sr * wl(:)) / srml f(:,i) = (sl * wr(:) - sr * wl(:)) / srml