/*******************************************************************************
* 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 includes. */
#include "swift.h"
/* System includes. */
#include
#include
#include
#include
/**
* @brief Check that a and b are consistent (up to some relative 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-6f)
error("Values are inconsistent: %12.15e %12.15e rel=%e (%s)!", a, b,
fabsf(a - b) / fabsf(a + b), s);
}
/**
* @brief Check that the pre-defined adiabatic index constants contain correct
* values
*/
void check_constants(void) {
float val;
val = 0.5 * (hydro_gamma + 1.0f) / hydro_gamma;
check_value(val, hydro_gamma_plus_one_over_two_gamma, "(gamma+1)/(2 gamma)");
val = 0.5 * (hydro_gamma - 1.0f) / hydro_gamma;
check_value(val, hydro_gamma_minus_one_over_two_gamma, "(gamma-1)/(2 gamma)");
val = (hydro_gamma - 1.0f) / (hydro_gamma + 1.0f);
check_value(val, hydro_gamma_minus_one_over_gamma_plus_one,
"(gamma-1)/(gamma+1)");
val = 2.0f / (hydro_gamma + 1.0f);
check_value(val, hydro_two_over_gamma_plus_one, "2/(gamma+1)");
val = 2.0f / (hydro_gamma - 1.0f);
check_value(val, hydro_two_over_gamma_minus_one, "2/(gamma-1)");
val = 0.5f * (hydro_gamma - 1.0f);
check_value(val, hydro_gamma_minus_one_over_two, "(gamma-1)/2");
val = 2.0f * hydro_gamma / (hydro_gamma - 1.0f);
check_value(val, hydro_two_gamma_over_gamma_minus_one, "(2 gamma)/(gamma-1)");
val = 1.0f / hydro_gamma;
check_value(val, hydro_one_over_gamma, "1/gamma");
}
/**
* @brief Check that the adiabatic index power functions return the correct
* values
*/
void check_functions(float x) {
float val_a, val_b;
const double xx = x;
#if defined(HYDRO_GAMMA_5_3)
#define hydro_gamma_d (5. / 3.)
#elif defined(HYDRO_GAMMA_7_5)
#define hydro_gamma_d (7. / 5.)
#elif defined(HYDRO_GAMMA_4_3)
#define hydro_gamma_d (4. / 3.)
#elif defined(HYDRO_GAMMA_2_1)
#define hydro_gamma_d (2. / 1.)
#else
#error "Need to choose an adiabatic index!"
#endif
val_a = pow(xx, hydro_gamma_d);
val_b = pow_gamma(x);
check_value(val_a, val_b, "x^gamma");
val_a = pow(xx, hydro_gamma_d - 1.0);
val_b = pow_gamma_minus_one(x);
check_value(val_a, val_b, "x^(gamma - 1)");
val_a = pow(xx, -(hydro_gamma_d - 1.0));
val_b = pow_minus_gamma_minus_one(x);
check_value(val_a, val_b, "x^(-(gamma - 1))");
val_a = pow(xx, -hydro_gamma_d);
val_b = pow_minus_gamma(x);
check_value(val_a, val_b, "x^(-gamma)");
val_a = pow(xx, 2.0 / (hydro_gamma_d - 1.0));
val_b = pow_two_over_gamma_minus_one(x);
check_value(val_a, val_b, "x^(2/(gamma-1))");
val_a = pow(xx, 2.0 * hydro_gamma_d / (hydro_gamma_d - 1.0));
val_b = pow_two_gamma_over_gamma_minus_one(x);
check_value(val_a, val_b, "x^((2 gamma)/(gamma-1))");
val_a = pow(xx, (hydro_gamma_d - 1.0) / (2.0 * hydro_gamma_d));
val_b = pow_gamma_minus_one_over_two_gamma(x);
check_value(val_a, val_b, "x^((gamma-1)/(2 gamma))");
val_a = pow(xx, -(hydro_gamma_d + 1.0) / (2.0 * hydro_gamma_d));
val_b = pow_minus_gamma_plus_one_over_two_gamma(x);
check_value(val_a, val_b, "x^(-(gamma+1)/(2 gamma))");
val_a = pow(xx, 1.0 / hydro_gamma_d);
val_b = pow_one_over_gamma(x);
check_value(val_a, val_b, "x^(1/gamma)");
val_a = pow(xx, 3. * hydro_gamma_d - 2.);
val_b = pow_three_gamma_minus_two(x);
check_value(val_a, val_b, "x^(3gamma - 2)");
val_a = pow(xx, (3. * hydro_gamma_d - 5.) / 2.);
val_b = pow_three_gamma_minus_five_over_two(x);
check_value(val_a, val_b, "x^((3gamma - 5)/2)");
}
/**
* @brief Check adiabatic index constants and power functions
*/
int main(int argc, char* argv[]) {
/* Initialize CPU frequency, this also starts time. */
unsigned long long cpufreq = 0;
clocks_set_cpufreq(cpufreq);
/* Choke on FPEs */
#ifdef HAVE_FE_ENABLE_EXCEPT
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
message("Testing for gamma=%f", hydro_gamma);
/* Get some randomness going */
const int seed = time(NULL);
message("Seed = %d", seed);
srand(seed);
/* check the values of the adiabatic index constants */
check_constants();
for (int i = 0; i < 100; ++i) {
const float x = random_uniform(0., 100.);
message("Random test %d/100 (x=%e)", i, x);
/* check the adiabatic index power functions */
check_functions(x);
}
return 0;
}