RiemannSolvers_iNS.f90 Source File


Source Code

#include "Includes.h"
module RiemannSolvers_iNSKeywordsModule

     integer,                       parameter :: KEYWORD_LENGTH           = 132
     character(len=KEYWORD_LENGTH), parameter :: RIEMANN_SOLVER_NAME_KEY  = "riemann solver"
     character(len=KEYWORD_LENGTH), parameter :: LAMBDA_STABILIZATION_KEY = "lambda stabilization"
     character(len=KEYWORD_LENGTH), parameter :: AVG_NAME_KEY             = "averaging"
!
!    --------------------------
!    Riemann solver definitions
!    --------------------------
     character(len=KEYWORD_LENGTH), parameter :: RIEMANN_CENTRAL_NAME = "central"
     character(len=KEYWORD_LENGTH), parameter :: RIEMANN_LXF_NAME     = "lax-friedrichs"
     character(len=KEYWORD_LENGTH), parameter :: RIEMANN_EXACT_NAME   = "exact"

     enum, bind(C)
        enumerator :: RIEMANN_CENTRAL = 1, RIEMANN_LXF, RIEMANN_EXACT
     end enum
!
!    -----------------------------
!    Available averaging functions
!    -----------------------------
!
     character(len=KEYWORD_LENGTH), parameter :: STANDARD_AVG_NAME       = "standard"
     character(len=KEYWORD_LENGTH), parameter :: SKEWSYMMETRIC1_AVG_NAME = "skew-symmetric 1"
     character(len=KEYWORD_LENGTH), parameter :: SKEWSYMMETRIC2_AVG_NAME = "skew-symmetric 2"

     enum, bind(C)
        enumerator :: STANDARD_AVG = 1, SKEWSYMMETRIC1_AVG, SKEWSYMMETRIC2_AVG
     end enum

end module RiemannSolvers_iNSKeywordsModule
!
!////////////////////////////////////////////////////////////////////////
!
module RiemannSolvers_iNS
   use SMConstants
   use Physics_iNS
   use PhysicsStorage_iNS
   use VariableConversion_iNS
   use FluidData_iNS

   implicit none

   private
   public whichAverage, whichRiemannSolver
   public SetRiemannSolver, DescribeRiemannSolver
   public RiemannSolver, AveragedStates, TwoPointFlux, ExactRiemannSolver

   abstract interface
      subroutine RiemannSolverFCN(QLeft, QRight, nHat, t1, t2, flux)
         use SMConstants
         use PhysicsStorage_iNS
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(in)       :: nHat(1:NDIM)
         real(kind=RP), intent(in)       :: t1(1:NDIM)
         real(kind=RP), intent(in)       :: t2(1:NDIM)
         real(kind=RP), intent(out)      :: flux(1:NCONS)
      end subroutine RiemannSolverFCN

      subroutine AveragedStatesFCN(QLeft, QRight, f, g, h)
         use SMConstants
         use PhysicsStorage_iNS
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(out)      :: f(1:NCONS), g(1:NCONS), h(1:NCONS)
      end subroutine AveragedStatesFCN

      subroutine TwoPointFluxFCN(QLeft, QRight, JaL, JaR, fSharp)
         use SMConstants
         use PhysicsStorage_iNS
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(in)       :: JaL(1:NDIM)
         real(kind=RP), intent(in)       :: JaR(1:NDIM)
         real(kind=RP), intent(out)      :: fSharp(NCONS)
      end subroutine TwoPointFluxFCN
   end interface

   procedure(RiemannSolverFCN),  protected, pointer :: RiemannSolver  => NULL()
   procedure(AveragedStatesFCN), protected, pointer :: AveragedStates => NULL()
   procedure(TwoPointFluxFCN),   protected, pointer :: TwoPointFlux   => NULL()

   integer, protected :: whichRiemannSolver = -1
   integer, protected :: whichAverage = -1
   real(RP)           :: lambdaStab = 1.0_RP
!
!  ========
   contains
!  ========
!
      subroutine SetRiemannSolver(controlVariables)
!
!        -------
!        Modules
!        -------
         use Utilities, only: toLower
         use FTValueDictionaryClass
         use RiemannSolvers_iNSKeywordsModule
!
!        ---------
!        Interface
!        ---------
         type(FTValueDictionary), intent(in) :: controlVariables
