/*******************************************************************************
* 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 .
*
******************************************************************************/
#ifndef SWIFT_GIZMO_SLOPE_LIMITER_FACE_H
#define SWIFT_GIZMO_SLOPE_LIMITER_FACE_H
/* Some standard headers. */
#include
/* Local headers. */
#include "minmax.h"
#include "sign.h"
/**
* @brief Slope limit a single quantity at the interface
*
* @param phi_i Value of the quantity at the particle position.
* @param phi_j Value of the quantity at the neighbouring particle position.
* @param phi_mid0 Extrapolated value of the quantity at the interface position.
* @param xij_norm Distance between the particle position and the interface
* position.
* @param r Distance between the particle and its neighbour.
* @return The slope limited difference between the quantity at the particle
* position and the quantity at the interface position.
*/
__attribute__((always_inline)) INLINE static float
hydro_slope_limit_face_quantity(float phi_i, float phi_j, float phi_mid0,
float xij_norm, float r_inv) {
const float psi1 = 0.5f;
const float psi2 = 0.25f;
const float delta1 = psi1 * fabsf(phi_i - phi_j);
const float delta2 = psi2 * fabsf(phi_i - phi_j);
const float phimin = min(phi_i, phi_j);
const float phimax = max(phi_i, phi_j);
const float phibar = phi_i + xij_norm * r_inv * (phi_j - phi_i);
float phiplus, phiminus, phi_mid;
if (same_signf(phimax + delta1, phimax)) {
phiplus = phimax + delta1;
} else {
phiplus =
(phimax != 0.0f) ? phimax / (1.0f + delta1 / fabsf(phimax)) : 0.0f;
}
if (same_signf(phimin - delta1, phimin)) {
phiminus = phimin - delta1;
} else {
phiminus =
(phimin != 0.0f) ? phimin / (1.0f + delta1 / fabsf(phimin)) : 0.0f;
}
if (phi_i < phi_j) {
const float temp = min(phibar + delta2, phi_mid0);
phi_mid = max(phiminus, temp);
} else {
const float temp = max(phibar - delta2, phi_mid0);
phi_mid = min(phiplus, temp);
}
return phi_mid - phi_i;
}
/**
* @brief Slope limit the slopes at the interface between two particles
*
* @param Wi Hydrodynamic variables of particle i.
* @param Wj Hydrodynamic variables of particle j.
* @param dWi Difference between the hydrodynamic variables of particle i at the
* position of particle i and at the interface position.
* @param dWj Difference between the hydrodynamic variables of particle j at the
* position of particle j and at the interface position.
* @param xij_i Relative position vector of the interface w.r.t. particle i.
* @param xij_j Relative position vector of the interface w.r.t. partilce j.
* @param r Distance between particle i and particle j.
*/
__attribute__((always_inline)) INLINE static void hydro_slope_limit_face(
float *Wi, float *Wj, float *dWi, float *dWj, const float *xij_i,
const float *xij_j, float r) {
const float xij_i_norm =
sqrtf(xij_i[0] * xij_i[0] + xij_i[1] * xij_i[1] + xij_i[2] * xij_i[2]);
const float xij_j_norm =
sqrtf(xij_j[0] * xij_j[0] + xij_j[1] * xij_j[1] + xij_j[2] * xij_j[2]);
const float r_inv = (r > 0.0f) ? 1.0f / r : 0.0f;
dWi[0] = hydro_slope_limit_face_quantity(Wi[0], Wj[0], Wi[0] + dWi[0],
xij_i_norm, r_inv);
dWi[1] = hydro_slope_limit_face_quantity(Wi[1], Wj[1], Wi[1] + dWi[1],
xij_i_norm, r_inv);
dWi[2] = hydro_slope_limit_face_quantity(Wi[2], Wj[2], Wi[2] + dWi[2],
xij_i_norm, r_inv);
dWi[3] = hydro_slope_limit_face_quantity(Wi[3], Wj[3], Wi[3] + dWi[3],
xij_i_norm, r_inv);
dWi[4] = hydro_slope_limit_face_quantity(Wi[4], Wj[4], Wi[4] + dWi[4],
xij_i_norm, r_inv);
dWj[0] = hydro_slope_limit_face_quantity(Wj[0], Wi[0], Wj[0] + dWj[0],
xij_j_norm, r_inv);
dWj[1] = hydro_slope_limit_face_quantity(Wj[1], Wi[1], Wj[1] + dWj[1],
xij_j_norm, r_inv);
dWj[2] = hydro_slope_limit_face_quantity(Wj[2], Wi[2], Wj[2] + dWj[2],
xij_j_norm, r_inv);
dWj[3] = hydro_slope_limit_face_quantity(Wj[3], Wi[3], Wj[3] + dWj[3],
xij_j_norm, r_inv);
dWj[4] = hydro_slope_limit_face_quantity(Wj[4], Wi[4], Wj[4] + dWj[4],
xij_j_norm, r_inv);
}
#endif /* SWIFT_GIZMO_SLOPE_LIMITER_FACE_H */