/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (schaller@strw.leidenuniv.nl)
*
* 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_DRIFT_H
#define SWIFT_DRIFT_H
/* Config parameters. */
#include
/* Local headers. */
#include "adaptive_softening.h"
#include "black_holes.h"
#include "const.h"
#include "debug.h"
#include "dimension.h"
#include "engine.h"
#include "entropy_floor.h"
#include "hydro.h"
#include "hydro_properties.h"
#include "lightcone/lightcone_crossing.h"
#include "lightcone/lightcone_replications.h"
#include "mhd.h"
#include "part.h"
#include "rt.h"
#include "sink.h"
#include "stars.h"
/**
* @brief Perform the 'drift' operation on a #gpart.
*
* @param gp The #gpart to drift.
* @param dt_drift The drift time-step.
* @param ti_old Integer start of time-step (for debugging checks).
* @param ti_current Integer end of time-step (for debugging checks).
* @param grav_props The properties of the gravity scheme.
* @param e the #engine
*/
__attribute__((always_inline)) INLINE static void drift_gpart(
struct gpart *restrict gp, double dt_drift, integertime_t ti_old,
integertime_t ti_current, const struct gravity_props *grav_props,
const struct engine *e, struct replication_list *replication_list,
const double cell_loc[3]) {
#ifdef SWIFT_DEBUG_CHECKS
if (gp->time_bin == time_bin_not_created) {
error("Found an extra gpart in the drift");
}
if (gp->ti_drift != ti_old)
error(
"g-particle has not been drifted to the current time "
"gp->ti_drift=%lld, "
"c->ti_old=%lld, ti_current=%lld",
gp->ti_drift, ti_old, ti_current);
gp->ti_drift = ti_current;
#endif
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Get the ID of the gpart */
long long id = 0;
if (gp->type == swift_type_gas)
id = e->s->parts[-gp->id_or_neg_offset].id;
else if (gp->type == swift_type_stars)
id = e->s->sparts[-gp->id_or_neg_offset].id;
else if (gp->type == swift_type_black_hole)
id = e->s->bparts[-gp->id_or_neg_offset].id;
else
id = gp->id_or_neg_offset;
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
/* Don't move! */
gp->v_full[0] = 0.f;
gp->v_full[1] = 0.f;
gp->v_full[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
/* Store initial position and velocity for lightcone check after the drift */
const double x[3] = {gp->x[0], gp->x[1], gp->x[2]};
const float v_full[3] = {gp->v_full[0], gp->v_full[1], gp->v_full[2]};
#endif
/* Drift... */
gp->x[0] += gp->v_full[0] * dt_drift;
gp->x[1] += gp->v_full[1] * dt_drift;
gp->x[2] += gp->v_full[2] * dt_drift;
gravity_predict_extra(gp, grav_props);
#ifdef WITH_LIGHTCONE
/* Check for lightcone crossing */
switch (gp->type) {
case swift_type_dark_matter:
case swift_type_dark_matter_background:
case swift_type_neutrino:
/* This particle has no *part counterpart, so check for lightcone crossing
* here */
lightcone_check_particle_crosses(e, replication_list, x, v_full, gp,
dt_drift, ti_old, ti_current, cell_loc);
break;
default:
/* Particle has a counterpart or is of a type not supported in lightcones
*/
break;
}
#endif
}
/**
* @brief Perform the 'drift' operation on a #part
*
* @param p The #part to drift.
* @param xp The #xpart of the particle.
* @param dt_drift The drift time-step
* @param dt_kick_grav The kick time-step for gravity accelerations.
* @param dt_kick_hydro The kick time-step for hydro accelerations.
* @param dt_therm The drift time-step for thermodynamic quantities.
* @param ti_old Integer start of time-step (for debugging checks).
* @param ti_current Integer end of time-step (for debugging checks).
* @param cosmo The cosmological model.
* @param hydro_props The properties of the hydro scheme.
* @param floor The properties of the entropy floor.
*/
__attribute__((always_inline)) INLINE static void drift_part(
struct part *restrict p, struct xpart *restrict xp, double dt_drift,
double dt_kick_hydro, double dt_kick_grav, double dt_therm,
integertime_t ti_old, integertime_t ti_current, const struct engine *e,
struct replication_list *replication_list, const double cell_loc[3]) {
const struct cosmology *cosmo = e->cosmology;
const struct hydro_props *hydro_props = e->hydro_properties;
const struct entropy_floor_properties *entropy_floor = e->entropy_floor;
const struct pressure_floor_props *pressure_floor = e->pressure_floor_props;
#ifdef SWIFT_DEBUG_CHECKS
if (p->ti_drift != ti_old)
error(
"particle has not been drifted to the current time p->ti_drift=%lld, "
"c->ti_old=%lld, ti_current=%lld",
p->ti_drift, ti_old, ti_current);
p->ti_drift = ti_current;
#endif
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Get the ID of the gpart */
const long long id = p->id;
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
/* Don't move! */
xp->v_full[0] = 0.f;
xp->v_full[1] = 0.f;
xp->v_full[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
/* Store initial position and velocity for lightcone check after the drift */
const double x[3] = {p->x[0], p->x[1], p->x[2]};
const float v_full[3] = {xp->v_full[0], xp->v_full[1], xp->v_full[2]};
#endif
/* Drift... */
p->x[0] += xp->v_full[0] * dt_drift;
p->x[1] += xp->v_full[1] * dt_drift;
p->x[2] += xp->v_full[2] * dt_drift;
/* Predict velocities (for hydro terms) */
p->v[0] += p->a_hydro[0] * dt_kick_hydro;
p->v[1] += p->a_hydro[1] * dt_kick_hydro;
p->v[2] += p->a_hydro[2] * dt_kick_hydro;
/* Predict velocities (for gravity terms) */
if (p->gpart != NULL) {
p->v[0] += xp->a_grav[0] * dt_kick_grav;
p->v[1] += xp->a_grav[1] * dt_kick_grav;
p->v[2] += xp->a_grav[2] * dt_kick_grav;
}
/* Predict the values of the extra fields */
hydro_predict_extra(p, xp, dt_drift, dt_therm, dt_kick_grav, cosmo,
hydro_props, entropy_floor, pressure_floor);
mhd_predict_extra(p, xp, dt_drift, dt_therm, cosmo, hydro_props,
entropy_floor);
rt_predict_extra(p, xp, dt_drift);
if (p->gpart) gravity_update_softening(p->gpart, p, e->gravity_properties);
/* Compute offsets since last cell construction */
for (int k = 0; k < 3; k++) {
const float dx = xp->v_full[k] * dt_drift;
xp->x_diff[k] -= dx;
xp->x_diff_sort[k] -= dx;
}
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
p->v[0] = 0.f;
p->v[1] = 0.f;
p->v[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
/* Check if the particle crossed the lightcone */
if (p->gpart)
lightcone_check_particle_crosses(e, replication_list, x, v_full, p->gpart,
dt_drift, ti_old, ti_current, cell_loc);
#endif
}
/**
* @brief Perform the 'drift' operation on a #spart
*
* @param sp The #spart to drift.
* @param dt_drift The drift time-step.
* @param ti_old Integer start of time-step (for debugging checks).
* @param ti_current Integer end of time-step (for debugging checks).
*/
__attribute__((always_inline)) INLINE static void drift_spart(
struct spart *restrict sp, double dt_drift, integertime_t ti_old,
integertime_t ti_current, const struct engine *e,
struct replication_list *replication_list, const double cell_loc[3]) {
#ifdef SWIFT_DEBUG_CHECKS
if (sp->ti_drift != ti_old)
error(
"s-particle has not been drifted to the current time "
"sp->ti_drift=%lld, "
"c->ti_old=%lld, ti_current=%lld",
sp->ti_drift, ti_old, ti_current);
sp->ti_drift = ti_current;
#endif
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Get the ID of the gpart */
const long long id = sp->id;
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
/* Don't move! */
sp->v[0] = 0.f;
sp->v[1] = 0.f;
sp->v[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
/* Store initial position and velocity for lightcone check after the drift */
const double x[3] = {sp->x[0], sp->x[1], sp->x[2]};
const float v_full[3] = {sp->v[0], sp->v[1], sp->v[2]};
#endif
/* Drift... */
sp->x[0] += sp->v[0] * dt_drift;
sp->x[1] += sp->v[1] * dt_drift;
sp->x[2] += sp->v[2] * dt_drift;
/* Predict the values of the extra fields */
stars_predict_extra(sp, dt_drift);
/* Compute offsets since last cell construction */
for (int k = 0; k < 3; k++) {
const float dx = sp->v[k] * dt_drift;
sp->x_diff[k] -= dx;
sp->x_diff_sort[k] -= dx;
}
#ifdef WITH_LIGHTCONE
/* Check for lightcone crossing */
if (sp->gpart)
lightcone_check_particle_crosses(e, replication_list, x, v_full, sp->gpart,
dt_drift, ti_old, ti_current, cell_loc);
#endif
}
/**
* @brief Perform the 'drift' operation on a #bpart
*
* @param bp The #bpart to drift.
* @param dt_drift The drift time-step.
* @param ti_old Integer start of time-step (for debugging checks).
* @param ti_current Integer end of time-step (for debugging checks).
*/
__attribute__((always_inline)) INLINE static void drift_bpart(
struct bpart *restrict bp, double dt_drift, integertime_t ti_old,
integertime_t ti_current, const struct engine *e,
struct replication_list *replication_list, const double cell_loc[3]) {
#ifdef SWIFT_DEBUG_CHECKS
if (bp->ti_drift != ti_old)
error(
"b-particle has not been drifted to the current time "
"bp->ti_drift=%lld, "
"c->ti_old=%lld, ti_current=%lld",
bp->ti_drift, ti_old, ti_current);
bp->ti_drift = ti_current;
#endif
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Get the ID of the gpart */
const long long id = bp->id;
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
/* Don't move! */
bp->v[0] = 0.f;
bp->v[1] = 0.f;
bp->v[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
/* Store initial position and velocity for lightcone check after the drift */
const double x[3] = {bp->x[0], bp->x[1], bp->x[2]};
const float v_full[3] = {bp->v[0], bp->v[1], bp->v[2]};
#endif
/* Drift... */
bp->x[0] += bp->v[0] * dt_drift;
bp->x[1] += bp->v[1] * dt_drift;
bp->x[2] += bp->v[2] * dt_drift;
/* Predict the values of the extra fields */
black_holes_predict_extra(bp, dt_drift);
/* Compute offsets since last cell construction */
for (int k = 0; k < 3; k++) {
const float dx = bp->v[k] * dt_drift;
bp->x_diff[k] -= dx;
}
#ifdef WITH_LIGHTCONE
/* Check for lightcone crossing */
if (bp->gpart)
lightcone_check_particle_crosses(e, replication_list, x, v_full, bp->gpart,
dt_drift, ti_old, ti_current, cell_loc);
#endif
}
/**
* @brief Perform the 'drift' operation on a #sink
*
* @param sink The #sink to drift.
* @param dt_drift The drift time-step.
* @param ti_old Integer start of time-step (for debugging checks).
* @param ti_current Integer end of time-step (for debugging checks).
*/
__attribute__((always_inline)) INLINE static void drift_sink(
struct sink *restrict sink, double dt_drift, integertime_t ti_old,
integertime_t ti_current) {
#ifdef SWIFT_DEBUG_CHECKS
if (sink->ti_drift != ti_old) {
error(
"s-particle has not been drifted to the current time "
"sink->ti_drift=%lld, "
"c->ti_old=%lld, ti_current=%lld",
sink->ti_drift, ti_old, ti_current);
}
sink->ti_drift = ti_current;
#endif
#ifdef SWIFT_FIXED_BOUNDARY_PARTICLES
/* Get the ID of the gpart */
const long long id = sink->id;
/* Cancel the velocity of the particles */
if (id < SWIFT_FIXED_BOUNDARY_PARTICLES) {
/* Don't move! */
sink->v[0] = 0.f;
sink->v[1] = 0.f;
sink->v[2] = 0.f;
}
#endif
#ifdef WITH_LIGHTCONE
error("Lightcone treatment of sinks needs implementing");
#endif
/* Drift... */
sink->x[0] += sink->v[0] * dt_drift;
sink->x[1] += sink->v[1] * dt_drift;
sink->x[2] += sink->v[2] * dt_drift;
/* Predict the values of the extra fields */
sink_predict_extra(sink, dt_drift);
/* Compute offsets since last cell construction */
for (int k = 0; k < 3; k++) {
const float dx = sink->v[k] * dt_drift;
sink->x_diff[k] -= dx;
}
}
#endif /* SWIFT_DRIFT_H */