Program Listing for File roeHD.hpp
↰ Return to documentation for file (hydro/HDsolvers/roeHD.hpp
)
// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************
#ifndef HYDRO_HDSOLVERS_ROEHD_HPP_
#define HYDRO_HDSOLVERS_ROEHD_HPP_
#include "../idefix.hpp"
#include "hydro.hpp"
#include "slopeLimiter.hpp"
#include "fluxHD.hpp"
#include "convertConsToPrimHD.hpp"
#define ROE_AVERAGE 0
#if HAVE_ENERGY
#define I0 0
#define I1 1
#define IE 2
#define I2 3
#define I3 4
#define NMODES 5
#else
#define I0 0
#define I1 1
#define I2 2
#define I3 3
#define NMODES 4
#endif
// Compute Riemann fluxes from states using ROE solver
template<const int DIR>
void Hydro::RoeHD() {
idfx::pushRegion("Hydro::ROE_Solver");
constexpr int ioffset = (DIR==IDIR) ? 1 : 0;
constexpr int joffset = (DIR==JDIR) ? 1 : 0;
constexpr int koffset = (DIR==KDIR) ? 1 : 0;
IdefixArray4D<real> Vc = this->Vc;
IdefixArray4D<real> Vs = this->Vs;
IdefixArray4D<real> Flux = this->FluxRiemann;
IdefixArray3D<real> cMax = this->cMax;
IdefixArray3D<real> csIsoArr = this->isoSoundSpeedArray;
[[maybe_unused]] real gamma = this->gamma;
[[maybe_unused]] real gamma_m1 = this->gamma - ONE_F;
[[maybe_unused]] real csIso = this->isoSoundSpeed;
[[maybe_unused]] HydroModuleStatus haveIsoCs = this->haveIsoSoundSpeed;
SlopeLimiter<DIR,NVAR> slopeLim(Vc,data->dx[DIR],shockFlattening);
idefix_for("ROE_Kernel",
data->beg[KDIR],data->end[KDIR]+koffset,
data->beg[JDIR],data->end[JDIR]+joffset,
data->beg[IDIR],data->end[IDIR]+ioffset,
KOKKOS_LAMBDA (int k, int j, int i) {
// Init the directions (should be in the kernel for proper optimisation by the compilers)
EXPAND( const int Xn = DIR+MX1; ,
const int Xt = (DIR == IDIR ? MX2 : MX1); ,
const int Xb = (DIR == KDIR ? MX2 : MX3); )
// Primitive variables
real vL[NVAR];
real vR[NVAR];
real dv[NVAR];
// Conservative variables
real uL[NVAR];
real uR[NVAR];
// Flux (left and right)
real fluxL[NVAR];
real fluxR[NVAR];
// Roe
real Rc[NVAR][NVAR];
real um[NVAR];
// 1-- Store the primitive variables on the left, right, and averaged states
slopeLim.ExtrapolatePrimVar(i, j, k, vL, vR);
#pragma unroll
for(int nv = 0 ; nv < NVAR; nv++) {
dv[nv] = vR[nv] - vL[nv];
}
// --- Compute the square of the sound speed
real a, a2, a2L, a2R;
#if HAVE_ENERGY
a2L = gamma * vL[PRS] / vL[RHO];
a2R = gamma * vR[PRS] / vR[RHO];
real h, vel2;
#else
if(haveIsoCs == UserDefFunction) {
a2L = HALF_F*(csIsoArr(k,j,i)+csIsoArr(k-koffset,j-joffset,i-ioffset));
} else {
a2L = csIso;
}
// Take the square
a2L = a2L*a2L;
a2R = a2L;
#endif
// 2-- Compute the conservative variables
K_PrimToCons(uL, vL, gamma_m1);
K_PrimToCons(uR, vR, gamma_m1);
// 3-- Compute the left and right fluxes
K_Flux(fluxL, vL, uL, a2L, Xn);
K_Flux(fluxR, vR, uR, a2R, Xn);
// ---- Define Wave Jumps ----
#if ROE_AVERAGE == YES
real s, c;
s = std::sqrt(vR[RHO]/vL[RHO]);
um[RHO] = vL[RHO]*s;
s = ONE_F/(ONE_F + s);
c = ONE_F - s;
EXPAND(um[VX1] = s*vL[VX1] + c*vR[VX1]; ,
um[VX2] = s*vL[VX2] + c*vR[VX2]; ,
um[VX3] = s*vL[VX3] + c*vR[VX3];)
#if HAVE_ENERGY
real gmm1_inv = ONE_F / gamma_m1;
vel2 = EXPAND(um[VX1]*um[VX1], + um[VX2]*um[VX2], + um[VX3]*um[VX3]);
real hl, hr;
hl = HALF_F*(EXPAND(vL[VX1]*vL[VX1], + vL[VX2]*vL[VX2], + vL[VX3]*vL[VX3]));
hl += a2L*gmm1_inv;
hr = HALF_F*(EXPAND(vR[VX1]*vR[VX1], + vR[VX2]*vR[VX2], + vR[VX3]*vR[VX3]));
hr += a2R*gmm1_inv;
h = s*hl + c*hr;
/* -------------------------------------------------
the following should be equivalent to
scrh = EXPAND( dv[VX1]*dv[VX1],
+ dv[VX2]*dv[VX2],
+ dv[VX3]*dv[VX3]);
a2 = s*a2L + c*a2R + 0.5*gamma_m1*s*c*scrh;
and therefore always positive.
just work out the coefficiendnts...
-------------------------------------------------- */
a2 = gamma_m1*(h - HALF_F*vel2);
a = std::sqrt(a2);
#else
a2 = HALF_F*(a2L + a2R);
a = std::sqrt(a2);
#endif // HAVE_ENERGY
#else
#pragma unroll
for(int nv = 0 ; nv < NVAR; nv++) {
um[nv] = HALF_F*(vR[nv]+vL[nv]);
}
#if HAVE_ENERGY
a2 = gamma*um[PRS]/um[RHO];
a = std::sqrt(a2);
vel2 = EXPAND(um[VX1]*um[VX1], + um[VX2]*um[VX2], + um[VX3]*um[VX3]);
h = HALF_F*vel2 + a2/gamma_m1;
#else
a2 = HALF_F*(a2L + a2R);
a = std::sqrt(a2);
#endif // HAVE_ENERGY
#endif // ROE_AVERAGE == YES/NO
// **********************************************************************************
/* ----------------------------------------------------------------
define non-zero components of conservative eigenvectors Rc,
eigenvalues (lambda) and wave strenght eta = L.du
---------------------------------------------------------------- */
real lambda[NMODES], alambda[NMODES];
real eta[NMODES];
#pragma unroll
for(int nv1 = 0 ; nv1 < NVAR; nv1++) {
#pragma unroll
for(int nv2 = 0 ; nv2 < NVAR; nv2++) {
Rc[nv1][nv2] = 0;
}
}
// ---- (u - c_s) ----
// nn = 0;
lambda[I0] = um[Xn] - a;
#if HAVE_ENERGY
eta[I0] = HALF_F/a2*(dv[PRS] - dv[Xn]*um[RHO]*a);
#else
eta[I0] = HALF_F*(dv[RHO] - um[RHO]*dv[Xn]/a);
#endif
Rc[RHO][I0] = ONE_F;
EXPAND(Rc[Xn][I0] = um[Xn] - a; ,
Rc[Xt][I0] = um[Xt]; ,
Rc[Xb][I0] = um[Xb]; )
#if HAVE_ENERGY
Rc[ENG][I0] = h - um[Xn]*a;
#endif
/* ---- (u + c_s) ---- */
// nn = 1;
lambda[I1] = um[Xn] + a;
#if HAVE_ENERGY
eta[I1] = HALF_F/a2*(dv[PRS] + dv[Xn]*um[RHO]*a);
#else
eta[I1] = HALF_F*(dv[RHO] + um[RHO]*dv[Xn]/a);
#endif
Rc[RHO][I1] = ONE_F;
EXPAND(Rc[Xn][I1] = um[Xn] + a; ,
Rc[Xt][I1] = um[Xt]; ,
Rc[Xb][I1] = um[Xb];)
#if HAVE_ENERGY
Rc[ENG][I1] = h + um[Xn]*a;
#endif
#if HAVE_ENERGY
/* ---- (u) ---- */
// nn = 2;
lambda[IE] = um[Xn];
eta[IE] = dv[RHO] - dv[PRS]/a2;
Rc[RHO][IE] = ONE_F;
EXPAND(Rc[MX1][IE] = um[VX1]; ,
Rc[MX2][IE] = um[VX2]; ,
Rc[MX3][IE] = um[VX3];)
Rc[ENG][IE] = HALF_F*vel2;
#endif
#if COMPONENTS > 1
/* ---- (u) ---- */
// nn++;
lambda[I2] = um[Xn];
eta[I2] = um[RHO]*dv[Xt];
Rc[Xt][I2] = ONE_F;
#if HAVE_ENERGY
Rc[ENG][I2] = um[Xt];
#endif
#endif
#if COMPONENTS > 2
/* ---- (u) ---- */
// nn++;
lambda[I3] = um[Xn];
eta[I3] = um[RHO]*dv[Xb];
Rc[Xb][I3] = ONE_F;
#if HAVE_ENERGY
Rc[ENG][I3] = um[Xb];
#endif
#endif
/* ---- get max eigenvalue ---- */
real cmax = FABS(um[Xn]) + a;
//g_maxMach = FMAX(FABS(um[Xn]/a), g_maxMach);
/* ---------------------------------------------
use the HLL flux function if the interface
lies within a strong shock.
The effect of this switch is visible
in the Mach reflection test.
--------------------------------------------- */
real scrh;
#if HAVE_ENERGY
scrh = FABS(vL[PRS] - vR[PRS]);
scrh /= FMIN(vL[PRS],vR[PRS]);
#else
scrh = FABS(vL[RHO] - vR[RHO]);
scrh /= FMIN(vL[RHO],vR[RHO]);
scrh *= a*a;
#endif
/*#if CHECK_ROE_MATRIX == YES
for(int nv = 0 ; nv < NVAR; nv++) {
um[nv] = ZERO_F;
for(int nv1 = 0 ; nv1 < NVAR; nv1++) {
for(int nv2 = 0 ; nv2 < NVAR; nv2++) {
um[nv] += Rc[nv][k]*(k==j)*lambda[k]*eta[j];
}
}
}
for(int nv = 0 ; nv < NVAR; nv++) {
scrh = fluxR[nv] - fluxL[nv] - um[nv];
if (nv == Xn) scrh += pR - pL;
if (FABS(scrh) > 1.e-6){
print ("! Matrix condition not satisfied %d, %12.6e\n", nv, scrh);
exit(1);
}
}
#endif*/
if (scrh > HALF_F && (vR[Xn] < vL[Xn])) { /* -- tunable parameter -- */
#if DIMENSIONS > 1
real scrh1;
real bmin, bmax;
bmin = FMIN(ZERO_F, lambda[0]);
bmax = FMAX(ZERO_F, lambda[1]);
scrh1 = ONE_F/(bmax - bmin);
#pragma unroll
for(int nv = 0 ; nv < NVAR; nv++) {
Flux(nv,k,j,i) = bmin*bmax*(uR[nv] - uL[nv])
+ bmax*fluxL[nv] - bmin*fluxR[nv];
Flux(nv,k,j,i) *= scrh1;
}
#endif
} else {
/* -----------------------------------------------------------
compute Roe flux
----------------------------------------------------------- */
#pragma unroll
for(int nv = 0 ; nv < NVAR; nv++) {
alambda[nv] = fabs(lambda[nv]);
}
/* ---- entropy fix ---- */
real delta = 1.e-7;
if (alambda[0] <= delta) {
alambda[0] = HALF_F*lambda[0]*lambda[0]/delta + HALF_F*delta;
}
if (alambda[1] <= delta) {
alambda[1] = HALF_F*lambda[1]*lambda[1]/delta + HALF_F*delta;
}
#pragma unroll
for(int nv = 0 ; nv < NVAR; nv++) {
Flux(nv,k,j,i) = fluxL[nv] + fluxR[nv];
#pragma unroll
for(int nv2 = 0 ; nv2 < NVAR; nv2++) {
Flux(nv,k,j,i) -= alambda[nv2]*eta[nv2]*Rc[nv][nv2];
}
Flux(nv,k,j,i) *= HALF_F;
}
}
//6-- Compute maximum wave speed for this sweep
cMax(k,j,i) = cmax;
}
);
idfx::popRegion();
}
#endif // HYDRO_HDSOLVERS_ROEHD_HPP_