/*******************************************************************************
* This file is part of SWIFT.
* Copyright (C) 2016 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 .
*
******************************************************************************/
#include
/* Local headers. */
#include
/* Local includes */
#include "error.h"
#include "riemann/riemann_trrs.h"
#include "tools.h"
int opposite(float a, float b) {
if ((a - b)) {
return fabs((a + b) / (a - b)) < 1.e-4;
} else {
return a == 0.0f;
}
}
int equal(float a, float b) {
if ((a + b)) {
return fabs((a - b) / (a + b)) < 1.e-4;
} else {
return a == 0.0f;
}
}
/**
* @brief Check that a and b are consistent (up to some error)
*
* @param a First value
* @param b Second value
* @param s String used to identify this check in messages
*/
void check_value(float a, float b, const char* s) {
if (fabsf(a - b) / fabsf(a + b) > 1.e-5f && fabsf(a - b) > 1.e-5f) {
error("Values are inconsistent: %g %g (%s)!", a, b, s);
} else {
message("Values are consistent: %g %g (%s).", a, b, s);
}
}
struct riemann_statevector {
/*! @brief Density */
float rho;
/*! @brief Fluid velocity */
float v;
/*! @brief Pressure */
float P;
};
/**
* @brief Check that the solution to the Riemann problem with given left and
* right state is consistent with the given expected solution
*
* @param WL Left state
* @param WR Right state
* @param Whalf Expected solution
* @param s String used to identify this check in messages
*/
void check_riemann_solution(struct riemann_statevector* WL,
struct riemann_statevector* WR,
struct riemann_statevector* Whalf, const char* s) {
float WLarr[5], WRarr[5], Whalfarr[5], n_unit[3];
n_unit[0] = 1.0f;
n_unit[1] = 0.0f;
n_unit[2] = 0.0f;
WLarr[0] = WL->rho;
WLarr[1] = WL->v;
WLarr[2] = 0.0f;
WLarr[3] = 0.0f;
WLarr[4] = WL->P;
WRarr[0] = WR->rho;
WRarr[1] = WR->v;
WRarr[2] = 0.0f;
WRarr[3] = 0.0f;
WRarr[4] = WR->P;
riemann_solver_solve(WLarr, WRarr, Whalfarr, n_unit);
message("Checking %s...", s);
check_value(Whalfarr[0], Whalf->rho, "rho");
check_value(Whalfarr[1], Whalf->v, "v");
check_value(Whalfarr[4], Whalf->P, "P");
}
/**
* @brief Check the TRRS Riemann solver on the Toro test problems
*/
void check_riemann_trrs(void) {
struct riemann_statevector WL, WR, Whalf;
/* Test 1 */
WL.rho = 1.0f;
WL.v = 0.0f;
WL.P = 1.0f;
WR.rho = 0.125f;
WR.v = 0.0f;
WR.P = 0.1f;
#if defined(HYDRO_GAMMA_5_3)
Whalf.rho = 0.481167f;
Whalf.v = 0.838085f;
Whalf.P = 0.295456f;
#elif defined(HYDRO_GAMMA_4_3)
Whalf.rho = 0.41586f;
Whalf.v = 0.942546f;
Whalf.P = 0.310406f;
#elif defined(HYDRO_GAMMA_2_1)
Whalf.rho = 0.53478f;
Whalf.v = 0.760037f;
Whalf.P = 0.285989f;
#else
#error "Unsupported adiabatic index!"
#endif
check_riemann_solution(&WL, &WR, &Whalf, "Test 1");
/* Test 2 */
WL.rho = 1.0f;
WL.v = -2.0f;
WL.P = 0.4f;
WR.rho = 1.0f;
WR.v = 2.0f;
WR.P = 0.4f;
#if defined(HYDRO_GAMMA_5_3)
Whalf.rho = 0.00617903f;
Whalf.v = 0.0f;
Whalf.P = 8.32249e-5f;
#elif defined(HYDRO_GAMMA_4_3)
Whalf.rho = 0.0257933f;
Whalf.v = 0.0f;
Whalf.P = 0.00304838f;
#elif defined(HYDRO_GAMMA_2_1)
Whalf.rho = 0.013932f;
Whalf.v = 0.0f;
Whalf.P = 7.76405e-5f;
#else
#error "Unsupported adiabatic index!"
#endif
check_riemann_solution(&WL, &WR, &Whalf, "Test 2");
/* Test 3 */
WL.rho = 1.0f;
WL.v = 0.0f;
WL.P = 1000.0f;
WR.rho = 1.0f;
WR.v = 0.0f;
WR.P = 0.01f;
#if defined(HYDRO_GAMMA_5_3)
Whalf.rho = 0.919498f;
Whalf.v = 3.37884f;
Whalf.P = 869.464f;
#elif defined(HYDRO_GAMMA_4_3)
Whalf.rho = 0.941258f;
Whalf.v = 2.19945f;
Whalf.P = 922.454f;
#elif defined(HYDRO_GAMMA_2_1)
Whalf.rho = 0.902032f;
Whalf.v = 4.49417f;
Whalf.P = 813.662f;
#else
#error "Unsupported adiabatic index!"
#endif
check_riemann_solution(&WL, &WR, &Whalf, "Test 3");
/* Test 4 */
WL.rho = 1.0f;
WL.v = 0.0f;
WL.P = 0.01f;
WR.rho = 1.0f;
WR.v = 0.0f;
WR.P = 100.0f;
#if defined(HYDRO_GAMMA_5_3)
Whalf.rho = 0.857525f;
Whalf.v = -1.93434f;
Whalf.P = 77.4007f;
#elif defined(HYDRO_GAMMA_4_3)
Whalf.rho = 0.880649f;
Whalf.v = -1.45215f;
Whalf.P = 84.4119f;
#elif defined(HYDRO_GAMMA_2_1)
Whalf.rho = 0.843058f;
Whalf.v = -2.31417f;
Whalf.P = 71.0747f;
#else
#error "Unsupported adiabatic index!"
#endif
check_riemann_solution(&WL, &WR, &Whalf, "Test 4");
/* Test 5 */
WL.rho = 5.99924f;
WL.v = 19.5975f;
WL.P = 460.894f;
WR.rho = 5.99242f;
WR.v = -6.19633f;
WR.P = 46.0950f;
#if defined(HYDRO_GAMMA_5_3)
Whalf.rho = 5.99924f;
Whalf.v = 19.5975f;
Whalf.P = 460.894f;
#elif defined(HYDRO_GAMMA_4_3)
Whalf.rho = 5.99924f;
Whalf.v = 19.5975f;
Whalf.P = 460.894f;
#elif defined(HYDRO_GAMMA_2_1)
Whalf.rho = 5.99924f;
Whalf.v = 19.5975f;
Whalf.P = 460.894f;
#else
#error "Unsupported adiabatic index!"
#endif
check_riemann_solution(&WL, &WR, &Whalf, "Test 5");
}
/**
* @brief Check the symmetry of the TRRS Riemann solver
*/
void check_riemann_symmetry(void) {
float WL[5], WR[5], Whalf1[5], Whalf2[5], n_unit1[3], n_unit2[3], n_norm,
vij[3], totflux1[5], totflux2[5];
WL[0] = random_uniform(0.1f, 1.0f);
WL[1] = random_uniform(-10.0f, 10.0f);
WL[2] = random_uniform(-10.0f, 10.0f);
WL[3] = random_uniform(-10.0f, 10.0f);
WL[4] = random_uniform(0.1f, 1.0f);
WR[0] = random_uniform(0.1f, 1.0f);
WR[1] = random_uniform(-10.0f, 10.0f);
WR[2] = random_uniform(-10.0f, 10.0f);
WR[3] = random_uniform(-10.0f, 10.0f);
WR[4] = random_uniform(0.1f, 1.0f);
n_unit1[0] = random_uniform(-1.0f, 1.0f);
n_unit1[1] = random_uniform(-1.0f, 1.0f);
n_unit1[2] = random_uniform(-1.0f, 1.0f);
n_norm = sqrtf(n_unit1[0] * n_unit1[0] + n_unit1[1] * n_unit1[1] +
n_unit1[2] * n_unit1[2]);
n_unit1[0] /= n_norm;
n_unit1[1] /= n_norm;
n_unit1[2] /= n_norm;
n_unit2[0] = -n_unit1[0];
n_unit2[1] = -n_unit1[1];
n_unit2[2] = -n_unit1[2];
riemann_solver_solve(WL, WR, Whalf1, n_unit1);
riemann_solver_solve(WR, WL, Whalf2, n_unit2);
if (!equal(Whalf1[0], Whalf2[0]) || !equal(Whalf1[1], Whalf2[1]) ||
!equal(Whalf1[2], Whalf2[2]) || !equal(Whalf1[3], Whalf2[3]) ||
!equal(Whalf1[4], Whalf2[4])) {
message(
"Solver asymmetric: [%.3e,%.3e,%.3e,%.3e,%.3e] == "
"[%.3e,%.3e,%.3e,%.3e,%.3e]\n",
Whalf1[0], Whalf1[1], Whalf1[2], Whalf1[3], Whalf1[4], Whalf2[0],
Whalf2[1], Whalf2[2], Whalf2[3], Whalf2[4]);
error("Asymmetry in solution!");
} else {
/* message( */
/* "Solver symmetric: [%.3e,%.3e,%.3e,%.3e,%.3e] == " */
/* "[%.3e,%.3e,%.3e,%.3e,%.3e]\n", */
/* Whalf1[0], Whalf1[1], Whalf1[2], Whalf1[3], Whalf1[4], Whalf2[0], */
/* Whalf2[1], Whalf2[2], Whalf2[3], Whalf2[4]); */
}
vij[0] = random_uniform(-10.0f, 10.0f);
vij[1] = random_uniform(-10.0f, 10.0f);
vij[2] = random_uniform(-10.0f, 10.0f);
riemann_solve_for_flux(WL, WR, n_unit1, vij, totflux1);
riemann_solve_for_flux(WR, WL, n_unit2, vij, totflux2);
if (!opposite(totflux1[0], totflux2[0]) ||
!opposite(totflux1[1], totflux2[1]) ||
!opposite(totflux1[2], totflux2[2]) ||
!opposite(totflux1[3], totflux2[3]) ||
!opposite(totflux1[4], totflux2[4])) {
message(
"Solver asymmetric: [%.3e,%.3e,%.3e,%.3e,%.3e] == "
"[%.3e,%.3e,%.3e,%.3e,%.3e]\n",
totflux1[0], totflux1[1], totflux1[2], totflux1[3], totflux1[4],
totflux2[0], totflux2[1], totflux2[2], totflux2[3], totflux2[4]);
error("Asymmetry in solution!");
} else {
/* message( */
/* "Solver symmetric: [%.3e,%.3e,%.3e,%.3e,%.3e] == " */
/* "[%.3e,%.3e,%.3e,%.3e,%.3e]\n", */
/* totflux1[0], totflux1[1], totflux1[2], totflux1[3], totflux1[4], */
/* totflux2[0], totflux2[1], totflux2[2], totflux2[3], totflux2[4]); */
}
}
/**
* @brief Check the TRRS Riemann solver
*/
int main(int argc, char* argv[]) {
/* check the TRRS Riemann solver */
check_riemann_trrs();
/* symmetry test */
int i;
for (i = 0; i < 100; i++) check_riemann_symmetry();
return 0;
}