Skip to content
Snippets Groups Projects
Commit 5f04d794 authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Created all the files for the Pressure-Entropy SPH routines.

parent 66d6d525
No related branches found
No related tags found
1 merge request!252Implementation Pressure entropy SPH
......@@ -60,7 +60,8 @@
/* SPH variant to use */
//#define MINIMAL_SPH
#define GADGET2_SPH
//#define GADGET2_SPH
#define HOPKINS_PE_SPH
//#define DEFAULT_SPH
/* Self gravity stuff. */
......
......@@ -41,6 +41,8 @@
#include "./hydro/Minimal/hydro_debug.h"
#elif defined(GADGET2_SPH)
#include "./hydro/Gadget2/hydro_debug.h"
#elif defined(HOPKINS_PE_SPH)
#include "./hydro/PressureEntropy/hydro_debug.h"
#elif defined(DEFAULT_SPH)
#include "./hydro/Default/hydro_debug.h"
#else
......
......@@ -34,6 +34,10 @@
#include "./hydro/Gadget2/hydro.h"
#include "./hydro/Gadget2/hydro_iact.h"
#define SPH_IMPLEMENTATION "Gadget-2 version of SPH (Springel 2005)"
#elif defined(HOPKINS_PE_SPH)
#include "./hydro/PressureEntropy/hydro.h"
#include "./hydro/PressureEntropy/hydro_iact.h"
#define SPH_IMPLEMENTATION "Pressure-Entropy formulation of SPH (Hopkins 2013)"
#elif defined(DEFAULT_SPH)
#include "./hydro/Default/hydro.h"
#include "./hydro/Default/hydro_iact.h"
......
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_PRESSURE_ENTROPY_HYDRO_H
#define SWIFT_PRESSURE_ENTROPY_HYDRO_H
/**
* @file PressureEntropy/hydro_part.h
* @brief Pressure-Entropy implementation of SPH (Particle definition)
*
* The thermal variable is the entropy (S) and the entropy is smoothed over
* contact discontinuities to prevent spurious surface tension.
*
* Follows Hopkins, P., MNRAS, 2013, Volume 428, Issue 4, pp. 2840-2856
*/
#include "adiabatic_index.h"
#include "dimension.h"
#include "equation_of_state.h"
#include "hydro_properties.h"
#include "kernel_hydro.h"
/**
* @brief Returns the internal energy of a particle
*
* @param p The particle of interest
* @param dt Time since the last kick
*/
__attribute__((always_inline)) INLINE static float hydro_get_internal_energy(
const struct part *restrict p, float dt) {
const float entropy = p->entropy + p->entropy_dt * dt;
return gas_internal_energy_from_entropy(p->rho, entropy);
}
/**
* @brief Returns the pressure of a particle
*
* @param p The particle of interest
* @param dt Time since the last kick
*/
__attribute__((always_inline)) INLINE static float hydro_get_pressure(
const struct part *restrict p, float dt) {
const float entropy = p->entropy + p->entropy_dt * dt;
return gas_pressure_from_entropy(p->rho, entropy);
}
/**
* @brief Returns the entropy of a particle
*
* @param p The particle of interest
* @param dt Time since the last kick
*/
__attribute__((always_inline)) INLINE static float hydro_get_entropy(
const struct part *restrict p, float dt) {
return p->entropy + p->entropy_dt * dt;
}
/**
* @brief Returns the sound speed of a particle
*
* @param p The particle of interest
* @param dt Time since the last kick
*/
__attribute__((always_inline)) INLINE static float hydro_get_soundspeed(
const struct part *restrict p, float dt) {
return p->force.soundspeed;
}
/**
* @brief Modifies the thermal state of a particle to the imposed internal
* energy
*
* This overrides the current state of the particle but does *not* change its
* time-derivatives
*
* @param p The particle
* @param u The new internal energy
*/
__attribute__((always_inline)) INLINE static void hydro_set_internal_energy(
struct part *restrict p, float u) {
p->entropy = gas_entropy_from_internal_energy(p->rho, u);
}
/**
* @brief Modifies the thermal state of a particle to the imposed entropy
*
* This overrides the current state of the particle but does *not* change its
* time-derivatives
*
* @param p The particle
* @param S The new entropy
*/
__attribute__((always_inline)) INLINE static void hydro_set_entropy(
struct part *restrict p, float S) {
p->entropy = S;
}
/**
* @brief Computes the hydro time-step of a given particle
*
* @param p Pointer to the particle data
* @param xp Pointer to the extended particle data
*
*/
__attribute__((always_inline)) INLINE static float hydro_compute_timestep(
const struct part *restrict p, const struct xpart *restrict xp,
const struct hydro_props *restrict hydro_properties) {
const float CFL_condition = hydro_properties->CFL_condition;
/* CFL condition */
const float dt_cfl =
2.f * kernel_gamma * CFL_condition * p->h / p->force.v_sig;
return dt_cfl;
}
/**
* @brief Initialises the particles for the first time
*
* This function is called only once just after the ICs have been
* read in to do some conversions.
*
* @param p The particle to act upon
* @param xp The extended particle data to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_first_init_part(
struct part *restrict p, struct xpart *restrict xp) {
p->ti_begin = 0;
p->ti_end = 0;
xp->v_full[0] = p->v[0];
xp->v_full[1] = p->v[1];
xp->v_full[2] = p->v[2];
}
/**
* @brief Prepares a particle for the density calculation.
*
* Zeroes all the relevant arrays in preparation for the sums taking place in
* the variaous density tasks
*
* @param p The particle to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_init_part(
struct part *restrict p) {
p->density.wcount = 0.f;
p->density.wcount_dh = 0.f;
p->rho = 0.f;
p->rho_dh = 0.f;
p->density.div_v = 0.f;
p->density.rot_v[0] = 0.f;
p->density.rot_v[1] = 0.f;
p->density.rot_v[2] = 0.f;
}
/**
* @brief Finishes the density calculation.
*
* Multiplies the density and number of neighbours by the appropiate constants
* and add the self-contribution term.
*
* @param p The particle to act upon
* @param ti_current The current time (on the integer timeline)
*/
__attribute__((always_inline)) INLINE static void hydro_end_density(
struct part *restrict p, int ti_current) {
/* Some smoothing length multiples. */
const float h = p->h;
const float h_inv = 1.0f / h; /* 1/h */
const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */
const float h_inv_dim_plus_one = h_inv_dim * h_inv; /* 1/h^(d+1) */
/* Final operation on the density (add self-contribution). */
p->rho += p->mass * kernel_root;
p->rho_dh -= hydro_dimension * p->mass * kernel_root;
p->density.wcount += kernel_root;
/* Finish the calculation by inserting the missing h-factors */
p->rho *= h_inv_dim;
p->rho_dh *= h_inv_dim_plus_one;
p->density.wcount *= kernel_norm;
p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm;
const float irho = 1.f / p->rho;
/* Compute the derivative term */
p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh * irho);
/* Finish calculation of the velocity curl components */
p->density.rot_v[0] *= h_inv_dim_plus_one * irho;
p->density.rot_v[1] *= h_inv_dim_plus_one * irho;
p->density.rot_v[2] *= h_inv_dim_plus_one * irho;
/* Finish calculation of the velocity divergence */
p->density.div_v *= h_inv_dim_plus_one * irho;
}
/**
* @brief Prepare a particle for the force calculation.
*
* Computes viscosity term, conduction term and smoothing length gradient terms.
*
* @param p The particle to act upon
* @param xp The extended particle data to act upon
* @param ti_current The current time (on the timeline)
* @param timeBase The minimal time-step size
*/
__attribute__((always_inline)) INLINE static void hydro_prepare_force(
struct part *restrict p, struct xpart *restrict xp, int ti_current,
double timeBase) {
const float fac_mu = 1.f; /* Will change with cosmological integration */
/* Compute the norm of the curl */
const float curl_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] +
p->density.rot_v[1] * p->density.rot_v[1] +
p->density.rot_v[2] * p->density.rot_v[2]);
/* Compute the norm of div v */
const float abs_div_v = fabsf(p->density.div_v);
/* Compute the pressure */
const float half_dt = (ti_current - (p->ti_begin + p->ti_end) / 2) * timeBase;
const float pressure = hydro_get_pressure(p, half_dt);
const float irho = 1.f / p->rho;
/* Divide the pressure by the density and density gradient */
const float P_over_rho2 = pressure * irho * irho * p->rho_dh;
/* Compute the sound speed */
const float soundspeed = sqrtf(hydro_gamma * pressure * irho);
/* Compute the Balsara switch */
const float balsara =
abs_div_v / (abs_div_v + curl_v + 0.0001f * soundspeed / fac_mu / p->h);
/* Update variables. */
p->force.P_over_rho2 = P_over_rho2;
p->force.soundspeed = soundspeed;
p->force.balsara = balsara;
}
/**
* @brief Reset acceleration fields of a particle
*
* Resets all hydro acceleration and time derivative fields in preparation
* for the sums taking place in the variaous force tasks
*
* @param p The particle to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_reset_acceleration(
struct part *restrict p) {
/* Reset the acceleration. */
p->a_hydro[0] = 0.0f;
p->a_hydro[1] = 0.0f;
p->a_hydro[2] = 0.0f;
/* Reset the time derivatives. */
p->entropy_dt = 0.0f;
p->force.h_dt = 0.0f;
/* Reset maximal signal velocity */
p->force.v_sig = 0.0f;
}
/**
* @brief Predict additional particle fields forward in time when drifting
*
* @param p The particle
* @param xp The extended data of the particle
* @param t0 The time at the start of the drift
* @param t1 The time at the end of the drift
* @param timeBase The minimal time-step size
*/
__attribute__((always_inline)) INLINE static void hydro_predict_extra(
struct part *restrict p, const struct xpart *restrict xp, int t0, int t1,
double timeBase) {
/* Drift the pressure */
const float dt_entr = (t1 - (p->ti_begin + p->ti_end) / 2) * timeBase;
const float pressure = hydro_get_pressure(p, dt_entr);
const float irho = 1.f / p->rho;
/* Divide the pressure by the density and density gradient */
const float P_over_rho2 = pressure * irho * irho * p->rho_dh;
/* Compute the new sound speed */
const float soundspeed = sqrtf(hydro_gamma * pressure * irho);
/* Update variables */
p->force.P_over_rho2 = P_over_rho2;
p->force.soundspeed = soundspeed;
}
/**
* @brief Finishes the force calculation.
*
* Multiplies the forces and accelerationsby the appropiate constants
*
* @param p The particle to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_end_force(
struct part *restrict p) {
p->force.h_dt *= p->h * hydro_dimension_inv;
p->entropy_dt *=
0.5f * hydro_gamma_minus_one * pow_minus_gamma_minus_one(p->rho);
}
/**
* @brief Kick the additional variables
*
* @param p The particle to act upon
* @param xp The particle extended data to act upon
* @param dt The time-step for this kick
* @param half_dt The half time-step for this kick
*/
__attribute__((always_inline)) INLINE static void hydro_kick_extra(
struct part *restrict p, struct xpart *restrict xp, float dt,
float half_dt) {
/* Do not decrease the entropy (temperature) by more than a factor of 2*/
const float entropy_change = p->entropy_dt * dt;
if (entropy_change > -0.5f * p->entropy)
p->entropy += entropy_change;
else
p->entropy *= 0.5f;
/* Do not 'overcool' when timestep increases */
if (p->entropy + p->entropy_dt * half_dt < 0.5f * p->entropy)
p->entropy_dt = -0.5f * p->entropy / half_dt;
}
/**
* @brief Converts hydro quantity of a particle at the start of a run
*
* Requires the density to be known
*
* @param p The particle to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_convert_quantities(
struct part *restrict p) {
/* We read u in the entropy field. We now get S from u */
p->entropy = gas_entropy_from_internal_energy(p->rho, p->entropy);
}
#endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_H */
/*******************************************************************************
* This file is part of SWIFT.
* Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_PRESSURE_ENTROPY_HYDRO_DEBUG_H
#define SWIFT_PRESSURE_ENTROPY_HYDRO_DEBUG_H
/**
* @file PressureEntropy/hydro_debug.h
* @brief Pressure-Entropy implementation of SPH (Particle definition)
*
* The thermal variable is the entropy (S) and the entropy is smoothed over
* contact discontinuities to prevent spurious surface tension.
*
* Follows Hopkins, P., MNRAS, 2013, Volume 428, Issue 4, pp. 2840-2856
*/
__attribute__((always_inline)) INLINE static void hydro_debug_particle(
const struct part* p, const struct xpart* xp) {
printf(
"x=[%.3e,%.3e,%.3e], "
"v=[%.3e,%.3e,%.3e],v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e],\n "
"h=%.3e, wcount=%.3f, wcount_dh=%.3e, m=%.3e, dh_drho=%.3e, rho=%.3e, "
"P=%.3e, P_over_rho2=%.3e, S=%.3e, dS/dt=%.3e, c=%.3e\n"
"divV=%.3e, rotV=[%.3e,%.3e,%.3e], balsara=%.3e \n "
"v_sig=%e dh/dt=%.3e t_begin=%d, t_end=%d\n",
p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], xp->v_full[0],
xp->v_full[1], xp->v_full[2], p->a_hydro[0], p->a_hydro[1], p->a_hydro[2],
p->h, p->density.wcount, p->density.wcount_dh, p->mass, p->rho_dh, p->rho,
hydro_get_pressure(p, 0.), p->force.P_over_rho2, p->entropy,
p->entropy_dt, p->force.soundspeed, p->density.div_v, p->density.rot_v[0],
p->density.rot_v[1], p->density.rot_v[2], p->force.balsara,
p->force.v_sig, p->force.h_dt, p->ti_begin, p->ti_end);
}
#endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_DEBUG_H */
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_PRESSURE_ENTROPY_HYDRO_IACT_H
#define SWIFT_PRESSURE_ENTROPY_HYDRO_IACT_H
/**
* @file PressureEntropy/hydro_part.h
* @brief Pressure-Entropy implementation of SPH (Particle definition)
*
* The thermal variable is the entropy (S) and the entropy is smoothed over
* contact discontinuities to prevent spurious surface tension.
*
* Follows Hopkins, P., MNRAS, 2013, Volume 428, Issue 4, pp. 2840-2856
*/
/**
* @brief Density loop
*/
__attribute__((always_inline)) INLINE static void runner_iact_density(
float r2, float *dx, float hi, float hj, struct part *pi, struct part *pj) {
float wi, wi_dx;
float wj, wj_dx;
float dv[3], curlvr[3];
/* Get the masses. */
const float mi = pi->mass;
const float mj = pj->mass;
/* Get r and r inverse. */
const float r = sqrtf(r2);
const float r_inv = 1.0f / r;
/* Compute the kernel function for pi */
const float hi_inv = 1.f / hi;
const float ui = r * hi_inv;
kernel_deval(ui, &wi, &wi_dx);
/* Compute contribution to the density */
pi->rho += mj * wi;
pi->rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx);
/* Compute contribution to the number of neighbours */
pi->density.wcount += wi;
pi->density.wcount_dh -= ui * wi_dx;
/* Compute the kernel function for pj */
const float hj_inv = 1.f / hj;
const float uj = r * hj_inv;
kernel_deval(uj, &wj, &wj_dx);
/* Compute contribution to the density */
pj->rho += mi * wj;
pj->rho_dh -= mi * (hydro_dimension * wj + uj * wj_dx);
/* Compute contribution to the number of neighbours */
pj->density.wcount += wj;
pj->density.wcount_dh -= uj * wj_dx;
const float faci = mj * wi_dx * r_inv;
const float facj = mi * wj_dx * r_inv;
/* Compute dv dot r */
dv[0] = pi->v[0] - pj->v[0];
dv[1] = pi->v[1] - pj->v[1];
dv[2] = pi->v[2] - pj->v[2];
const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
pi->density.div_v -= faci * dvdr;
pj->density.div_v -= facj * dvdr;
/* Compute dv cross r */
curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1];
curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2];
curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0];
pi->density.rot_v[0] += faci * curlvr[0];
pi->density.rot_v[1] += faci * curlvr[1];
pi->density.rot_v[2] += faci * curlvr[2];
pj->density.rot_v[0] += facj * curlvr[0];
pj->density.rot_v[1] += facj * curlvr[1];
pj->density.rot_v[2] += facj * curlvr[2];
}
/**
* @brief Density loop (Vectorized version)
*/
__attribute__((always_inline)) INLINE static void runner_iact_vec_density(
float *R2, float *Dx, float *Hi, float *Hj, struct part **pi,
struct part **pj) {
error("Vectorized version of Pressure-Entropy SPH routine not existatn yet.");
}
/**
* @brief Density loop (non-symmetric version)
*/
__attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
float r2, float *dx, float hi, float hj, struct part *pi, struct part *pj) {
float wi, wi_dx;
float dv[3], curlvr[3];
/* Get the masses. */
const float mj = pj->mass;
/* Get r and r inverse. */
const float r = sqrtf(r2);
const float ri = 1.0f / r;
/* Compute the kernel function */
const float h_inv = 1.0f / hi;
const float u = r * h_inv;
kernel_deval(u, &wi, &wi_dx);
/* Compute contribution to the density */
pi->rho += mj * wi;
pi->rho_dh -= mj * (hydro_dimension * wi + u * wi_dx);
/* Compute contribution to the number of neighbours */
pi->density.wcount += wi;
pi->density.wcount_dh -= u * wi_dx;
const float fac = mj * wi_dx * ri;
/* Compute dv dot r */
dv[0] = pi->v[0] - pj->v[0];
dv[1] = pi->v[1] - pj->v[1];
dv[2] = pi->v[2] - pj->v[2];
const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
pi->density.div_v -= fac * dvdr;
/* Compute dv cross r */
curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1];
curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2];
curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0];
pi->density.rot_v[0] += fac * curlvr[0];
pi->density.rot_v[1] += fac * curlvr[1];
pi->density.rot_v[2] += fac * curlvr[2];
}
/**
* @brief Density loop (non-symmetric vectorized version)
*/
__attribute__((always_inline)) INLINE static void
runner_iact_nonsym_vec_density(float *R2, float *Dx, float *Hi, float *Hj,
struct part **pi, struct part **pj) {
error("Vectorized version of Pressure-Entropy SPH routine not existatn yet.");
}
/**
* @brief Force loop
*/
__attribute__((always_inline)) INLINE static void runner_iact_force(
float r2, float *dx, float hi, float hj, struct part *pi, struct part *pj) {
float wi, wj, wi_dx, wj_dx;
const float fac_mu = 1.f; /* Will change with cosmological integration */
const float r = sqrtf(r2);
const float r_inv = 1.0f / r;
/* Get some values in local variables. */
const float mi = pi->mass;
const float mj = pj->mass;
const float rhoi = pi->rho;
const float rhoj = pj->rho;
/* Get the kernel for hi. */
const float hi_inv = 1.0f / hi;
const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
const float ui = r * hi_inv;
kernel_deval(ui, &wi, &wi_dx);
const float wi_dr = hid_inv * wi_dx;
/* Get the kernel for hj. */
const float hj_inv = 1.0f / hj;
const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
const float xj = r * hj_inv;
kernel_deval(xj, &wj, &wj_dx);
const float wj_dr = hjd_inv * wj_dx;
/* Compute gradient terms */
const float P_over_rho2_i = pi->force.P_over_rho2;
const float P_over_rho2_j = pj->force.P_over_rho2;
/* Compute sound speeds */
const float ci = pi->force.soundspeed;
const float cj = pj->force.soundspeed;
/* Compute dv dot r. */
const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] +
(pi->v[1] - pj->v[1]) * dx[1] +
(pi->v[2] - pj->v[2]) * dx[2];
/* Balsara term */
const float balsara_i = pi->force.balsara;
const float balsara_j = pj->force.balsara;
/* Are the particles moving towards each others ? */
const float omega_ij = fminf(dvdr, 0.f);
const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
/* Signal velocity */
const float v_sig = ci + cj - 3.f * mu_ij;
/* Now construct the full viscosity term */
const float rho_ij = 0.5f * (rhoi + rhoj);
const float visc = -0.25f * const_viscosity_alpha * v_sig * mu_ij *
(balsara_i + balsara_j) / rho_ij;
/* Now, convolve with the kernel */
const float visc_term = 0.5f * visc * (wi_dr + wj_dr) * r_inv;
const float sph_term =
(P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv;
/* Eventually got the acceleration */
const float acc = visc_term + sph_term;
/* Use the force Luke ! */
pi->a_hydro[0] -= mj * acc * dx[0];
pi->a_hydro[1] -= mj * acc * dx[1];
pi->a_hydro[2] -= mj * acc * dx[2];
pj->a_hydro[0] += mi * acc * dx[0];
pj->a_hydro[1] += mi * acc * dx[1];
pj->a_hydro[2] += mi * acc * dx[2];
/* Get the time derivative for h. */
pi->force.h_dt -= mj * dvdr * r_inv / rhoj * wi_dr;
pj->force.h_dt -= mi * dvdr * r_inv / rhoi * wj_dr;
/* Update the signal velocity. */
pi->force.v_sig = fmaxf(pi->force.v_sig, v_sig);
pj->force.v_sig = fmaxf(pj->force.v_sig, v_sig);
/* Change in entropy */
pi->entropy_dt += mj * visc_term * dvdr;
pj->entropy_dt += mi * visc_term * dvdr;
}
/**
* @brief Force loop (Vectorized version)
*/
__attribute__((always_inline)) INLINE static void runner_iact_vec_force(
float *R2, float *Dx, float *Hi, float *Hj, struct part **pi,
struct part **pj) {
error("Vectorized version of Pressure-Entropy SPH routine not existatn yet.");
}
/**
* @brief Force loop (non-symmetric version)
*/
__attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
float r2, float *dx, float hi, float hj, struct part *pi, struct part *pj) {
float wi, wj, wi_dx, wj_dx;
const float fac_mu = 1.f; /* Will change with cosmological integration */
const float r = sqrtf(r2);
const float r_inv = 1.0f / r;
/* Get some values in local variables. */
// const float mi = pi->mass;
const float mj = pj->mass;
const float rhoi = pi->rho;
const float rhoj = pj->rho;
/* Get the kernel for hi. */
const float hi_inv = 1.0f / hi;
const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
const float ui = r * hi_inv;
kernel_deval(ui, &wi, &wi_dx);
const float wi_dr = hid_inv * wi_dx;
/* Get the kernel for hj. */
const float hj_inv = 1.0f / hj;
const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
const float xj = r * hj_inv;
kernel_deval(xj, &wj, &wj_dx);
const float wj_dr = hjd_inv * wj_dx;
/* Compute gradient terms */
const float P_over_rho2_i = pi->force.P_over_rho2;
const float P_over_rho2_j = pj->force.P_over_rho2;
/* Compute sound speeds */
const float ci = pi->force.soundspeed;
const float cj = pj->force.soundspeed;
/* Compute dv dot r. */
const float dvdr = (pi->v[0] - pj->v[0]) * dx[0] +
(pi->v[1] - pj->v[1]) * dx[1] +
(pi->v[2] - pj->v[2]) * dx[2];
/* Balsara term */
const float balsara_i = pi->force.balsara;
const float balsara_j = pj->force.balsara;
/* Are the particles moving towards each others ? */
const float omega_ij = fminf(dvdr, 0.f);
const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
/* Signal velocity */
const float v_sig = ci + cj - 3.f * mu_ij;
/* Now construct the full viscosity term */
const float rho_ij = 0.5f * (rhoi + rhoj);
const float visc = -0.25f * const_viscosity_alpha * v_sig * mu_ij *
(balsara_i + balsara_j) / rho_ij;
/* Now, convolve with the kernel */
const float visc_term = 0.5f * visc * (wi_dr + wj_dr) * r_inv;
const float sph_term =
(P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv;
/* Eventually got the acceleration */
const float acc = visc_term + sph_term;
/* Use the force Luke ! */
pi->a_hydro[0] -= mj * acc * dx[0];
pi->a_hydro[1] -= mj * acc * dx[1];
pi->a_hydro[2] -= mj * acc * dx[2];
/* Get the time derivative for h. */
pi->force.h_dt -= mj * dvdr * r_inv / rhoj * wi_dr;
/* Update the signal velocity. */
pi->force.v_sig = fmaxf(pi->force.v_sig, v_sig);
/* Change in entropy */
pi->entropy_dt += mj * visc_term * dvdr;
}
/**
* @brief Force loop (Vectorized non-symmetric version)
*/
__attribute__((always_inline)) INLINE static void runner_iact_nonsym_vec_force(
float *R2, float *Dx, float *Hi, float *Hj, struct part **pi,
struct part **pj) {
error("Vectorized version of Pressure-Entropy SPH routine not existatn yet.");
}
#endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_IACT_H */
/*******************************************************************************
* This file is part of SWIFT.
* Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_PRESSURE_ENTROPY_HYDRO_IO_H
#define SWIFT_PRESSURE_ENTROPY_HYDRO_IO_H
/**
* @file PressureEntropy/hydro_io.h
* @brief Pressure-Entropy implementation of SPH (Particle definition)
*
* The thermal variable is the entropy (S) and the entropy is smoothed over
* contact discontinuities to prevent spurious surface tension.
*
* Follows Hopkins, P., MNRAS, 2013, Volume 428, Issue 4, pp. 2840-2856
*/
#include "adiabatic_index.h"
#include "hydro.h"
#include "io_properties.h"
#include "kernel_hydro.h"
/**
* @brief Specifies which particle fields to read from a dataset
*
* @param parts The particle array.
* @param list The list of i/o properties to read.
* @param num_fields The number of i/o fields to read.
*/
void hydro_read_particles(struct part* parts, struct io_props* list,
int* num_fields) {
*num_fields = 8;
/* List what we want to read */
list[0] = io_make_input_field("Coordinates", DOUBLE, 3, COMPULSORY,
UNIT_CONV_LENGTH, parts, x);
list[1] = io_make_input_field("Velocities", FLOAT, 3, COMPULSORY,
UNIT_CONV_SPEED, parts, v);
list[2] = io_make_input_field("Masses", FLOAT, 1, COMPULSORY, UNIT_CONV_MASS,
parts, mass);
list[3] = io_make_input_field("SmoothingLength", FLOAT, 1, COMPULSORY,
UNIT_CONV_LENGTH, parts, h);
list[4] = io_make_input_field("InternalEnergy", FLOAT, 1, COMPULSORY,
UNIT_CONV_ENERGY_PER_UNIT_MASS, parts, entropy);
list[5] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY,
UNIT_CONV_NO_UNITS, parts, id);
list[6] = io_make_input_field("Accelerations", FLOAT, 3, OPTIONAL,
UNIT_CONV_ACCELERATION, parts, a_hydro);
list[7] = io_make_input_field("Density", FLOAT, 1, OPTIONAL,
UNIT_CONV_DENSITY, parts, rho);
}
float convert_u(struct engine* e, struct part* p) {
return hydro_get_internal_energy(p, 0);
}
float convert_P(struct engine* e, struct part* p) {
return hydro_get_pressure(p, 0);
}
/**
* @brief Specifies which particle fields to write to a dataset
*
* @param parts The particle array.
* @param list The list of i/o properties to write.
* @param num_fields The number of i/o fields to write.
*/
void hydro_write_particles(struct part* parts, struct io_props* list,
int* num_fields) {
*num_fields = 10;
/* List what we want to write */
list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH,
parts, x);
list[1] =
io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
list[2] =
io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass);
list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
parts, h);
list[4] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1,
UNIT_CONV_ENERGY_PER_UNIT_MASS,
parts, entropy, convert_u);
list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
UNIT_CONV_NO_UNITS, parts, id);
list[6] = io_make_output_field("Acceleration", FLOAT, 3,
UNIT_CONV_ACCELERATION, parts, a_hydro);
list[7] =
io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
list[8] = io_make_output_field("Entropy", FLOAT, 1,
UNIT_CONV_ENTROPY_PER_UNIT_MASS, parts, rho);
list[9] = io_make_output_field_convert_part(
"Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, rho, convert_P);
}
/**
* @brief Writes the current model of SPH to the file
* @param h_grpsph The HDF5 group in which to write
*/
void writeSPHflavour(hid_t h_grpsph) {
/* Viscosity and thermal conduction */
/* Nothing in this minimal model... */
writeAttribute_s(h_grpsph, "Thermal Conductivity Model", "No treatment");
writeAttribute_s(h_grpsph, "Viscosity Model",
"Minimal treatment as in Monaghan (1992)");
/* Time integration properties */
writeAttribute_f(h_grpsph, "Maximal Delta u change over dt",
const_max_u_change);
}
/**
* @brief Are we writing entropy in the internal energy field ?
*
* @return 1 if entropy is in 'internal energy', 0 otherwise.
*/
int writeEntropyFlag() { return 0; }
#endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_IO_H */
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef SWIFT_PRESSURE_ENTROPY_HYDRO_PART_H
#define SWIFT_PRESSURE_ENTROPY_HYDRO_PART_H
/**
* @file PressureEntropy/hydro_part.h
* @brief Pressure-Entropy implementation of SPH (Particle definition)
*
* The thermal variable is the entropy (S) and the entropy is smoothed over
* contact discontinuities to prevent spurious surface tension.
*
* Follows Hopkins, P., MNRAS, 2013, Volume 428, Issue 4, pp. 2840-2856
*/
/* Extra particle data not needed during the SPH loops over neighbours. */
struct xpart {
/* Offset between current position and position at last tree rebuild. */
float x_diff[3];
/* Velocity at the last full step. */
float v_full[3];
} __attribute__((aligned(xpart_align)));
/* Data of a single particle. */
struct part {
/* Particle position. */
double x[3];
/* Particle predicted velocity. */
float v[3];
/* Particle acceleration. */
float a_hydro[3];
/* Particle cutoff radius. */
float h;
/* Particle mass. */
float mass;
/* Particle time of beginning of time-step. */
int ti_begin;
/* Particle time of end of time-step. */
int ti_end;
/* Particle density. */
float rho;
/* Particle entropy. */
float entropy;
/* Entropy time derivative */
float entropy_dt;
/* Derivative of the density with respect to smoothing length. */
float rho_dh;
union {
struct {
/* Number of neighbours. */
float wcount;
/* Number of neighbours spatial derivative. */
float wcount_dh;
/* Particle velocity curl. */
float rot_v[3];
/* Particle velocity divergence. */
float div_v;
} density;
struct {
/* Balsara switch */
float balsara;
/* Pressure over density squared (including drho/dh term) */
float P_over_rho2;
/* Particle sound speed. */
float soundspeed;
/* Signal velocity. */
float v_sig;
/* Time derivative of the smoothing length */
float h_dt;
} force;
};
/* Particle ID. */
long long id;
/* Pointer to corresponding gravity part. */
struct gpart* gpart;
} __attribute__((aligned(part_align)));
#endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_PART_H */
......@@ -26,6 +26,8 @@
#include "./hydro/Minimal/hydro_io.h"
#elif defined(GADGET2_SPH)
#include "./hydro/Gadget2/hydro_io.h"
#elif defined(HOPKINS_PE_SPH)
#include "./hydro/PressureEntropy/hydro_io.h"
#elif defined(DEFAULT_SPH)
#include "./hydro/Default/hydro_io.h"
#else
......
......@@ -43,6 +43,8 @@
#include "./hydro/Minimal/hydro_part.h"
#elif defined(GADGET2_SPH)
#include "./hydro/Gadget2/hydro_part.h"
#elif defined(HOPKINS_PE_SPH)
#include "./hydro/PressureEntropy/hydro_part.h"
#elif defined(DEFAULT_SPH)
#include "./hydro/Default/hydro_part.h"
#else
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment