"""
This is a 2nd-order PLM method for a method-of-lines integration
(i.e., no characteristic tracing).
We wish to solve
.. math::
U_t + F^x_x + F^y_y = H
we want U_{i+1/2} -- the interface values that are input to
the Riemann problem through the faces for each zone.
Taylor expanding *in space only* yields::
dU
U = U + 0.5 dx --
i+1/2,j,L i,j dx
"""
import pyro.compressible as comp
import pyro.compressible.unsplit_fluxes as flx
from pyro.compressible import riemann
from pyro.mesh import reconstruction
[docs]
def fluxes(my_data, rp, ivars, solid, tc):
"""
unsplitFluxes returns the fluxes through the x and y interfaces by
doing an unsplit reconstruction of the interface values and then
solving the Riemann problem through all the interfaces at once
currently we assume a gamma-law EOS
Parameters
----------
my_data : CellCenterData2d object
The data object containing the grid and advective scalar that
we are advecting.
rp : RuntimeParameters object
The runtime parameters for the simulation
vars : Variables object
The Variables object that tells us which indices refer to which
variables
tc : TimerCollection object
The timers we are using to profile
Returns
-------
out : ndarray, ndarray
The fluxes on the x- and y-interfaces
"""
tm_flux = tc.timer("unsplitFluxes")
tm_flux.begin()
myg = my_data.grid
gamma = rp.get_param("eos.gamma")
# =========================================================================
# compute the primitive variables
# =========================================================================
# Q = (rho, u, v, p)
q = comp.cons_to_prim(my_data.data, gamma, ivars, myg)
# =========================================================================
# compute the flattening coefficients
# =========================================================================
# there is a single flattening coefficient (xi) for all directions
use_flattening = rp.get_param("compressible.use_flattening")
if use_flattening:
xi_x = reconstruction.flatten(myg, q, 1, ivars, rp)
xi_y = reconstruction.flatten(myg, q, 2, ivars, rp)
xi = reconstruction.flatten_multid(myg, q, xi_x, xi_y, ivars)
else:
xi = 1.0
# monotonized central differences in x-direction
tm_limit = tc.timer("limiting")
tm_limit.begin()
limiter = rp.get_param("compressible.limiter")
ldx = myg.scratch_array(nvar=ivars.nvar)
ldy = myg.scratch_array(nvar=ivars.nvar)
for n in range(ivars.nvar):
ldx[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 1, limiter)
ldy[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 2, limiter)
tm_limit.end()
# if we are doing a well-balanced scheme, then redo the pressure
# note: we only have gravity in the y direction, so we will only
# modify the y pressure slope
well_balanced = rp.get_param("compressible.well_balanced")
grav = rp.get_param("compressible.grav")
if well_balanced:
ldy[:, :, ivars.ip] = reconstruction.well_balance(
q, myg, limiter, ivars, grav)
# =========================================================================
# x-direction
# =========================================================================
# left and right primitive variable states
tm_states = tc.timer("interfaceStates")
tm_states.begin()
V_l = myg.scratch_array(nvar=ivars.nvar)
V_r = myg.scratch_array(nvar=ivars.nvar)
for n in range(ivars.nvar):
V_l.ip(1, n=n, buf=2)[:, :] = q.v(n=n, buf=2) + 0.5 * ldx.v(n=n, buf=2)
V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldx.v(n=n, buf=2)
tm_states.end()
# transform interface states back into conserved variables
U_xl = comp.prim_to_cons(V_l, gamma, ivars, myg)
U_xr = comp.prim_to_cons(V_r, gamma, ivars, myg)
# =========================================================================
# y-direction
# =========================================================================
# left and right primitive variable states
tm_states.begin()
for n in range(ivars.nvar):
if well_balanced and n == ivars.ip:
# we want to do p0 + p1 on the interfaces. We found the
# limited slope for p1 (it's average is 0). So now we
# need p0 on the interface too
V_l.jp(1, n=n, buf=2)[:, :] = q.v(n=ivars.ip, buf=2) + \
0.5 * myg.dy * q.v(n=ivars.irho, buf=2) * \
grav + 0.5 * ldy.v(n=ivars.ip, buf=2)
V_r.v(n=n, buf=2)[:, :] = q.v(n=ivars.ip, buf=2) - \
0.5 * myg.dy * q.v(n=ivars.irho, buf=2) * \
grav - 0.5 * ldy.v(n=ivars.ip, buf=2)
else:
V_l.jp(1, n=n, buf=2)[:, :] = q.v(
n=n, buf=2) + 0.5 * ldy.v(n=n, buf=2)
V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldy.v(n=n, buf=2)
tm_states.end()
# transform interface states back into conserved variables
U_yl = comp.prim_to_cons(V_l, gamma, ivars, myg)
U_yr = comp.prim_to_cons(V_r, gamma, ivars, myg)
# =========================================================================
# construct the fluxes normal to the interfaces
# =========================================================================
F_x = riemann.riemann_flux(1, U_xl, U_xr,
my_data, rp, ivars,
solid.xl, solid.xr, tc)
F_y = riemann.riemann_flux(2, U_yl, U_yr,
my_data, rp, ivars,
solid.yl, solid.yr, tc)
# =========================================================================
# apply artificial viscosity
# =========================================================================
F_x, F_y = flx.apply_artificial_viscosity(F_x, F_y, q,
my_data, rp,
ivars)
tm_flux.end()
return F_x, F_y