コード例 #1
0
ファイル: simulation.py プロジェクト: liuxin21/pyro2
    def dovis(self):
        """
        Do runtime visualization.
        """

        plt.clf()

        plt.rc("font", size=10)

        # we do this even though ivars is in self, so this works when
        # we are plotting from a file
        ivars = compressible.Variables(self.cc_data)

        # access gamma from the cc_data object so we can use dovis
        # outside of a running simulation.
        gamma = self.cc_data.get_aux("gamma")

        q = compressible.cons_to_prim(self.cc_data.data, gamma, ivars, self.cc_data.grid)

        rho = q[:,:,ivars.irho]
        u = q[:,:,ivars.iu]
        v = q[:,:,ivars.iv]
        p = q[:,:,ivars.ip]
        e = eos.rhoe(gamma, p)/rho

        X = q[:,:,ivars.ix]

        magvel = np.sqrt(u**2 + v**2)

        myg = self.cc_data.grid

        fields = [rho, magvel, p, e, X]
        field_names = [r"$\rho$", r"U", "p", "e", r"$X_\mathrm{fuel}$"]

        f, axes, cbar_title = plot_tools.setup_axes(myg, len(fields))

        for n, ax in enumerate(axes):
            v = fields[n]

            img = ax.imshow(np.transpose(v.v()),
                            interpolation="nearest", origin="lower",
                            extent=[myg.xmin, myg.xmax, myg.ymin, myg.ymax],
                            cmap=self.cm)

            ax.set_xlabel("x")
            ax.set_ylabel("y")

            # needed for PDF rendering
            cb = axes.cbar_axes[n].colorbar(img)
            cb.solids.set_rasterized(True)
            cb.solids.set_edgecolor("face")

            if cbar_title:
                cb.ax.set_title(field_names[n])
            else:
                ax.set_title(field_names[n])

        plt.figtext(0.05, 0.0125, "t = {:10.5g}".format(self.cc_data.t))

        plt.pause(0.001)
        plt.draw()
コード例 #2
0
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(ivars.nvar)
    V_r = myg.scratch_array(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
    # =========================================================================
    tm_riem = tc.timer("Riemann")
    tm_riem.begin()

    riemann = rp.get_param("compressible.riemann")

    if riemann == "HLLC":
        riemannFunc = interface.riemann_hllc
    elif riemann == "CGF":
        riemannFunc = interface.riemann_cgf
    else:
        msg.fail("ERROR: Riemann solver undefined")

    _fx = riemannFunc(1, myg.ng, ivars.idens, ivars.ixmom, ivars.iymom,
                      ivars.iener, ivars.irhox, ivars.naux, solid.xl, solid.xr,
                      gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.ng, ivars.idens, ivars.ixmom, ivars.iymom,
                      ivars.iener, ivars.irhox, ivars.naux, solid.yl, solid.yr,
                      gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # apply artificial viscosity
    # =========================================================================
    cvisc = rp.get_param("compressible.cvisc")

    _ax, _ay = interface.artificial_viscosity(myg.ng, myg.dx, myg.dy, cvisc,
                                              q.v(n=ivars.iu, buf=myg.ng),
                                              q.v(n=ivars.iv, buf=myg.ng))

    avisco_x = ai.ArrayIndexer(d=_ax, grid=myg)
    avisco_y = ai.ArrayIndexer(d=_ay, grid=myg)

    b = (2, 1)

    for n in range(ivars.nvar):
        # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j))
        var = my_data.get_var_by_index(n)

        F_x.v(buf=b, n=n)[:, :] += \
            avisco_x.v(buf=b) * (var.ip(-1, buf=b) - var.v(buf=b))

        # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j))
        F_y.v(buf=b, n=n)[:, :] += \
            avisco_y.v(buf=b) * (var.jp(-1, buf=b) - var.v(buf=b))

    tm_flux.end()

    return F_x, F_y
コード例 #3
0
ファイル: fluxes.py プロジェクト: zingale/pyro2
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(ivars.nvar)
    V_r = myg.scratch_array(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
    # =========================================================================
    tm_riem = tc.timer("Riemann")
    tm_riem.begin()

    riemann = rp.get_param("compressible.riemann")

    if riemann == "HLLC":
        riemannFunc = interface.riemann_hllc
    elif riemann == "CGF":
        riemannFunc = interface.riemann_cgf
    else:
        msg.fail("ERROR: Riemann solver undefined")

    _fx = riemannFunc(1, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.xl, solid.xr,
                      gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.yl, solid.yr,
                      gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # apply artificial viscosity
    # =========================================================================
    cvisc = rp.get_param("compressible.cvisc")

    _ax, _ay = interface.artificial_viscosity(myg.ng, myg.dx, myg.dy,
        cvisc, q.v(n=ivars.iu, buf=myg.ng), q.v(n=ivars.iv, buf=myg.ng))

    avisco_x = ai.ArrayIndexer(d=_ax, grid=myg)
    avisco_y = ai.ArrayIndexer(d=_ay, grid=myg)

    b = (2, 1)

    for n in range(ivars.nvar):
        # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j))
        var = my_data.get_var_by_index(n)

        F_x.v(buf=b, n=n)[:, :] += \
            avisco_x.v(buf=b) * (var.ip(-1, buf=b) - var.v(buf=b))

        # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j))
        F_y.v(buf=b, n=n)[:, :] += \
            avisco_y.v(buf=b) * (var.jp(-1, buf=b) - var.v(buf=b))

    tm_flux.end()

    return F_x, F_y
コード例 #4
0
ファイル: unsplit_fluxes.py プロジェクト: zingale/pyro2
def unsplit_fluxes(my_data, my_aux, rp, ivars, solid, tc, dt):
    """
    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

    The runtime parameter grav is assumed to be the gravitational
    acceleration in the y-direction

    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
    dt : float
        The timestep we are advancing through.

    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, {X})

    dens = my_data.get_var("density")
    ymom = my_data.get_var("y-momentum")

    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
    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()

    # =========================================================================
    # x-direction
    # =========================================================================

    # left and right primitive variable states
    tm_states = tc.timer("interfaceStates")
    tm_states.begin()

    V_l, V_r = ifc.states(1, myg.ng, myg.dx, dt,
                          ivars.irho, ivars.iu, ivars.iv, ivars.ip, ivars.ix,
                          ivars.naux,
                          gamma,
                          q, ldx)

    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()

    _V_l, _V_r = ifc.states(2, myg.ng, myg.dy, dt,
                            ivars.irho, ivars.iu, ivars.iv, ivars.ip, ivars.ix,
                            ivars.naux,
                            gamma,
                            q, ldy)
    V_l = ai.ArrayIndexer(d=_V_l, grid=myg)
    V_r = ai.ArrayIndexer(d=_V_r, grid=myg)

    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)

    # =========================================================================
    # apply source terms
    # =========================================================================
    grav = rp.get_param("compressible.grav")

    ymom_src = my_aux.get_var("ymom_src")
    ymom_src.v()[:, :] = dens.v()*grav
    my_aux.fill_BC("ymom_src")

    E_src = my_aux.get_var("E_src")
    E_src.v()[:, :] = ymom.v()*grav
    my_aux.fill_BC("E_src")

    # ymom_xl[i,j] += 0.5*dt*dens[i-1,j]*grav
    U_xl.v(buf=1, n=ivars.iymom)[:, :] += 0.5*dt*ymom_src.ip(-1, buf=1)
    U_xl.v(buf=1, n=ivars.iener)[:, :] += 0.5*dt*E_src.ip(-1, buf=1)

    # ymom_xr[i,j] += 0.5*dt*dens[i,j]*grav
    U_xr.v(buf=1, n=ivars.iymom)[:, :] += 0.5*dt*ymom_src.v(buf=1)
    U_xr.v(buf=1, n=ivars.iener)[:, :] += 0.5*dt*E_src.v(buf=1)

    # ymom_yl[i,j] += 0.5*dt*dens[i,j-1]*grav
    U_yl.v(buf=1, n=ivars.iymom)[:, :] += 0.5*dt*ymom_src.jp(-1, buf=1)
    U_yl.v(buf=1, n=ivars.iener)[:, :] += 0.5*dt*E_src.jp(-1, buf=1)

    # ymom_yr[i,j] += 0.5*dt*dens[i,j]*grav
    U_yr.v(buf=1, n=ivars.iymom)[:, :] += 0.5*dt*ymom_src.v(buf=1)
    U_yr.v(buf=1, n=ivars.iener)[:, :] += 0.5*dt*E_src.v(buf=1)

    # =========================================================================
    # compute transverse fluxes
    # =========================================================================
    tm_riem = tc.timer("riemann")
    tm_riem.begin()

    riemann = rp.get_param("compressible.riemann")

    if riemann == "HLLC":
        riemannFunc = ifc.riemann_hllc
    elif riemann == "CGF":
        riemannFunc = ifc.riemann_cgf
    else:
        msg.fail("ERROR: Riemann solver undefined")

    _fx = riemannFunc(1, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.xl, solid.xr,
                      gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.yl, solid.yr,
                      gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # construct the interface values of U now
    # =========================================================================

    """
    finally, we can construct the state perpendicular to the interface
    by adding the central difference part to the trasverse flux
    difference.

    The states that we represent by indices i,j are shown below
    (1,2,3,4):


      j+3/2--+----------+----------+----------+
             |          |          |          |
             |          |          |          |
        j+1 -+          |          |          |
             |          |          |          |
             |          |          |          |    1: U_xl[i,j,:] = U
      j+1/2--+----------XXXXXXXXXXXX----------+                      i-1/2,j,L
             |          X          X          |
             |          X          X          |
          j -+        1 X 2        X          |    2: U_xr[i,j,:] = U
             |          X          X          |                      i-1/2,j,R
             |          X    4     X          |
      j-1/2--+----------XXXXXXXXXXXX----------+
             |          |    3     |          |    3: U_yl[i,j,:] = U
             |          |          |          |                      i,j-1/2,L
        j-1 -+          |          |          |
             |          |          |          |
             |          |          |          |    4: U_yr[i,j,:] = U
      j-3/2--+----------+----------+----------+                      i,j-1/2,R
             |    |     |    |     |    |     |
                 i-1         i         i+1
           i-3/2      i-1/2      i+1/2      i+3/2


    remember that the fluxes are stored on the left edge, so

    F_x[i,j,:] = F_x
                    i-1/2, j

    F_y[i,j,:] = F_y
                    i, j-1/2

    """

    tm_transverse = tc.timer("transverse flux addition")
    tm_transverse.begin()

    dtdx = dt/myg.dx
    dtdy = dt/myg.dy

    b = (2, 1)

    for n in range(ivars.nvar):

        # U_xl[i,j,:] = U_xl[i,j,:] - 0.5*dt/dy * (F_y[i-1,j+1,:] - F_y[i-1,j,:])
        U_xl.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdy*(F_y.ip_jp(-1, 1, buf=b, n=n) - F_y.ip(-1, buf=b, n=n))

        # U_xr[i,j,:] = U_xr[i,j,:] - 0.5*dt/dy * (F_y[i,j+1,:] - F_y[i,j,:])
        U_xr.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdy*(F_y.jp(1, buf=b, n=n) - F_y.v(buf=b, n=n))

        # U_yl[i,j,:] = U_yl[i,j,:] - 0.5*dt/dx * (F_x[i+1,j-1,:] - F_x[i,j-1,:])
        U_yl.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdx*(F_x.ip_jp(1, -1, buf=b, n=n) - F_x.jp(-1, buf=b, n=n))

        # U_yr[i,j,:] = U_yr[i,j,:] - 0.5*dt/dx * (F_x[i+1,j,:] - F_x[i,j,:])
        U_yr.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdx*(F_x.ip(1, buf=b, n=n) - F_x.v(buf=b, n=n))

    tm_transverse.end()

    # =========================================================================
    # construct the fluxes normal to the interfaces
    # =========================================================================

    # up until now, F_x and F_y stored the transverse fluxes, now we
    # overwrite with the fluxes normal to the interfaces

    tm_riem.begin()

    _fx = riemannFunc(1, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.xl, solid.xr,
                      gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.ng,
                      ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux,
                      solid.yl, solid.yr,
                      gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # apply artificial viscosity
    # =========================================================================
    cvisc = rp.get_param("compressible.cvisc")

    _ax, _ay = ifc.artificial_viscosity(myg.ng, myg.dx, myg.dy,
        cvisc, q.v(n=ivars.iu, buf=myg.ng), q.v(n=ivars.iv, buf=myg.ng))

    avisco_x = ai.ArrayIndexer(d=_ax, grid=myg)
    avisco_y = ai.ArrayIndexer(d=_ay, grid=myg)

    b = (2, 1)

    for n in range(ivars.nvar):
        # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j))
        var = my_data.get_var_by_index(n)

        F_x.v(buf=b, n=n)[:, :] += \
            avisco_x.v(buf=b)*(var.ip(-1, buf=b) - var.v(buf=b))

        # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j))
        F_y.v(buf=b, n=n)[:, :] += \
            avisco_y.v(buf=b)*(var.jp(-1, buf=b) - var.v(buf=b))

    tm_flux.end()

    return F_x, F_y
コード例 #5
0
ファイル: unsplit_fluxes.py プロジェクト: mstiegl/pyro2
def unsplit_fluxes(my_data, my_aux, rp, ivars, solid, tc, dt):
    """
    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

    The runtime parameter grav is assumed to be the gravitational
    acceleration in the y-direction

    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
    dt : float
        The timestep we are advancing through.

    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, {X})

    dens = my_data.get_var("density")
    ymom = my_data.get_var("y-momentum")

    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
    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()

    # =========================================================================
    # x-direction
    # =========================================================================

    # left and right primitive variable states
    tm_states = tc.timer("interfaceStates")
    tm_states.begin()

    V_l, V_r = ifc.states(1, myg.qx, myg.qy, myg.ng, myg.dx, dt, ivars.irho,
                          ivars.iu, ivars.iv, ivars.ip, ivars.ix, ivars.nvar,
                          ivars.naux, gamma, q, ldx)

    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()

    _V_l, _V_r = ifc.states(2, myg.qx, myg.qy, myg.ng, myg.dy, dt, ivars.irho,
                            ivars.iu, ivars.iv, ivars.ip, ivars.ix, ivars.nvar,
                            ivars.naux, gamma, q, ldy)
    V_l = ai.ArrayIndexer(d=_V_l, grid=myg)
    V_r = ai.ArrayIndexer(d=_V_r, grid=myg)

    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)

    # =========================================================================
    # apply source terms
    # =========================================================================
    grav = rp.get_param("compressible.grav")

    ymom_src = my_aux.get_var("ymom_src")
    ymom_src.v()[:, :] = dens.v() * grav
    my_aux.fill_BC("ymom_src")

    E_src = my_aux.get_var("E_src")
    E_src.v()[:, :] = ymom.v() * grav
    my_aux.fill_BC("E_src")

    # ymom_xl[i,j] += 0.5*dt*dens[i-1,j]*grav
    U_xl.v(buf=1, n=ivars.iymom)[:, :] += 0.5 * dt * ymom_src.ip(-1, buf=1)
    U_xl.v(buf=1, n=ivars.iener)[:, :] += 0.5 * dt * E_src.ip(-1, buf=1)

    # ymom_xr[i,j] += 0.5*dt*dens[i,j]*grav
    U_xr.v(buf=1, n=ivars.iymom)[:, :] += 0.5 * dt * ymom_src.v(buf=1)
    U_xr.v(buf=1, n=ivars.iener)[:, :] += 0.5 * dt * E_src.v(buf=1)

    # ymom_yl[i,j] += 0.5*dt*dens[i,j-1]*grav
    U_yl.v(buf=1, n=ivars.iymom)[:, :] += 0.5 * dt * ymom_src.jp(-1, buf=1)
    U_yl.v(buf=1, n=ivars.iener)[:, :] += 0.5 * dt * E_src.jp(-1, buf=1)

    # ymom_yr[i,j] += 0.5*dt*dens[i,j]*grav
    U_yr.v(buf=1, n=ivars.iymom)[:, :] += 0.5 * dt * ymom_src.v(buf=1)
    U_yr.v(buf=1, n=ivars.iener)[:, :] += 0.5 * dt * E_src.v(buf=1)

    # =========================================================================
    # compute transverse fluxes
    # =========================================================================
    tm_riem = tc.timer("riemann")
    tm_riem.begin()

    riemann = rp.get_param("compressible.riemann")

    if riemann == "HLLC":
        riemannFunc = ifc.riemann_hllc
    elif riemann == "CGF":
        riemannFunc = ifc.riemann_cgf
    else:
        msg.fail("ERROR: Riemann solver undefined")

    _fx = riemannFunc(1, myg.qx, myg.qy, myg.ng, ivars.nvar, ivars.idens,
                      ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox,
                      ivars.naux, solid.xl, solid.xr, gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.qx, myg.qy, myg.ng, ivars.nvar, ivars.idens,
                      ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox,
                      ivars.naux, solid.yl, solid.yr, gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # construct the interface values of U now
    # =========================================================================
    """
    finally, we can construct the state perpendicular to the interface
    by adding the central difference part to the trasverse flux
    difference.

    The states that we represent by indices i,j are shown below
    (1,2,3,4):


      j+3/2--+----------+----------+----------+
             |          |          |          |
             |          |          |          |
        j+1 -+          |          |          |
             |          |          |          |
             |          |          |          |    1: U_xl[i,j,:] = U
      j+1/2--+----------XXXXXXXXXXXX----------+                      i-1/2,j,L
             |          X          X          |
             |          X          X          |
          j -+        1 X 2        X          |    2: U_xr[i,j,:] = U
             |          X          X          |                      i-1/2,j,R
             |          X    4     X          |
      j-1/2--+----------XXXXXXXXXXXX----------+
             |          |    3     |          |    3: U_yl[i,j,:] = U
             |          |          |          |                      i,j-1/2,L
        j-1 -+          |          |          |
             |          |          |          |
             |          |          |          |    4: U_yr[i,j,:] = U
      j-3/2--+----------+----------+----------+                      i,j-1/2,R
             |    |     |    |     |    |     |
                 i-1         i         i+1
           i-3/2      i-1/2      i+1/2      i+3/2


    remember that the fluxes are stored on the left edge, so

    F_x[i,j,:] = F_x
                    i-1/2, j

    F_y[i,j,:] = F_y
                    i, j-1/2

    """

    tm_transverse = tc.timer("transverse flux addition")
    tm_transverse.begin()

    dtdx = dt / myg.dx
    dtdy = dt / myg.dy

    b = (2, 1)

    for n in range(ivars.nvar):

        # U_xl[i,j,:] = U_xl[i,j,:] - 0.5*dt/dy * (F_y[i-1,j+1,:] - F_y[i-1,j,:])
        U_xl.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdy*(F_y.ip_jp(-1, 1, buf=b, n=n) - F_y.ip(-1, buf=b, n=n))

        # U_xr[i,j,:] = U_xr[i,j,:] - 0.5*dt/dy * (F_y[i,j+1,:] - F_y[i,j,:])
        U_xr.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdy*(F_y.jp(1, buf=b, n=n) - F_y.v(buf=b, n=n))

        # U_yl[i,j,:] = U_yl[i,j,:] - 0.5*dt/dx * (F_x[i+1,j-1,:] - F_x[i,j-1,:])
        U_yl.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdx*(F_x.ip_jp(1, -1, buf=b, n=n) - F_x.jp(-1, buf=b, n=n))

        # U_yr[i,j,:] = U_yr[i,j,:] - 0.5*dt/dx * (F_x[i+1,j,:] - F_x[i,j,:])
        U_yr.v(buf=b, n=n)[:, :] += \
            - 0.5*dtdx*(F_x.ip(1, buf=b, n=n) - F_x.v(buf=b, n=n))

    tm_transverse.end()

    # =========================================================================
    # construct the fluxes normal to the interfaces
    # =========================================================================

    # up until now, F_x and F_y stored the transverse fluxes, now we
    # overwrite with the fluxes normal to the interfaces

    tm_riem.begin()

    _fx = riemannFunc(1, myg.qx, myg.qy, myg.ng, ivars.nvar, ivars.idens,
                      ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox,
                      ivars.naux, solid.xl, solid.xr, gamma, U_xl, U_xr)

    _fy = riemannFunc(2, myg.qx, myg.qy, myg.ng, ivars.nvar, ivars.idens,
                      ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox,
                      ivars.naux, solid.yl, solid.yr, gamma, U_yl, U_yr)

    F_x = ai.ArrayIndexer(d=_fx, grid=myg)
    F_y = ai.ArrayIndexer(d=_fy, grid=myg)

    tm_riem.end()

    # =========================================================================
    # apply artificial viscosity
    # =========================================================================
    cvisc = rp.get_param("compressible.cvisc")

    _ax, _ay = ifc.artificial_viscosity(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy,
                                        cvisc, q.v(n=ivars.iu, buf=myg.ng),
                                        q.v(n=ivars.iv, buf=myg.ng))

    avisco_x = ai.ArrayIndexer(d=_ax, grid=myg)
    avisco_y = ai.ArrayIndexer(d=_ay, grid=myg)

    b = (2, 1)

    for n in range(ivars.nvar):
        # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j))
        var = my_data.get_var_by_index(n)

        F_x.v(buf=b, n=n)[:, :] += \
            avisco_x.v(buf=b)*(var.ip(-1, buf=b) - var.v(buf=b))

        # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j))
        F_y.v(buf=b, n=n)[:, :] += \
            avisco_y.v(buf=b)*(var.jp(-1, buf=b) - var.v(buf=b))

    tm_flux.end()

    return F_x, F_y
コード例 #6
0
def fluxes(myd, rp, ivars, solid, tc):

    myg = myd.grid

    gamma = rp.get_param("eos.gamma")

    # get the cell-average data
    U_avg = myd.data

    # convert U from cell-centers to cell averages
    U_cc = np.zeros_like(U_avg)

    U_cc[:, :, ivars.idens] = myd.to_centers("density")
    U_cc[:, :, ivars.ixmom] = myd.to_centers("x-momentum")
    U_cc[:, :, ivars.iymom] = myd.to_centers("y-momentum")
    U_cc[:, :, ivars.iener] = myd.to_centers("energy")

    # compute the primitive variables of both the cell-center and averages
    q_bar = comp.cons_to_prim(U_avg, gamma, ivars, myd.grid)
    q_cc = comp.cons_to_prim(U_cc, gamma, ivars, myd.grid)

    # compute the 4th-order approximation to the cell-average primitive state
    q_avg = myg.scratch_array(nvar=ivars.nq)
    for n in range(ivars.nq):
        q_avg.v(n=n, buf=3)[:, :] = q_cc.v(
            n=n, buf=3) + myg.dx**2 / 24.0 * q_bar.lap(n=n, buf=3)

    # flattening -- 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_bar, 1, ivars, rp)
        xi_y = reconstruction.flatten(myg, q_bar, 2, ivars, rp)

        xi = reconstruction.flatten_multid(myg, q_bar, xi_x, xi_y, ivars)
    else:
        xi = 1.0

    fluxes = []

    # for debugging
    nolimit = 0

    for idir in [1, 2]:

        # interpolate <W> to faces (with limiting)
        q_l = myg.scratch_array(nvar=ivars.nq)
        q_r = myg.scratch_array(nvar=ivars.nq)

        if nolimit:
            for n in range(ivars.nq):

                if idir == 1:
                    qtmp = 7./12.*(q_avg.ip(-1, n=n, buf=1) + q_avg.v(n=n, buf=1)) - \
                           1./12.*(q_avg.ip(-2, n=n, buf=1) + q_avg.ip(1, n=n, buf=1))
                else:
                    qtmp = 7./12.*(q_avg.jp(-1, n=n, buf=1) + q_avg.v(n=n, buf=1)) - \
                           1./12.*(q_avg.jp(-2, n=n, buf=1) + q_avg.jp(1, n=n, buf=1))

                q_l.v(n=n, buf=1)[:, :] = qtmp
                q_r.v(n=n, buf=1)[:, :] = qtmp

        else:
            for n in range(ivars.nq):
                q_l[:, :,
                    n], q_r[:, :,
                            n] = interface_f.states(q_avg[:, :, n], myg.qx,
                                                    myg.qy, myg.ng, idir)

            # apply flattening
            for n in range(ivars.nq):
                if idir == 1:
                    q_l.ip(
                        1, n=n,
                        buf=2)[:, :] = xi.v(buf=2) * q_l.ip(1, n=n, buf=2) + (
                            1.0 - xi.v(buf=2)) * q_avg.v(n=n, buf=2)
                    q_r.v(n=n, buf=2)[:, :] = xi.v(buf=2) * q_r.v(
                        n=n, buf=2) + (1.0 - xi.v(buf=2)) * q_avg.v(n=n, buf=2)
                else:
                    q_l.jp(
                        1, n=n,
                        buf=2)[:, :] = xi.v(buf=2) * q_l.jp(1, n=n, buf=2) + (
                            1.0 - xi.v(buf=2)) * q_avg.v(n=n, buf=2)
                    q_r.v(n=n, buf=2)[:, :] = xi.v(buf=2) * q_r.v(
                        n=n, buf=2) + (1.0 - xi.v(buf=2)) * q_avg.v(n=n, buf=2)

        _q = cf.riemann_prim(idir, myg.qx, myg.qy, myg.ng, ivars.nq,
                             ivars.irho, ivars.iu, ivars.iv, ivars.ip,
                             ivars.ix, ivars.naux, 0, 0, gamma, q_l, q_r)

        q_int_avg = ai.ArrayIndexer(_q, grid=myg)

        # calculate the face-centered W using the transverse Laplacian
        q_int_fc = myg.scratch_array(nvar=ivars.nq)

        if idir == 1:
            for n in range(ivars.nq):
                q_int_fc.v(n=n, buf=myg.ng - 1)[:, :] = q_int_avg.v(
                    n=n, buf=myg.ng -
                    1) - 1.0 / 24.0 * (q_int_avg.jp(1, n=n, buf=myg.ng - 1) -
                                       2 * q_int_avg.v(n=n, buf=myg.ng - 1) +
                                       q_int_avg.jp(-1, n=n, buf=myg.ng - 1))
        else:
            for n in range(ivars.nq):
                q_int_fc.v(n=n, buf=myg.ng - 1)[:, :] = q_int_avg.v(
                    n=n, buf=myg.ng -
                    1) - 1.0 / 24.0 * (q_int_avg.ip(1, n=n, buf=myg.ng - 1) -
                                       2 * q_int_avg.v(n=n, buf=myg.ng - 1) +
                                       q_int_avg.ip(-1, n=n, buf=myg.ng - 1))

        # compute the final fluxes
        F_fc = flux_cons(ivars, idir, gamma, q_int_fc)
        F_avg = flux_cons(ivars, idir, gamma, q_int_avg)

        if idir == 1:
            F_x = myg.scratch_array(nvar=ivars.nvar)
            for n in range(ivars.nvar):
                F_x.v(n=n, buf=1)[:, :] = F_fc.v(n=n, buf=1) + 1.0 / 24.0 * (
                    F_avg.jp(1, n=n, buf=1) - 2 * F_avg.v(n=n, buf=1) +
                    F_avg.jp(-1, n=n, buf=1))
        else:
            F_y = myg.scratch_array(nvar=ivars.nvar)
            for n in range(ivars.nvar):
                F_y.v(n=n, buf=1)[:, :] = F_fc.v(n=n, buf=1) + 1.0 / 24.0 * (
                    F_avg.ip(1, n=n, buf=1) - 2 * F_avg.v(n=n, buf=1) +
                    F_avg.ip(-1, n=n, buf=1))

    return F_x, F_y
コード例 #7
0
def fluxes(myd, rp, ivars, solid, tc):

    alpha = 0.3
    beta = 0.3

    myg = myd.grid

    gamma = rp.get_param("eos.gamma")

    # get the cell-average data
    U_avg = myd.data

    # convert U from cell-centers to cell averages
    U_cc = np.zeros_like(U_avg)

    U_cc[:, :, ivars.idens] = myd.to_centers("density")
    U_cc[:, :, ivars.ixmom] = myd.to_centers("x-momentum")
    U_cc[:, :, ivars.iymom] = myd.to_centers("y-momentum")
    U_cc[:, :, ivars.iener] = myd.to_centers("energy")

    # compute the primitive variables of both the cell-center and averages
    q_bar = comp.cons_to_prim(U_avg, gamma, ivars, myd.grid)
    q_cc = comp.cons_to_prim(U_cc, gamma, ivars, myd.grid)

    # compute the 4th-order approximation to the cell-average primitive state
    q_avg = myg.scratch_array(nvar=ivars.nq)
    for n in range(ivars.nq):
        q_avg.v(n=n, buf=3)[:, :] = q_cc.v(n=n, buf=3) + myg.dx**2/24.0 * q_bar.lap(n=n, buf=3)

    # flattening -- 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_bar, 1, ivars, rp)
        xi_y = reconstruction.flatten(myg, q_bar, 2, ivars, rp)

        xi = reconstruction.flatten_multid(myg, q_bar, xi_x, xi_y, ivars)
    else:
        xi = 1.0

    # for debugging
    nolimit = 0

    for idir in [1, 2]:

        # interpolate <W> to faces (with limiting)
        q_l = myg.scratch_array(nvar=ivars.nq)
        q_r = myg.scratch_array(nvar=ivars.nq)

        if nolimit:
            for n in range(ivars.nq):

                if idir == 1:
                    qtmp = 7./12.*(q_avg.ip(-1, n=n, buf=1) + q_avg.v(n=n, buf=1)) - \
                           1./12.*(q_avg.ip(-2, n=n, buf=1) + q_avg.ip(1, n=n, buf=1))
                else:
                    qtmp = 7./12.*(q_avg.jp(-1, n=n, buf=1) + q_avg.v(n=n, buf=1)) - \
                           1./12.*(q_avg.jp(-2, n=n, buf=1) + q_avg.jp(1, n=n, buf=1))

                q_l.v(n=n, buf=1)[:, :] = qtmp
                q_r.v(n=n, buf=1)[:, :] = qtmp

        else:
            for n in range(ivars.nq):
                q_l[:, :, n], q_r[:, :, n] = interface.states(q_avg[:, :, n], myg.ng, idir)

            # apply flattening
            for n in range(ivars.nq):
                if idir == 1:
                    q_l.ip(1, n=n, buf=2)[:, :] = xi.v(buf=2)*q_l.ip(1, n=n, buf=2) + \
                        (1.0 - xi.v(buf=2))*q_avg.v(n=n, buf=2)
                    q_r.v(n=n, buf=2)[:, :] = xi.v(buf=2)*q_r.v(n=n, buf=2) + \
                        (1.0 - xi.v(buf=2))*q_avg.v(n=n, buf=2)
                else:
                    q_l.jp(1, n=n, buf=2)[:, :] = xi.v(buf=2)*q_l.jp(1, n=n, buf=2) + \
                        (1.0 - xi.v(buf=2))*q_avg.v(n=n, buf=2)
                    q_r.v(n=n, buf=2)[:, :] = xi.v(buf=2)*q_r.v(n=n, buf=2) + \
                        (1.0 - xi.v(buf=2))*q_avg.v(n=n, buf=2)

        _q = cf.riemann_prim(idir, myg.ng,
                             ivars.irho, ivars.iu, ivars.iv, ivars.ip, ivars.ix, ivars.naux,
                             0, 0,
                             gamma, q_l, q_r)

        q_int_avg = ai.ArrayIndexer(_q, grid=myg)

        # calculate the face-centered W using the transverse Laplacian
        q_int_fc = myg.scratch_array(nvar=ivars.nq)

        if idir == 1:
            for n in range(ivars.nq):
                q_int_fc.v(n=n, buf=myg.ng-1)[:, :] = q_int_avg.v(n=n, buf=myg.ng-1) - \
                    1.0/24.0 * (q_int_avg.jp(1, n=n, buf=myg.ng-1) -
                                2*q_int_avg.v(n=n, buf=myg.ng-1) +
                                q_int_avg.jp(-1, n=n, buf=myg.ng-1))
        else:
            for n in range(ivars.nq):
                q_int_fc.v(n=n, buf=myg.ng-1)[:, :] = q_int_avg.v(n=n, buf=myg.ng-1) - \
                    1.0/24.0 * (q_int_avg.ip(1, n=n, buf=myg.ng-1) -
                                2*q_int_avg.v(n=n, buf=myg.ng-1) +
                                q_int_avg.ip(-1, n=n, buf=myg.ng-1))

        # compute the final fluxes
        F_fc = flux_cons(ivars, idir, gamma, q_int_fc)
        F_avg = flux_cons(ivars, idir, gamma, q_int_avg)

        if idir == 1:
            F_x = myg.scratch_array(nvar=ivars.nvar)
            for n in range(ivars.nvar):
                F_x.v(n=n, buf=1)[:, :] = F_fc.v(n=n, buf=1) + \
                    1.0/24.0 * (F_avg.jp(1, n=n, buf=1) -
                                2*F_avg.v(n=n, buf=1) +
                                F_avg.jp(-1, n=n, buf=1))
        else:
            F_y = myg.scratch_array(nvar=ivars.nvar)
            for n in range(ivars.nvar):
                F_y.v(n=n, buf=1)[:, :] = F_fc.v(n=n, buf=1) + \
                    1.0/24.0 * (F_avg.ip(1, n=n, buf=1) -
                                2*F_avg.v(n=n, buf=1) +
                                F_avg.ip(-1, n=n, buf=1))

        # artificial viscosity McCorquodale & Colella Eq. 35, 36
        # first find face-centered div
        lam = myg.scratch_array()

        if idir == 1:
            lam.v(buf=1)[:, :] = (q_bar.v(buf=1, n=ivars.iu) -
                                  q_bar.ip(-1, buf=1, n=ivars.iu))/myg.dx + \
                                  0.25*(q_bar.jp(1, buf=1, n=ivars.iv) -
                                        q_bar.jp(-1, buf=1, n=ivars.iv) +
                                        q_bar.ip_jp(-1, 1, buf=1, n=ivars.iv) -
                                        q_bar.ip_jp(-1, -1, buf=1, n=ivars.iv))/myg.dy
        else:
            lam.v(buf=1)[:, :] = (q_bar.v(buf=1, n=ivars.iv) -
                                  q_bar.jp(-1, buf=1, n=ivars.iv))/myg.dy + \
                                  0.25*(q_bar.ip(1, buf=1, n=ivars.iu) -
                                        q_bar.ip(-1, buf=1, n=ivars.iu) +
                                        q_bar.ip_jp(1, -1, buf=1, n=ivars.iu) -
                                        q_bar.ip_jp(-1, -1, buf=1, n=ivars.iu))/myg.dx

        test = myg.scratch_array()
        test.v(buf=1)[:, :] = (myg.dx*lam.v(buf=1))**2 / \
                                (beta * gamma * q_bar.v(buf=1, n=ivars.ip) /
                                 q_bar.v(buf=1, n=ivars.irho))

        nu = myg.dx * lam * np.minimum(test, 1.0)
        nu[lam >= 0.0] = 0.0

        if idir == 1:
            for n in range(ivars.nvar):
                F_x.v(buf=1, n=n)[:, :] += alpha * nu.v(buf=1) * (U_avg.v(buf=1, n=n) - U_avg.ip(-1, buf=1, n=n))
        else:
            for n in range(ivars.nvar):
                F_y.v(buf=1, n=n)[:, :] += alpha * nu.v(buf=1) * (U_avg.v(buf=1, n=n) - U_avg.jp(-1, buf=1, n=n))

    return F_x, F_y