!
!        ---------------
!        Local variables
!        ---------------
         character(len=KEYWORD_LENGTH) :: keyword

!
!        --------------------------------------------
!        Choose the Riemann solver (default is exact)
!        --------------------------------------------
         if (controlVariables % containsKey(RIEMANN_SOLVER_NAME_KEY)) then

            keyword = controlVariables % stringValueForKey(RIEMANN_SOLVER_NAME_KEY, KEYWORD_LENGTH)
            call toLower(keyword)

            select case (keyword)
            case(RIEMANN_CENTRAL_NAME)
               RiemannSolver => CentralRiemannSolver
               whichRiemannSolver = RIEMANN_CENTRAL

            case(RIEMANN_LXF_NAME)
               RiemannSolver => LxFRiemannSolver
               whichRiemannSolver = RIEMANN_LXF

            case(RIEMANN_EXACT_NAME)
               RiemannSolver => ExactRiemannSolver
               whichRiemannSolver = RIEMANN_EXACT

            case default
               print*, "Riemann Solver not recognized."
               errorMessage(STD_OUT)
               error stop
            end select

         else
!
!           Select exact by default
!           -----------------------
            RiemannSolver => CentralRiemannSolver
            whichRiemannSolver = RIEMANN_EXACT

         end if
!
!        --------------------
!        Lambda stabilization
!        --------------------
         if (controlVariables % containsKey(LAMBDA_STABILIZATION_KEY)) then
            lambdaStab = controlVariables % doublePrecisionValueForKey(LAMBDA_STABILIZATION_KEY)

         else
!
!           By default, lambda is 1 (full upwind stabilization)
!           ---------------------------------------------------
            lambdaStab = 1.0_RP

         end if
!
!        If central fluxes are used, set lambdaStab to zero
!        --------------------------------------------------
         if (whichRiemannSolver .eq. RIEMANN_CENTRAL) lambdaStab = 0.0_RP
!
!        ----------------------------
!        Set up an averaging function
!        ----------------------------
         if (controlVariables % containsKey(AVG_NAME_KEY)) then

            keyword = controlVariables % stringValueForKey(AVG_NAME_KEY, KEYWORD_LENGTH)
            call toLower(keyword)

            select case (keyword)
            case (STANDARD_AVG_NAME)
               AveragedStates => StandardAverage
               TwoPointFlux => StandardDG_TwoPointFlux
               whichAverage = STANDARD_AVG

            case (SKEWSYMMETRIC1_AVG_NAME)
               AveragedStates => SkewSymmetric1Average
               TwoPointFlux => SkewSymmetric1DG_TwoPointFlux
               whichAverage = SKEWSYMMETRIC1_AVG

            case (SKEWSYMMETRIC2_AVG_NAME)
               AveragedStates => SkewSymmetric2Average
               TwoPointFlux => SkewSymmetric2DG_TwoPointFlux
               whichAverage = SKEWSYMMETRIC2_AVG

            case default
               print*, "Averaging not recognized."
               errorMessage(STD_OUT)
               error stop
            end select

         else
!
!           Select standard by default
!           --------------------------
            AveragedStates => StandardAverage
            TwoPointFlux => StandardDG_TwoPointFlux
            whichAverage = STANDARD_AVG

         end if

      END SUBROUTINE SetRiemannSolver

      subroutine DescribeRiemannSolver
!
!        -------
!        Modules
!        -------
         use RiemannSolvers_iNSKeywordsModule


         select case (whichAverage)
         case (STANDARD_AVG)
            write(STD_OUT,'(30X,A,A30,A)') "->","Averaging function: ","Standard"

         case (SKEWSYMMETRIC1_AVG)
            write(STD_OUT,'(30X,A,A30,A)') "->","Averaging function: ","Skew-symmetric 1"

         case (SKEWSYMMETRIC2_AVG)
            write(STD_OUT,'(30X,A,A30,A)') "->","Averaging function: ","Skew-symmetric 2"

         end select

         select case (whichRiemannSolver)
         case (RIEMANN_CENTRAL)
            write(STD_OUT,'(30X,A,A30,A)') "->","Riemann solver: ","Central"

         case (RIEMANN_LXF)
            write(STD_OUT,'(30X,A,A30,A)') "->","Riemann solver: ","Lax-Friedrichs"

         case (RIEMANN_EXACT)
            write(STD_OUT,'(30X,A,A30,A)') "->","Riemann solver: ","Exact"

         end select

         write(STD_OUT,'(30X,A,A30,F10.3)') "->","Lambda stabilization: ", lambdaStab

      end subroutine DescribeRiemannSolver
