/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2015 Bert Vandenbroucke (bert.vandenbroucke@ugent.be)
* 2018 Bert Vandenbroucke (bert.vandenbroucke@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
******************************************************************************/
#ifndef SWIFT_RIEMANN_TRRS_H
#define SWIFT_RIEMANN_TRRS_H
/* Some standard headers. */
#include
#include
#include
#include
/* Local headers. */
#include "adiabatic_index.h"
#include "error.h"
#include "minmax.h"
#include "riemann_checks.h"
#include "riemann_vacuum.h"
#ifndef EOS_IDEAL_GAS
#error \
"The TRRS Riemann solver currently only supports an ideal gas equation of state. Either select this equation of state, or try using another Riemann solver!"
#endif
/**
* @brief Solve the Riemann problem using the Two Rarefaction Riemann Solver
*
* By assuming 2 rarefaction waves, we can analytically solve for the pressure
* and velocity in the intermediate region, eliminating the iterative procedure.
*
* According to Toro: 'The two-rarefaction approximation is generally quite
* robust; (...) The TRRS is in fact exact when both non-linear waves are
* actually rarefaction waves.'
*
* @param WL The left state vector
* @param WR The right state vector
* @param Whalf Empty state vector in which the result will be stored
* @param n_unit Normal vector of the interface
*/
__attribute__((always_inline)) INLINE static void riemann_solver_solve(
const float* WL, const float* WR, float* Whalf, const float* n_unit) {
float aL, aR;
float PLR;
float vL, vR;
float ustar, pstar;
float vhalf;
float pdpR, SHR, STR;
float pdpL, SHL, STL;
/* calculate the velocities along the interface normal */
vL = WL[1] * n_unit[0] + WL[2] * n_unit[1] + WL[3] * n_unit[2];
vR = WR[1] * n_unit[0] + WR[2] * n_unit[1] + WR[3] * n_unit[2];
/* calculate the sound speeds */
aL = sqrtf(hydro_gamma * WL[4] / WL[0]);
aR = sqrtf(hydro_gamma * WR[4] / WR[0]);
if (riemann_is_vacuum(WL, WR, vL, vR, aL, aR)) {
riemann_solve_vacuum(WL, WR, vL, vR, aL, aR, Whalf, n_unit);
return;
}
/* calculate the velocity and pressure in the intermediate state */
PLR = pow_gamma_minus_one_over_two_gamma(WL[4] / WR[4]);
ustar = (PLR * vL / aL + vR / aR +
hydro_two_over_gamma_minus_one * (PLR - 1.0f)) /
(PLR / aL + 1.0f / aR);
pstar =
0.5f *
(WL[4] * pow_two_gamma_over_gamma_minus_one(
1.0f + hydro_gamma_minus_one_over_two / aL * (vL - ustar)) +
WR[4] * pow_two_gamma_over_gamma_minus_one(
1.0f + hydro_gamma_minus_one_over_two / aR * (ustar - vR)));
/* sample the solution */
if (ustar < 0.0f) {
/* right state */
Whalf[1] = WR[1];
Whalf[2] = WR[2];
Whalf[3] = WR[3];
pdpR = pstar / WR[4];
/* always a rarefaction wave, that's the approximation */
SHR = vR + aR;
if (SHR > 0.0f) {
STR = ustar + aR * pow_gamma_minus_one_over_two_gamma(pdpR);
if (STR <= 0.0f) {
Whalf[0] =
WR[0] * pow_two_over_gamma_minus_one(
hydro_two_over_gamma_plus_one -
hydro_gamma_minus_one_over_gamma_plus_one / aR * vR);
vhalf = hydro_two_over_gamma_plus_one *
(-aR + hydro_gamma_minus_one_over_two * vR) -
vR;
Whalf[4] =
WR[4] * pow_two_gamma_over_gamma_minus_one(
hydro_two_over_gamma_plus_one -
hydro_gamma_minus_one_over_gamma_plus_one / aR * vR);
} else {
Whalf[0] = WR[0] * pow_one_over_gamma(pdpR);
vhalf = ustar - vR;
Whalf[4] = pstar;
}
} else {
Whalf[0] = WR[0];
vhalf = 0.0f;
Whalf[4] = WR[4];
}
} else {
/* left state */
Whalf[1] = WL[1];
Whalf[2] = WL[2];
Whalf[3] = WL[3];
pdpL = pstar / WL[4];
/* rarefaction wave */
SHL = vL - aL;
if (SHL < 0.0f) {
STL = ustar - aL * pow_gamma_minus_one_over_two_gamma(pdpL);
if (STL > 0.0f) {
Whalf[0] =
WL[0] * pow_two_over_gamma_minus_one(
hydro_two_over_gamma_plus_one +
hydro_gamma_minus_one_over_gamma_plus_one / aL * vL);
vhalf = hydro_two_over_gamma_plus_one *
(aL + hydro_gamma_minus_one_over_two * vL) -
vL;
Whalf[4] =
WL[4] * pow_two_gamma_over_gamma_minus_one(
hydro_two_over_gamma_plus_one +
hydro_gamma_minus_one_over_gamma_plus_one / aL * vL);
} else {
Whalf[0] = WL[0] * pow_one_over_gamma(pdpL);
vhalf = ustar - vL;
Whalf[4] = pstar;
}
} else {
Whalf[0] = WL[0];
vhalf = 0.0f;
Whalf[4] = WL[4];
}
}
/* add the velocity solution along the interface normal to the velocities */
Whalf[1] += vhalf * n_unit[0];
Whalf[2] += vhalf * n_unit[1];
Whalf[3] += vhalf * n_unit[2];
}
__attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
const float* Wi, const float* Wj, const float* n_unit, const float* vij,
float* totflux) {
#ifdef SWIFT_DEBUG_CHECKS
riemann_check_input(Wi, Wj, n_unit, vij);
#endif
float Whalf[5];
float flux[5][3];
float vtot[3];
float rhoe;
riemann_solver_solve(Wi, Wj, Whalf, n_unit);
flux[0][0] = Whalf[0] * Whalf[1];
flux[0][1] = Whalf[0] * Whalf[2];
flux[0][2] = Whalf[0] * Whalf[3];
vtot[0] = Whalf[1] + vij[0];
vtot[1] = Whalf[2] + vij[1];
vtot[2] = Whalf[3] + vij[2];
flux[1][0] = Whalf[0] * vtot[0] * Whalf[1] + Whalf[4];
flux[1][1] = Whalf[0] * vtot[0] * Whalf[2];
flux[1][2] = Whalf[0] * vtot[0] * Whalf[3];
flux[2][0] = Whalf[0] * vtot[1] * Whalf[1];
flux[2][1] = Whalf[0] * vtot[1] * Whalf[2] + Whalf[4];
flux[2][2] = Whalf[0] * vtot[1] * Whalf[3];
flux[3][0] = Whalf[0] * vtot[2] * Whalf[1];
flux[3][1] = Whalf[0] * vtot[2] * Whalf[2];
flux[3][2] = Whalf[0] * vtot[2] * Whalf[3] + Whalf[4];
/* eqn. (15) */
/* F_P = \rho e ( \vec{v} - \vec{v_{ij}} ) + P \vec{v} */
/* \rho e = P / (\gamma-1) + 1/2 \rho \vec{v}^2 */
rhoe = Whalf[4] / hydro_gamma_minus_one +
0.5f * Whalf[0] *
(vtot[0] * vtot[0] + vtot[1] * vtot[1] + vtot[2] * vtot[2]);
flux[4][0] = rhoe * Whalf[1] + Whalf[4] * vtot[0];
flux[4][1] = rhoe * Whalf[2] + Whalf[4] * vtot[1];
flux[4][2] = rhoe * Whalf[3] + Whalf[4] * vtot[2];
totflux[0] =
flux[0][0] * n_unit[0] + flux[0][1] * n_unit[1] + flux[0][2] * n_unit[2];
totflux[1] =
flux[1][0] * n_unit[0] + flux[1][1] * n_unit[1] + flux[1][2] * n_unit[2];
totflux[2] =
flux[2][0] * n_unit[0] + flux[2][1] * n_unit[1] + flux[2][2] * n_unit[2];
totflux[3] =
flux[3][0] * n_unit[0] + flux[3][1] * n_unit[1] + flux[3][2] * n_unit[2];
totflux[4] =
flux[4][0] * n_unit[0] + flux[4][1] * n_unit[1] + flux[4][2] * n_unit[2];
#ifdef SWIFT_DEBUG_CHECKS
riemann_check_output(Wi, Wj, n_unit, vij, totflux);
#endif
}
__attribute__((always_inline)) INLINE static void
riemann_solve_for_middle_state_flux(const float* Wi, const float* Wj,
const float* n_unit, const float* vij,
float* totflux) {
#ifdef SWIFT_DEBUG_CHECKS
riemann_check_input(Wi, Wj, n_unit, vij);
#endif
if (Wi[0] == 0.0f || Wj[0] == 0.0f) {
totflux[0] = 0.0f;
totflux[1] = 0.0f;
totflux[2] = 0.0f;
totflux[3] = 0.0f;
totflux[4] = 0.0f;
return;
}
/* calculate the velocities along the interface normal */
const float vL = Wi[1] * n_unit[0] + Wi[2] * n_unit[1] + Wi[3] * n_unit[2];
const float vR = Wj[1] * n_unit[0] + Wj[2] * n_unit[1] + Wj[3] * n_unit[2];
/* calculate the sound speeds */
const float aL = sqrtf(hydro_gamma * Wi[4] / Wi[0]);
const float aR = sqrtf(hydro_gamma * Wj[4] / Wj[0]);
if (riemann_is_vacuum(Wi, Wj, vL, vR, aL, aR)) {
totflux[0] = 0.0f;
totflux[1] = 0.0f;
totflux[2] = 0.0f;
totflux[3] = 0.0f;
totflux[4] = 0.0f;
return;
}
/* calculate the velocity and pressure in the intermediate state */
const float PLR = pow_gamma_minus_one_over_two_gamma(Wi[4] / Wj[4]);
const float ustar = (PLR * vL / aL + vR / aR +
hydro_two_over_gamma_minus_one * (PLR - 1.0f)) /
(PLR / aL + 1.0f / aR);
const float pstar =
0.5f *
(Wi[4] * pow_two_gamma_over_gamma_minus_one(
1.0f + hydro_gamma_minus_one_over_two / aL * (vL - ustar)) +
Wj[4] * pow_two_gamma_over_gamma_minus_one(
1.0f + hydro_gamma_minus_one_over_two / aR * (ustar - vR)));
totflux[0] = 0.0f;
totflux[1] = pstar * n_unit[0];
totflux[2] = pstar * n_unit[1];
totflux[3] = pstar * n_unit[2];
const float vface =
vij[0] * n_unit[0] + vij[1] * n_unit[1] + vij[2] * n_unit[2];
totflux[4] = pstar * (ustar + vface);
#ifdef SWIFT_DEBUG_CHECKS
riemann_check_output(Wi, Wj, n_unit, vij, totflux);
#endif
}
#endif /* SWIFT_RIEMANN_TRRS_H */