/*******************************************************************************
* 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_SHADOWSWIFT_HYDRO_H
#define SWIFT_SHADOWSWIFT_HYDRO_H
#include "adiabatic_index.h"
#include "approx_math.h"
#include "cosmology.h"
#include "entropy_floor.h"
#include "equation_of_state.h"
#include "hydro_gradients.h"
#include "hydro_properties.h"
#include "hydro_space.h"
#include "pressure_floor.h"
#include "voronoi_algorithm.h"
#include
/**
* @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.
* @param hydro_properties Pointer to the hydro parameters.
*/
__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 struct cosmology* restrict cosmo) {
const float CFL_condition = hydro_properties->CFL_condition;
float vrel[3];
vrel[0] = p->primitives.v[0] - xp->v_full[0];
vrel[1] = p->primitives.v[1] - xp->v_full[1];
vrel[2] = p->primitives.v[2] - xp->v_full[2];
float vmax =
sqrtf(vrel[0] * vrel[0] + vrel[1] * vrel[1] + vrel[2] * vrel[2]) +
sqrtf(hydro_gamma * p->primitives.P / p->primitives.rho);
vmax = max(vmax, p->timestepvars.vmax);
const float psize =
cosmo->a *
powf(p->cell.volume / hydro_dimension_unit_sphere, hydro_dimension_inv);
float dt = FLT_MAX;
if (vmax > 0.) {
dt = psize / vmax;
}
return CFL_condition * dt;
}
/**
* @brief Does some extra hydro operations once the actual physical time step
* for the particle is known.
*
* We use this to store the physical time step, since it is used for the flux
* exchange during the force loop.
*
* We also set the active flag of the particle to inactive. It will be set to
* active in hydro_init_part, which is called the next time the particle becomes
* active.
*
* @param p The particle to act upon.
* @param dt Physical time step of the particle during the next step.
*/
__attribute__((always_inline)) INLINE static void hydro_timestep_extra(
struct part* p, float dt) {
p->force.dt = dt;
p->force.active = 0;
}
/**
* @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.
*
* In this case, we copy the particle velocities into the corresponding
* primitive variable field. We do this because the particle velocities in GIZMO
* can be independent of the actual fluid velocity. The latter is stored as a
* primitive variable and integrated using the linear momentum, a conserved
* variable.
*
* @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* p, struct xpart* xp) {
const float mass = p->conserved.mass;
p->time_bin = 0;
p->primitives.v[0] = p->v[0];
p->primitives.v[1] = p->v[1];
p->primitives.v[2] = p->v[2];
p->conserved.momentum[0] = mass * p->primitives.v[0];
p->conserved.momentum[1] = mass * p->primitives.v[1];
p->conserved.momentum[2] = mass * p->primitives.v[2];
#ifdef EOS_ISOTHERMAL_GAS
p->conserved.energy = mass * gas_internal_energy_from_entropy(0.f, 0.f);
#else
p->conserved.energy *= mass;
#endif
#ifdef SHADOWFAX_TOTAL_ENERGY
p->conserved.energy += 0.5f * (p->conserved.momentum[0] * p->primitives.v[0] +
p->conserved.momentum[1] * p->primitives.v[1] +
p->conserved.momentum[2] * p->primitives.v[2]);
#endif
#if defined(SHADOWFAX_FIX_CELLS)
p->v[0] = 0.;
p->v[1] = 0.;
p->v[2] = 0.;
#else
p->v[0] = p->primitives.v[0];
p->v[1] = p->primitives.v[1];
p->v[2] = p->primitives.v[2];
#endif
/* set the initial velocity of the cells */
xp->v_full[0] = p->v[0];
xp->v_full[1] = p->v[1];
xp->v_full[2] = p->v[2];
/* ignore accelerations present in the initial condition */
p->a_hydro[0] = 0.0f;
p->a_hydro[1] = 0.0f;
p->a_hydro[2] = 0.0f;
}
/**
* @brief Prepares a particle for the volume calculation.
*
* Simply makes sure all necessary variables are initialized to zero.
* Initializes the Voronoi cell.
*
* @param p The particle to act upon
* @param hs #hydro_space containing extra information about the space.
*/
__attribute__((always_inline)) INLINE static void hydro_init_part(
struct part* p, const struct hydro_space* hs) {
/* make sure we don't enter the no neighbour case in runner.c */
p->density.wcount = 1.0f;
p->density.wcount_dh = 0.0f;
voronoi_cell_init(&p->cell, p->x, hs->anchor, hs->side);
/* Set the active flag to active. */
p->force.active = 1;
}
/**
* @brief Finishes the volume calculation.
*
* Calls the finalize method on the Voronoi cell, which calculates the volume
* and centroid of the cell. We use the return value of this function to set
* a new value for the smoothing length and possibly force another iteration
* of the volume calculation for this particle. We then use the volume to
* convert conserved variables into primitive variables.
*
* This method also initializes the gradient variables (if gradients are used).
*
* @param p The particle to act upon.
*/
__attribute__((always_inline)) INLINE static void hydro_end_density(
struct part* restrict p, const struct cosmology* cosmo) {
float volume;
float m, momentum[3], energy;
hydro_gradients_init(p);
float hnew = voronoi_cell_finalize(&p->cell);
/* Enforce hnew as new smoothing length in the iteration
This is annoyingly difficult, as we do not have access to the variables
that govern the loop...
So here's an idea: let's force in some method somewhere that makes sure
r->e->hydro_properties->target_neighbours is 1, and
r->e->hydro_properties->delta_neighbours is 0.
This way, we can accept an iteration by setting p->density.wcount to 1.
To get the right correction for h, we set wcount to something else
(say 0), and then set p->density.wcount_dh to 1/(hnew-h). */
if (hnew < p->h) {
/* Iteration succesful: we accept, but manually set h to a smaller value
for the next time step */
const float hinvdim = pow_dimension(1.0f / p->h);
p->density.wcount = hinvdim;
p->h = 1.1f * hnew;
} else {
/* Iteration not succesful: we force h to become 1.1*hnew */
p->density.wcount = 0.0f;
p->density.wcount_dh = p->h / (1.1f * hnew - p->h);
return;
}
volume = p->cell.volume;
#ifdef SWIFT_DEBUG_CHECKS
/* the last condition checks for NaN: a NaN value always evaluates to false,
even when checked against itself */
if (volume == 0. || volume == INFINITY || volume != volume) {
error("Invalid value for cell volume (%g)!", volume);
}
#endif
/* compute primitive variables */
/* eqns (3)-(5) */
m = p->conserved.mass;
if (m > 0.) {
momentum[0] = p->conserved.momentum[0];
momentum[1] = p->conserved.momentum[1];
momentum[2] = p->conserved.momentum[2];
p->primitives.rho = m / volume;
p->primitives.v[0] = momentum[0] / m;
p->primitives.v[1] = momentum[1] / m;
p->primitives.v[2] = momentum[2] / m;
energy = p->conserved.energy;
#ifdef SHADOWFAX_TOTAL_ENERGY
energy -= 0.5f * (momentum[0] * p->primitives.v[0] +
momentum[1] * p->primitives.v[1] +
momentum[2] * p->primitives.v[2]);
#endif
energy /= m;
p->primitives.P =
gas_pressure_from_internal_energy(p->primitives.rho, energy);
} else {
p->primitives.rho = 0.;
p->primitives.v[0] = 0.;
p->primitives.v[1] = 0.;
p->primitives.v[2] = 0.;
p->primitives.P = 0.;
}
#ifdef SWIFT_DEBUG_CHECKS
if (p->primitives.rho < 0.) {
error("Negative density!");
}
if (p->primitives.P < 0.) {
error("Negative pressure!");
}
#endif
}
/**
* @brief Sets all particle fields to sensible values when the #part has 0 ngbs.
*
* @param p The particle to act upon
* @param xp The extended particle data to act upon
*/
__attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours(
struct part* restrict p, struct xpart* restrict xp,
const struct cosmology* cosmo) {
/* 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 */
/* Re-set problematic values */
p->density.wcount = kernel_root * h_inv_dim;
p->density.wcount_dh = 0.f;
}
/**
* @brief Prepare a particle for the force calculation.
*
* This function is called in the ghost task to convert some quantities coming
* from the density loop over neighbours into quantities ready to be used in the
* force loop over neighbours. Quantities are typically read from the density
* sub-structure and written to the force sub-structure.
* Examples of calculations done here include the calculation of viscosity term
* constants, thermal conduction terms, hydro conversions, etc.
*
* @param p The particle to act upon
* @param xp The extended particle data to act upon
* @param cosmo The current cosmological model.
* @param hydro_props Hydrodynamic properties.
* @param dt_alpha The time-step used to evolve non-cosmological quantities such
* as the artificial viscosity.
* @param dt_therm The time-step used to evolve hydrodynamical quantities.
*/
__attribute__((always_inline)) INLINE static void hydro_prepare_force(
struct part* restrict p, struct xpart* restrict xp,
const struct cosmology* cosmo, const struct hydro_props* hydro_props,
const struct pressure_floor_props* pressure_floor, const float dt_alpha,
const float dt_therm) {
/* Initialize time step criterion variables */
p->timestepvars.vmax = 0.0f;
/* Set the actual velocity of the particle */
p->force.v_full[0] = xp->v_full[0];
p->force.v_full[1] = xp->v_full[1];
p->force.v_full[2] = xp->v_full[2];
p->conserved.flux.mass = 0.0f;
p->conserved.flux.momentum[0] = 0.0f;
p->conserved.flux.momentum[1] = 0.0f;
p->conserved.flux.momentum[2] = 0.0f;
p->conserved.flux.energy = 0.0f;
}
/**
* @brief Prepare a particle for the gradient calculation.
*
* This function is called after the density loop and before the gradient loop.
*
* We use it to set the physical timestep for the particle and to copy the
* actual velocities, which we need to boost our interfaces during the flux
* calculation. We also initialize the variables used for the time step
* calculation.
*
* @param p The particle to act upon.
* @param xp The extended particle data to act upon.
* @param cosmo The cosmological model.
* @param hydro_props Hydrodynamic properties.
*/
__attribute__((always_inline)) INLINE static void hydro_prepare_gradient(
struct part* restrict p, struct xpart* restrict xp,
const struct cosmology* cosmo, const struct hydro_props* hydro_props,
const struct pressure_floor_props* pressure_floor) {
/* Initialize time step criterion variables */
p->timestepvars.vmax = 0.;
}
/**
* @brief Resets the variables that are required for a gradient calculation.
*
* This function is called after hydro_prepare_gradient.
*
* @param p The particle to act upon.
* @param xp The extended particle data to act upon.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static void hydro_reset_gradient(
struct part* restrict p) {}
/**
* @brief Finishes the gradient calculation.
*
* Just a wrapper around hydro_gradients_finalize, which can be an empty method,
* in which case no gradients are used.
*
* @param p The particle to act upon.
*/
__attribute__((always_inline)) INLINE static void hydro_end_gradient(
struct part* p) {
hydro_gradients_finalize(p);
}
/**
* @brief Reset acceleration fields of a particle
*
* This is actually not necessary for Shadowswift, since we just set the
* accelerations after the flux calculation.
*
* @param p The particle to act upon.
*/
__attribute__((always_inline)) INLINE static void hydro_reset_acceleration(
struct part* 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->force.h_dt = 0.0f;
}
/**
* @brief Sets the values to be predicted in the drifts to their values at a
* kick time
*
* @param p The particle.
* @param xp The extended data of this particle.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
struct part* restrict p, const struct xpart* restrict xp,
const struct cosmology* cosmo,
const struct pressure_floor_props* pressure_floor) {}
/**
* @brief Converts the hydrodynamic variables from the initial condition file to
* conserved variables that can be used during the integration
*
* Requires the volume to be known.
*
* The initial condition file contains a mixture of primitive and conserved
* variables. Mass is a conserved variable, and we just copy the particle
* mass into the corresponding conserved quantity. We need the volume to
* also derive a density, which is then used to convert the internal energy
* to a pressure. However, we do not actually use these variables anymore.
* We do need to initialize the linear momentum, based on the mass and the
* velocity of the particle.
*
* @param p The particle to act upon.
* @param xp The extended particle data to act upon.
*/
__attribute__((always_inline)) INLINE static void hydro_convert_quantities(
struct part* p, struct xpart* xp, const struct cosmology* cosmo,
const struct hydro_props* hydro_props,
const struct pressure_floor_props* pressure_floor) {}
/**
* @brief Extra operations to be done during the drift
*
* Not used for Shadowswift.
*
* @param p Particle to act upon.
* @param xp The extended particle data to act upon.
* @param dt The drift time-step.
*/
__attribute__((always_inline)) INLINE static void hydro_predict_extra(
struct part* p, struct xpart* xp, float dt_drift, float dt_therm,
float dt_kick_grav, const struct cosmology* cosmo,
const struct hydro_props* hydro_props,
const struct entropy_floor_properties* floor_props,
const struct pressure_floor_props* pressure_floor) {}
/**
* @brief Set the particle acceleration after the flux loop.
*
* @param p Particle to act upon.
*/
__attribute__((always_inline)) INLINE static void hydro_end_force(
struct part* p, const struct cosmology* cosmo) {}
/**
* @brief Extra operations done during the kick
*
* Not used for Shadowswift.
*
* @param p Particle to act upon.
* @param xp Extended particle data to act upon.
* @param dt Physical time step.
*/
__attribute__((always_inline)) INLINE static void hydro_kick_extra(
struct part* p, struct xpart* xp, float dt, float dt_grav,
float dt_grav_mesh, float dt_hydro, float dt_kick_corr,
const struct cosmology* cosmo, const struct hydro_props* hydro_props,
const struct entropy_floor_properties* floor_props) {
/* Update the conserved variables. We do this here and not in the kick,
since we need the updated variables below. */
p->conserved.mass += p->conserved.flux.mass * dt;
p->conserved.momentum[0] += p->conserved.flux.momentum[0] * dt;
p->conserved.momentum[1] += p->conserved.flux.momentum[1] * dt;
p->conserved.momentum[2] += p->conserved.flux.momentum[2] * dt;
#ifdef EOS_ISOTHERMAL_GAS
/* reset the thermal energy */
p->conserved.energy =
p->conserved.mass * gas_internal_energy_from_entropy(0.f, 0.f);
#else
p->conserved.energy += p->conserved.flux.energy * dt;
#endif
#if defined(SHADOWFAX_FIX_CELLS)
p->v[0] = 0.0f;
p->v[1] = 0.0f;
p->v[2] = 0.0f;
#else
if (p->conserved.mass > 0.0f && p->primitives.rho > 0.0f) {
const float inverse_mass = 1.f / p->conserved.mass;
/* Normal case: set particle velocity to fluid velocity. */
p->v[0] = p->conserved.momentum[0] * inverse_mass;
p->v[1] = p->conserved.momentum[1] * inverse_mass;
p->v[2] = p->conserved.momentum[2] * inverse_mass;
#ifdef SHADOWFAX_STEER_CELL_MOTION
float centroid[3], d[3];
float volume, csnd, R, vfac, fac, dnrm;
voronoi_get_centroid(&p->cell, centroid);
d[0] = centroid[0] - p->x[0];
d[1] = centroid[1] - p->x[1];
d[2] = centroid[2] - p->x[2];
dnrm = sqrtf(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
csnd = sqrtf(hydro_gamma * p->primitives.P / p->primitives.rho);
volume = p->cell.volume;
R = get_radius_dimension_sphere(volume);
fac = 4.0f * dnrm / R;
if (fac > 0.9f) {
if (fac < 1.1f) {
vfac = csnd * (dnrm - 0.225f * R) / dnrm / (0.05f * R);
} else {
vfac = csnd / dnrm;
}
p->v[0] += vfac * d[0];
p->v[1] += vfac * d[1];
p->v[2] += vfac * d[2];
}
#endif
} else {
p->v[0] = 0.;
p->v[1] = 0.;
p->v[2] = 0.;
}
#endif
/* Now make sure all velocity variables are up to date. */
xp->v_full[0] = p->v[0];
xp->v_full[1] = p->v[1];
xp->v_full[2] = p->v[2];
if (p->gpart) {
p->gpart->v_full[0] = p->v[0];
p->gpart->v_full[1] = p->v[1];
p->gpart->v_full[2] = p->v[2];
}
}
/**
* @brief Returns the internal energy of a particle
*
* @param p The particle of interest.
* @return Internal energy of the particle.
*/
__attribute__((always_inline)) INLINE static float hydro_get_internal_energy(
const struct part* restrict p) {
if (p->primitives.rho > 0.) {
return gas_internal_energy_from_pressure(p->primitives.rho,
p->primitives.P);
} else {
return 0.;
}
}
/**
* @brief Returns the entropy of a particle
*
* @param p The particle of interest.
* @return Entropy of the particle.
*/
__attribute__((always_inline)) INLINE static float hydro_get_entropy(
const struct part* restrict p) {
if (p->primitives.rho > 0.) {
return gas_entropy_from_pressure(p->primitives.rho, p->primitives.P);
} else {
return 0.;
}
}
/**
* @brief Returns the sound speed of a particle
*
* @param p The particle of interest.
* @param Sound speed of the particle.
*/
__attribute__((always_inline)) INLINE static float hydro_get_soundspeed(
const struct part* restrict p) {
if (p->primitives.rho > 0.) {
return gas_soundspeed_from_pressure(p->primitives.rho, p->primitives.P);
} else {
return 0.;
}
}
/**
* @brief Returns the pressure of a particle
*
* @param p The particle of interest
* @param Pressure of the particle.
*/
__attribute__((always_inline)) INLINE static float hydro_get_pressure(
const struct part* restrict p) {
return p->primitives.P;
}
/**
* @brief Returns the mass of a particle
*
* @param p The particle of interest
*/
__attribute__((always_inline)) INLINE static float hydro_get_mass(
const struct part* restrict p) {
return p->conserved.mass;
}
/**
* @brief Returns the velocities drifted to the current time of a particle.
*
* @param p The particle of interest
* @param xp The extended data of the particle.
* @param dt The time since the last kick.
* @param v (return) The velocities at the current time.
*/
__attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities(
const struct part* restrict p, const struct xpart* xp, float dt_kick_hydro,
float dt_kick_grav, float v[3]) {
v[0] = p->v[0];
v[1] = p->v[1];
v[2] = p->v[2];
}
/**
* @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) {
if (p->primitives.rho > 0.) {
p->conserved.energy = u * p->conserved.mass;
#ifdef SHADOWFAX_TOTAL_ENERGY
p->conserved.energy +=
0.5f * (p->conserved.momentum[0] * p->primitives.v[0] +
p->conserved.momentum[1] * p->primitives.v[1] +
p->conserved.momentum[2] * p->primitives.v[2]);
#endif
p->primitives.P = gas_pressure_from_internal_energy(p->primitives.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) {
if (p->primitives.rho > 0.) {
p->conserved.energy =
gas_internal_energy_from_entropy(p->primitives.rho, S) *
p->conserved.mass;
#ifdef SHADOWFAX_TOTAL_ENERGY
p->conserved.energy +=
0.5f * (p->conserved.momentum[0] * p->primitives.v[0] +
p->conserved.momentum[1] * p->primitives.v[1] +
p->conserved.momentum[2] * p->primitives.v[2]);
#endif
p->primitives.P = gas_pressure_from_entropy(p->primitives.rho, S);
}
}
/**
* @brief Sets the mass of a particle
*
* @param p The particle of interest
* @param m The mass to set.
*/
__attribute__((always_inline)) INLINE static void hydro_set_mass(
struct part* restrict p, float m) {
p->conserved.mass = m;
}
/**
* @brief Overwrite the initial internal energy of a particle.
*
* Note that in the cases where the thermodynamic variable is not
* internal energy but gets converted later, we must overwrite that
* field. The conversion to the actual variable happens later after
* the initial fake time-step.
*
* @param p The #part to write to.
* @param u_init The new initial internal energy.
*/
__attribute__((always_inline)) INLINE static void
hydro_set_init_internal_energy(struct part* p, float u_init) {
p->conserved.energy = u_init * p->conserved.mass;
#ifdef GIZMO_TOTAL_ENERGY
/* add the kinetic energy */
p->conserved.energy += 0.5f * p->conserved.mass *
(p->conserved.momentum[0] * p->primitives.v[0] +
p->conserved.momentum[1] * p->primitives.v[1] +
p->conserved.momentum[2] * p->primitives.v[2]);
#endif
p->primitives.P = hydro_gamma_minus_one * p->primitives.rho * u_init;
}
/**
* @brief Returns the comoving internal energy of a particle
*
* @param p The particle of interest.
*/
__attribute__((always_inline)) INLINE static float
hydro_get_comoving_internal_energy(const struct part* restrict p) {
if (p->primitives.rho > 0.)
return gas_internal_energy_from_pressure(p->primitives.rho,
p->primitives.P);
else
return 0.;
}
/**
* @brief Returns the comoving entropy of a particle
*
* @param p The particle of interest.
*/
__attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy(
const struct part* restrict p) {
if (p->primitives.rho > 0.) {
return gas_entropy_from_pressure(p->primitives.rho, p->primitives.P);
} else {
return 0.;
}
}
/**
* @brief Returns the sound speed of a particle
*
* @param p The particle of interest.
*/
__attribute__((always_inline)) INLINE static float
hydro_get_comoving_soundspeed(const struct part* restrict p) {
if (p->primitives.rho > 0.)
return gas_soundspeed_from_pressure(p->primitives.rho, p->primitives.P);
else
return 0.;
}
/**
* @brief Returns the comoving pressure of a particle
*
* @param p The particle of interest
*/
__attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure(
const struct part* restrict p) {
return p->primitives.P;
}
/**
* @brief Returns the comoving density of a particle
*
* @param p The particle of interest
*/
__attribute__((always_inline)) INLINE static float hydro_get_comoving_density(
const struct part* restrict p) {
return p->primitives.rho;
}
/**
* @brief Returns the physical internal energy of a particle
*
* @param p The particle of interest.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static float
hydro_get_physical_internal_energy(const struct part* restrict p,
const struct xpart* restrict xp,
const struct cosmology* cosmo) {
return cosmo->a_factor_internal_energy *
hydro_get_comoving_internal_energy(p);
}
/**
* @brief Returns the physical internal energy of a particle
*
* @param p The particle of interest.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static float hydro_get_physical_entropy(
const struct part* restrict p, const struct cosmology* cosmo) {
/* Note: no cosmological conversion required here with our choice of
* coordinates. */
return hydro_get_comoving_entropy(p);
}
/**
* @brief Returns the physical sound speed of a particle
*
* @param p The particle of interest.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static float
hydro_get_physical_soundspeed(const struct part* restrict p,
const struct cosmology* cosmo) {
return cosmo->a_factor_sound_speed * hydro_get_comoving_soundspeed(p);
}
/**
* @brief Sets the physical entropy of a particle
*
* @param p The particle of interest.
* @param xp The extended particle data.
* @param cosmo Cosmology data structure
* @param entropy The physical entropy
*/
__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy(
struct part* p, struct xpart* xp, const struct cosmology* cosmo,
const float entropy) {
error("Needs implementing");
}
/**
* @brief Sets the physical internal energy of a particle
*
* @param p The particle of interest.
* @param xp The extended particle data.
* @param cosmo Cosmology data structure
* @param u The physical internal energy
*/
__attribute__((always_inline)) INLINE static void
hydro_set_physical_internal_energy(struct part* p, struct xpart* xp,
const struct cosmology* cosmo,
const float u) {
error("Need implementing");
}
/**
* @brief Sets the drifted physical internal energy of a particle
*
* @param p The particle of interest.
* @param cosmo Cosmology data structure
* @param u The physical internal energy
*/
__attribute__((always_inline)) INLINE static void
hydro_set_drifted_physical_internal_energy(struct part* p,
const struct cosmology* cosmo,
const float u) {
error("Need implementing");
}
/**
* @brief Gets the drifted physical internal energy of a particle
*
* @param p The particle of interest.
* @param cosmo Cosmology data structure
*
* @return The physical internal energy
*/
__attribute__((always_inline)) INLINE static float
hydro_get_drifted_physical_internal_energy(const struct part* p,
const struct cosmology* cosmo) {
error("Need implementing");
return 0;
}
/**
* @brief Gets the drifted physical entropy of a particle
*
* @param p The particle of interest.
* @param cosmo Cosmology data structure
*
* @return The physical entropy
*/
__attribute__((always_inline)) INLINE static float
hydro_get_drifted_physical_entropy(const struct part* p,
const struct cosmology* cosmo) {
error("Need implementing");
return 0;
}
/**
* @brief Update the value of the viscosity alpha for the scheme.
*
* @param p the particle of interest
* @param alpha the new value for the viscosity coefficient.
*/
__attribute__((always_inline)) INLINE static void hydro_set_viscosity_alpha(
struct part* restrict p, float alpha) {
/* Purposefully left empty */
}
/**
* @brief Update the value of the viscosity alpha to the
* feedback reset value for the scheme.
*
* @param p the particle of interest
*/
__attribute__((always_inline)) INLINE static void
hydro_diffusive_feedback_reset(struct part* restrict p) {
/* Purposefully left empty */
}
/**
* @brief Returns the comoving pressure of a particle
*
* @param p The particle of interest.
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static float hydro_get_physical_pressure(
const struct part* restrict p, const struct cosmology* cosmo) {
return cosmo->a_factor_pressure * p->primitives.P;
}
/**
* @brief Returns the physical density of a particle
*
* @param p The particle of interest
* @param cosmo The cosmological model.
*/
__attribute__((always_inline)) INLINE static float hydro_get_physical_density(
const struct part* restrict p, const struct cosmology* cosmo) {
return cosmo->a3_inv * p->primitives.rho;
}
/**
* @brief Operations performed when a particle gets removed from the
* simulation volume.
*
* @param p The particle.
* @param xp The extended particle data.
* @param time The simulation time.
*/
__attribute__((always_inline)) INLINE static void hydro_remove_part(
const struct part* p, const struct xpart* xp, const double time) {}
#endif /* SWIFT_SHADOWSWIFT_HYDRO_H */