!
!///////////////////////////////////////////////////////////////////////////////////////////
!
!        Riemann solvers
!        ---------------
!
!///////////////////////////////////////////////////////////////////////////////////////////
!
      subroutine CentralRiemannSolver(QLeft, QRight, nHat, t1, t2, flux)
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(in)       :: nHat(1:NDIM), t1(NDIM), t2(NDIM)
         real(kind=RP), intent(out)      :: flux(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP) :: f(1:NCONS), g(1:NCONS), h(1:NCONS)
!
!        Rotate the variables to the face local frame using normal and tangent vectors
!        -----------------------------------------------------------------------------
!         rhoL = QLeft(INSRHO)
!         invRhoL = 1.0_RP / rhoL
!         uL = invRhoL * (QLeft(INSRHOU) * nHat(1) + QLeft(INSRHOV) * nHat(2) + QLeft(INSRHOW) * nHat(3))
!         vL = invRhoL * (QLeft(INSRHOU) * t1(1)   + QLeft(INSRHOV) * t1(2)   + QLeft(INSRHOW) * t1(3))
!         wL = invRhoL * (QLeft(INSRHOU) * t2(1)   + QLeft(INSRHOV) * t2(2)   + QLeft(INSRHOW) * t2(3))
!         pL = QLeft(INSP)
!
!         rhoR = QRight(INSRHO)
!         invRhoR = 1.0_RP / rhoR
!         uR = invRhoR * (QRight(INSRHOU) * nHat(1) + QRight(INSRHOV) * nHat(2) + QRight(INSRHOW) * nHat(3))
!         vR = invRhoR * (QRight(INSRHOU) * t1(1)   + QRight(INSRHOV) * t1(2)   + QRight(INSRHOW) * t1(3))
!         wR = invRhoR * (QRight(INSRHOU) * t2(1)   + QRight(INSRHOV) * t2(2)   + QRight(INSRHOW) * t2(3))
!         pR = QRight(INSP)
!!
!!        Perform the average using the averaging function
!!        ------------------------------------------------
!         QLRot = (/ rhoL, uL, vL, wL, pL /)
!         QRRot = (/ rhoR, uR, vR, wR, pR /)
!         call AveragedStates(QLRot, QRRot, pL, pR, rhoL, rhoR, flux)
!!
!!        ************************************************
!!        Return momentum equations to the cartesian frame
!!        ************************************************
!!
!         flux(2:4) = nHat*flux(2) + t1*flux(3) + t2*flux(4)

          call AveragedStates(QLeft, QRight, f, g, h)

          flux = f * nHat(1) + g*nHat(2) + h*nHat(3)

      end subroutine CentralRiemannSolver

      subroutine LxFRiemannSolver(QLeft, QRight, nHat, t1, t2, flux)
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(in)       :: nHat(1:NDIM), t1(NDIM), t2(NDIM)
         real(kind=RP), intent(out)      :: flux(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: rhoL, uL, vL, wL, pL, invRhoL
         real(kind=RP)  :: rhoR, uR, vR, wR, pR, invRhoR
         real(kind=RP)  :: QLRot(NCONS), QRRot(NCONS)
         real(kind=RP)  :: stab(NCONS), lambdaMax
!!
!!        Rotate the variables to the face local frame using normal and tangent vectors
!!        -----------------------------------------------------------------------------
!         rhoL = QLeft(INSRHO)
!         invRhoL = 1.0_RP / rhoL
!         uL = invRhoL * (QLeft(INSRHOU) * nHat(1) + QLeft(INSRHOV) * nHat(2) + QLeft(INSRHOW) * nHat(3))
!         vL = invRhoL * (QLeft(INSRHOU) * t1(1)   + QLeft(INSRHOV) * t1(2)   + QLeft(INSRHOW) * t1(3))
!         wL = invRhoL * (QLeft(INSRHOU) * t2(1)   + QLeft(INSRHOV) * t2(2)   + QLeft(INSRHOW) * t2(3))
!         pL = QLeft(INSP)
!
!         rhoR = QRight(INSRHO)
!         invRhoR = 1.0_RP / rhoR
!         uR = invRhoR * (QRight(INSRHOU) * nHat(1) + QRight(INSRHOV) * nHat(2) + QRight(INSRHOW) * nHat(3))
!         vR = invRhoR * (QRight(INSRHOU) * t1(1)   + QRight(INSRHOV) * t1(2)   + QRight(INSRHOW) * t1(3))
!         wR = invRhoR * (QRight(INSRHOU) * t2(1)   + QRight(INSRHOV) * t2(2)   + QRight(INSRHOW) * t2(3))
!         pR = QRight(INSP)
!!
!!        Perform the average using the averaging function
!!        ------------------------------------------------
!         QLRot = (/ rhoL, uL, vL, wL, pL /)
!         QRRot = (/ rhoR, uR, vR, wR, pR /)
!         call AveragedStates(QLRot, QRRot, pL, pR, rhoL, rhoR, flux)
!!
!!        Compute the Lax-Friedrichs stabilization
!!        ----------------------------------------
!         lambdaMax = max(uL + sqrt(uL**2+4.0_RP*thermodynamics % rho0c02/rhoL), &
!                      uR + sqrt(uR**2+4.0_RP*thermodynamics % rho0c02/rhoR)    ) 
!
!         stab = 0.5_RP * lambdaMax * (QRRot - QLRot)
!
!         flux = flux - stab
!!
!!        ************************************************
!!        Return momentum equations to the cartesian frame
!!        ************************************************
!!
!         flux(2:4) = nHat*flux(2) + t1*flux(3) + t2*flux(4)

print*, "LxF Riemann solver not implemented"
error stop

      end subroutine LxFRiemannSolver

      subroutine ExactRiemannSolver(QLeft, QRight, nHat, t1, t2, flux)
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(in)       :: nHat(1:NDIM), t1(NDIM), t2(NDIM)
         real(kind=RP), intent(out)      :: flux(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: rhoL, uL, vL, wL, pL, invRhoL, lambdaMinusL, lambdaPlusL
         real(kind=RP)  :: rhoR, uR, vR, wR, pR, invRhoR, lambdaMinusR, lambdaPlusR
         real(kind=RP)  :: rhoStarL, rhoStarR, uStar, pStar, rhoStar, vStar, wStar
         real(kind=RP)  :: QLRot(NCONS), QRRot(NCONS)
         real(kind=RP)  :: stab(NCONS), lambdaMax
!
!        Rotate the variables to the face local frame using normal and tangent vectors
!        -----------------------------------------------------------------------------
         rhoL = QLeft(INSRHO)
         invRhoL = 1.0_RP / rhoL
         uL = invRhoL * (QLeft(INSRHOU) * nHat(1) + QLeft(INSRHOV) * nHat(2) + QLeft(INSRHOW) * nHat(3))
         vL = invRhoL * (QLeft(INSRHOU) * t1(1)   + QLeft(INSRHOV) * t1(2)   + QLeft(INSRHOW) * t1(3))
         wL = invRhoL * (QLeft(INSRHOU) * t2(1)   + QLeft(INSRHOV) * t2(2)   + QLeft(INSRHOW) * t2(3))
         pL = QLeft(INSP)

         rhoR = QRight(INSRHO)
         invRhoR = 1.0_RP / rhoR
         uR = invRhoR * (QRight(INSRHOU) * nHat(1) + QRight(INSRHOV) * nHat(2) + QRight(INSRHOW) * nHat(3))
         vR = invRhoR * (QRight(INSRHOU) * t1(1)   + QRight(INSRHOV) * t1(2)   + QRight(INSRHOW) * t1(3))
         wR = invRhoR * (QRight(INSRHOU) * t2(1)   + QRight(INSRHOV) * t2(2)   + QRight(INSRHOW) * t2(3))
         pR = QRight(INSP)
!
!        Compute the Star Region
!        -----------------------
         lambdaMinusR = 0.5_RP * (uR - sqrt(uR*uR + 4.0_RP*thermodynamics % rho0c02/rhoR))
         lambdaPlusR  = 0.5_RP * (uR + sqrt(uR*uR + 4.0_RP*thermodynamics % rho0c02/rhoR))

         lambdaMinusL = 0.5_RP * (uL - sqrt(uL*uL + 4.0_RP*thermodynamics % rho0c02/rhoL))
         lambdaPlusL  = 0.5_RP * (uL + sqrt(uL*uL + 4.0_RP*thermodynamics % rho0c02/rhoL))

         uStar = (pR-pL+rhoR*uR*lambdaMinusR-rhoL*uL*lambdaPlusL)/(rhoR*lambdaMinusR - rhoL*lambdaPlusL)
         pStar = pR + rhoR*lambdaMinusR*(uR-uStar)
         rhoStarL = (rhoL*lambdaPlusL)/(uStar-lambdaMinusL)
         rhoStarR = (rhoR*lambdaMinusR)/(uStar - lambdaPlusR)

         if ( uStar .ge. 0.0_RP ) then
            rhoStar = rhoStarL
            vStar   = vL
            wStar   = wL

         else
            rhoStar = rhoStarR
            vStar   = vR
            wStar   = wR

         end if

         flux = [rhoStar*uStar, rhoStar*uStar*uStar + pStar, rhoStar*uStar*vStar, rhoStar*uStar*wStar, thermodynamics % rho0c02 * uStar]
!
!        ************************************************
!        Return momentum equations to the cartesian frame
!        ************************************************
!
         flux(2:4) = nHat*flux(2) + t1*flux(3) + t2*flux(4)

      end subroutine ExactRiemannSolver
!
!////////////////////////////////////////////////////////////////////////////////////////////
!
!        Averaged states functions
!        -------------------------
!
!     To this averages, the states QLeft and QRight velocities have already been rotated,
!  so that only the first flux component has to be computed (Rotational invariance, see
!  E.F. Toro - Riemann solvers and numerical methods for fluid dynamics. Page 105).
!
!  Implemented two-point averages are:
!     -> Standard: Central fluxes
!     -> Skew-symmetric 1
!     -> Skew-symmetric 2
!
!////////////////////////////////////////////////////////////////////////////////////////////
!
      subroutine StandardAverage(QLeft, QRight, f, g, h)
!
!        *********************************************************************
!           Computes the standard average of the two states:
!              F* = {{F}} = 0.5 * (FL + FR)
!
!           State vectors are rotated.
!        *********************************************************************
!
         use Physics_iNS, only: iEulerXFlux
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(out)      :: f(1:NCONS), g(1:NCONS), h(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: fL(NCONS), fR(NCONS)
!
!        Compute the flux
!        ----------------
!         fL(INSRHO)  = QLeft(INSRHO) * QLeft(INSRHOU)
!         fL(INSRHOU) = fL(INSRHO) * QLeft(INSRHOU) + QLeft(INSP)
!         fL(INSRHOV) = fL(INSRHO) * QLeft(INSRHOV)
!         fL(INSRHOW) = fL(INSRHO) * QLeft(INSRHOW)
!         fL(INSP)    = thermodynamics % rho0c02 * QLeft(INSP)
!
!         fR(INSRHO)  = QRight(INSRHO) * QRight(INSRHOU)
!         fR(INSRHOU) = fR(INSRHO) * QRight(INSRHOU) + QRight(INSP)
!         fR(INSRHOV) = fR(INSRHO) * QRight(INSRHOV)
!         fR(INSRHOW) = fR(INSRHO) * QRight(INSRHOW)
!         fR(INSP)    = thermodynamics % rho0c02 * QRight(INSP)
!
!         flux = 0.5_RP * (fL + fR)

         print*, "Standard average not implemented"
         error stop

      end subroutine StandardAverage

      subroutine SkewSymmetric1Average(QLeft, QRight, f, g, h)
!
!        *********************************************************************
!        *********************************************************************
!
         use Physics_iNS, only: iEulerXFlux
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(out)      :: f(1:NCONS), g(1:NCONS), h(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: rhou, u

!         rhou = 0.5_RP * (QLeft(INSRHO) * QLeft(INSRHOU) + QRight(INSRHO) * QRight(INSRHOU))
!         u    = 0.5_RP * (QLeft(INSRHOU) + QRight(INSRHOU))
!!
!!        Compute the flux
!!        ----------------
!         flux(INSRHO) = rhou
!         flux(INSRHOU) = rhou * u + 0.5_RP * (QLeft(INSP) + QRight(INSP))
!         flux(INSRHOU) = rhou * 0.5_RP * (QLeft(INSRHOV) + QRight(INSRHOV))
!         flux(INSRHOU) = rhou * 0.5_RP * (QLeft(INSRHOW) + QRight(INSRHOW))
!         flux(INSP)    = thermodynamics % rho0c02 * u
!
         print*, "SkewSymmetric 1 average not implemented"
         error stop
      end subroutine SkewSymmetric1Average

      subroutine SkewSymmetric2Average(QLeft, QRight, f, g, h)
!
!        *********************************************************************
!        *********************************************************************
!
         use Physics_iNS, only: iEulerXFlux
         implicit none
         real(kind=RP), intent(in)       :: QLeft(1:NCONS)
         real(kind=RP), intent(in)       :: QRight(1:NCONS)
         real(kind=RP), intent(out)      :: f(1:NCONS), g(1:NCONS), h(1:NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)  :: invRhoL, invRhoR
         real(kind=RP)  :: rho, u, v, w, p

         invRhoL = 1.0_RP / QLeft(INSRHO)    ; invRhoR = 1.0_RP / QRight(INSRHO)

         rho = 0.5_RP * (QLeft(INSRHO) + QRight(INSRHO))
         u   = 0.5_RP * (invRhoL * QLeft(INSRHOU) + invRhoR * QRight(INSRHOU))
         v   = 0.5_RP * (invRhoL * QLeft(INSRHOV) + invRhoR * QRight(INSRHOV))
         w   = 0.5_RP * (invRhoL * QLeft(INSRHOW) + invRhoR * QRight(INSRHOW))
         p   = 0.5_RP * (QLeft(INSP) + QRight(INSP))

         f(INSRHO) = rho*u
         f(INSRHOU) = f(INSRHO)*u+p
         f(INSRHOV) = f(INSRHO)*v
         f(INSRHOW) = f(INSRHO)*w
         f(INSP)    = thermodynamics % rho0c02 * u

         g(INSRHO) = rho*v
         g(INSRHOU) = g(INSRHO)*u
         g(INSRHOV) = g(INSRHO)*v+p
         g(INSRHOW) = g(INSRHO)*w
         g(INSP)    = thermodynamics % rho0c02 * v

         h(INSRHO) = rho*w
         h(INSRHOU) = h(INSRHO)*u
         h(INSRHOV) = h(INSRHO)*v
         h(INSRHOW) = h(INSRHO)*w + p
         h(INSP)    = thermodynamics % rho0c02 * w


         

!         u    = 0.5_RP * (QLeft(INSRHOU) + QRight(INSRHOU))
!!
!!        Compute the flux
!!        ----------------
!         flux(INSRHO) = 0.5_RP * (QLeft(INSRHO) + QRight(INSRHO)) * u
!         flux(INSRHOU) = flux(INSRHOU) * u + 0.5_RP * (QLeft(INSP) + QRight(INSP))
!         flux(INSRHOU) = flux(INSRHOU) * 0.5_RP * (QLeft(INSRHOV) + QRight(INSRHOV))
!         flux(INSRHOU) = flux(INSRHOU) * 0.5_RP * (QLeft(INSRHOW) + QRight(INSRHOW))
!         flux(INSP)    = thermodynamics % rho0c02 * u

      end subroutine SkewSymmetric2Average
!
!///////////////////////////////////////////////////////////////////////
!
!        Volumetric two-point fluxes
!        ---------------------------
!///////////////////////////////////////////////////////////////////////
!
      subroutine StandardDG_TwoPointFlux(QL,QR,JaL,JaR, fSharp)
         use SMConstants
         use PhysicsStorage_iNS
         implicit none
         real(kind=RP), intent(in)       :: QL(1:NCONS)
         real(kind=RP), intent(in)       :: QR(1:NCONS)
         real(kind=RP), intent(in)       :: JaL(1:NDIM)
         real(kind=RP), intent(in)       :: JaR(1:NDIM)
         real(kind=RP), intent(out)      :: fSharp(NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP)     :: rhoL, uL, vL, wL, pL, invRhoL
         real(kind=RP)     :: rhoR, uR, vR, wR, pR, invRhoR
         real(kind=RP)     :: Ja(1:NDIM)
         real(kind=RP)     :: f(NCONS), g(NCONS), h(NCONS)

         rhoL    = QL(INSRHO)
         rhoR    = QR(INSRHO)
         invRhoL = 1.0_RP / rhoL         ; invRhoR = 1.0_RP / rhoR
         uL      = QL(INSRHOU) * invRhoL ; uR      = QR(INSRHOU) * invRhoR
         vL      = QL(INSRHOV) * invRhoL ; vR      = QR(INSRHOV) * invRhoR
         wL      = QL(INSRHOW) * invRhoL ; wR      = QR(INSRHOW) * invRhoR
         pL      = QL(INSP)              ; pR      = QR(INSP)

!
!        Average metrics: (Note: Here all average (1/2)s are accounted later)
!        ---------------
         Ja = (JaL + JaR)
!
!        Compute the flux
!        ----------------
         f(INSRHO)  = rhoL*uL         + rhoR*uR
         f(INSRHOU) = rhoL*uL*uL + pL + rhoR*uR*uR + pR
         f(INSRHOV) = rhoL*uL*vL      + rhoR*uR*vR
         f(INSRHOW) = rhoL*uL*wL      + rhoR*uR*wR
         f(INSP)    = thermodynamics % rho0c02 * (uL + uR)

         g(INSRHO)  = rhoL*vL         + rhoR*vR
         g(INSRHOU) = rhoL*vL*uL      + rhoR*vR*uR
         g(INSRHOV) = rhoL*vL*vL + pL + rhoR*vR*vR + pR
         g(INSRHOW) = rhoL*vL*wL      + rhoR*vR*wR
         g(INSP)    = thermodynamics % rho0c02 * (vL + vR)

         h(INSRHO)  = rhoL*wL         + rhoR*wR
         h(INSRHOU) = rhoL*wL*uL      + rhoR*wR*uR
         h(INSRHOV) = rhoL*wL*vL      + rhoR*wR*vR
         h(INSRHOW) = rhoL*wL*wL + pL + rhoR*wR*wR + pR
         h(INSP)    = thermodynamics % rho0c02 * (wL + wR)
!
!        Compute the sharp flux: (And account for the (1/2)^2)
!        ----------------------
         fSharp = 0.25_RP * ( f*Ja(IX) + g*Ja(IY) + h*Ja(IZ) )

      end subroutine StandardDG_TwoPointFlux

      subroutine SkewSymmetric1DG_TwoPointFlux(QL,QR,JaL,JaR, fSharp)
         use SMConstants
         use PhysicsStorage_iNS
         implicit none
         real(kind=RP), intent(in)       :: QL(1:NCONS)
         real(kind=RP), intent(in)       :: QR(1:NCONS)
         real(kind=RP), intent(in)       :: JaL(1:NDIM)
         real(kind=RP), intent(in)       :: JaR(1:NDIM)
         real(kind=RP), intent(out)      :: fSharp(NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP) :: rhoL, uL, vL, wL, pL, invRhoL
         real(kind=RP) :: rhoR, uR, vR, wR, pR, invRhoR
         real(kind=RP) :: rho, u, v, w, p, rhou, rhov, rhow
         real(kind=RP) :: Ja(1:NDIM)
         real(kind=RP) :: f(NCONS), g(NCONS), h(NCONS)

         rhoL    = QL(INSRHO)
         rhoR    = QR(INSRHO)
         invRhoL = 1.0_RP / rhoL         ; invRhoR = 1.0_RP / rhoR
         uL      = QL(INSRHOU) * invRhoL ; uR      = QR(INSRHOU) * invRhoR
         vL      = QL(INSRHOV) * invRhoL ; vR      = QR(INSRHOV) * invRhoR
         wL      = QL(INSRHOW) * invRhoL ; wR      = QR(INSRHOW) * invRhoR
         pL      = QL(INSP)              ; pR      = QR(INSP)

         rho = 0.5_RP * (rhoL + rhoR)
         u   = 0.5_RP * (uL + uR)
         v   = 0.5_RP * (vL + vR)
         w   = 0.5_RP * (wL + wR)
         p   = 0.5_RP * (pL + pR)

         rhou = 0.5_RP * (QL(INSRHOU) + QR(INSRHOU))
         rhov = 0.5_RP * (QL(INSRHOV) + QR(INSRHOV))
         rhow = 0.5_RP * (QL(INSRHOW) + QR(INSRHOW))
!
!        Average metrics
!        ---------------
         Ja = 0.5_RP * (JaL + JaR)
!
!        Compute the flux
!        ----------------
         f(INSRHO)  = rhou
         f(INSRHOU) = rhou*u + p
         f(INSRHOV) = rhou*v
         f(INSRHOW) = rhou*w
         f(INSP)    = thermodynamics % rho0c02 * u

         g(INSRHO)  = rhov
         g(INSRHOU) = rhov*u
         g(INSRHOV) = rhov*v + p
         g(INSRHOW) = rhov*w
         g(INSP)    = thermodynamics % rho0c02 * v

         h(INSRHO)  = rhow
         h(INSRHOU) = rhow*u
         h(INSRHOV) = rhow*v
         h(INSRHOW) = rhow*w + p
         h(INSP)    = thermodynamics % rho0c02 * w
!
!        Compute the sharp flux: (And account for the (1/2)^2)
!        ----------------------
         fSharp = f*Ja(IX) + g*Ja(IY) + h*Ja(IZ)

      end subroutine SkewSymmetric1DG_TwoPointFlux

      subroutine SkewSymmetric2DG_TwoPointFlux(QL,QR,JaL,JaR, fSharp)
         use SMConstants
         use PhysicsStorage_iNS
         implicit none
         real(kind=RP), intent(in)       :: QL(1:NCONS)
         real(kind=RP), intent(in)       :: QR(1:NCONS)
         real(kind=RP), intent(in)       :: JaL(1:NDIM)
         real(kind=RP), intent(in)       :: JaR(1:NDIM)
         real(kind=RP), intent(out)      :: fSharp(NCONS)
!
!        ---------------
!        Local variables
!        ---------------
!
         real(kind=RP) :: rhoL, uL, vL, wL, pL, invRhoL
         real(kind=RP) :: rhoR, uR, vR, wR, pR, invRhoR
         real(kind=RP) :: rho, u, v, w, p
         real(kind=RP) :: Ja(1:NDIM)
         real(kind=RP) :: f(NCONS), g(NCONS), h(NCONS)

         rhoL    = QL(INSRHO)
         rhoR    = QR(INSRHO)

         invRhoL = 1.0_RP / rhoL         ; invRhoR = 1.0_RP / rhoR
         uL      = QL(INSRHOU) * invRhoL ; uR      = QR(INSRHOU) * invRhoR
         vL      = QL(INSRHOV) * invRhoL ; vR      = QR(INSRHOV) * invRhoR
         wL      = QL(INSRHOW) * invRhoL ; wR      = QR(INSRHOW) * invRhoR
         pL      = QL(INSP)              ; pR      = QR(INSP)

         rho = 0.5_RP * (rhoL + rhoR)
         u   = 0.5_RP * (uL + uR)
         v   = 0.5_RP * (vL + vR)
         w   = 0.5_RP * (wL + wR)
         p   = 0.5_RP * (pL + pR)
!
!        Average metrics
!        ---------------
         Ja = 0.5_RP * (JaL + JaR)
!
!        Compute the flux
!        ----------------
         f(INSRHO)  = rho*u
         f(INSRHOU) = rho*u*u + p
         f(INSRHOV) = rho*u*v
         f(INSRHOW) = rho*u*w
         f(INSP)    = thermodynamics % rho0c02 * u

         g(INSRHO)  = rho*v
         g(INSRHOU) = rho*v*u
         g(INSRHOV) = rho*v*v + p
         g(INSRHOW) = rho*v*w
         g(INSP)    = thermodynamics % rho0c02 * v

         h(INSRHO)  = rho*w
         h(INSRHOU) = rho*w*u
         h(INSRHOV) = rho*w*v
         h(INSRHOW) = rho*w*w + p
         h(INSP)    = thermodynamics % rho0c02 * w
!
!        Compute the sharp flux: (And account for the (1/2)^2)
!        ----------------------
         fSharp = f*Ja(IX) + g*Ja(IY) + h*Ja(IZ)

      end subroutine SkewSymmetric2DG_TwoPointFlux

end module RiemannSolvers_iNS