/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
* Matthieu Schaller (schaller@strw.leidenuniv.nl)
* 2015 Peter W. Draper (p.w.draper@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 .
*
******************************************************************************/
/* Config parameters. */
#include
/* This object's header. */
#include "space.h"
/* Local headers. */
#include "black_holes.h"
#include "chemistry.h"
#include "engine.h"
#include "feedback.h"
#include "gravity.h"
#include "mhd.h"
#include "neutrino.h"
#include "particle_splitting.h"
#include "rt.h"
#include "sink.h"
#include "star_formation.h"
#include "stars.h"
#include "threadpool.h"
#include "tracers.h"
void space_first_init_parts_mapper(void *restrict map_data, int count,
void *restrict extra_data) {
struct part *restrict p = (struct part *)map_data;
const struct space *restrict s = (struct space *)extra_data;
const struct engine *e = s->e;
const ptrdiff_t delta = p - s->parts;
struct xpart *restrict xp = s->xparts + delta;
/* Extract some constants */
const struct cosmology *cosmo = s->e->cosmology;
const struct phys_const *phys_const = s->e->physical_constants;
const struct unit_system *us = s->e->internal_units;
const float a_factor_vel = cosmo->a;
const struct hydro_props *hydro_props = s->e->hydro_properties;
const float u_init = hydro_props->initial_internal_energy;
const float hydro_h_min_ratio = e->hydro_properties->h_min_ratio;
const struct gravity_props *grav_props = s->e->gravity_properties;
const int with_gravity = e->policy & engine_policy_self_gravity;
const struct chemistry_global_data *chemistry = e->chemistry;
const struct star_formation *star_formation = e->star_formation;
const struct cooling_function_data *cool_func = e->cooling_func;
const struct rt_props *rt_props = e->rt_props;
/* Check that the smoothing lengths are non-zero */
for (int k = 0; k < count; k++) {
if (p[k].h <= 0.)
error("Invalid value of smoothing length for part %lld h=%e", p[k].id,
p[k].h);
if (with_gravity) {
const struct gpart *gp = p[k].gpart;
const float softening = gravity_get_softening(gp, grav_props);
p->h = max(p->h, softening * hydro_h_min_ratio);
}
}
/* Convert velocities to internal units */
for (int k = 0; k < count; k++) {
p[k].v[0] *= a_factor_vel;
p[k].v[1] *= a_factor_vel;
p[k].v[2] *= a_factor_vel;
#ifdef HYDRO_DIMENSION_2D
p[k].x[2] = 0.f;
p[k].v[2] = 0.f;
#endif
#ifdef HYDRO_DIMENSION_1D
p[k].x[1] = p[k].x[2] = 0.f;
p[k].v[1] = p[k].v[2] = 0.f;
#endif
}
/* Overwrite the internal energy? */
if (u_init > 0.f) {
for (int k = 0; k < count; k++) {
hydro_set_init_internal_energy(&p[k], u_init);
}
}
/* Initialise the rest */
for (int k = 0; k < count; k++) {
hydro_first_init_part(&p[k], &xp[k]);
mhd_first_init_part(&p[k], &xp[k], &hydro_props->mhd, s->dim[0]);
p[k].limiter_data.min_ngb_time_bin = num_time_bins + 1;
p[k].limiter_data.wakeup = time_bin_not_awake;
p[k].limiter_data.to_be_synchronized = 0;
#ifdef WITH_CSDS
csds_part_data_init(&xp[k].csds_data);
#endif
/* Also initialise the chemistry */
chemistry_first_init_part(phys_const, us, cosmo, chemistry, &p[k], &xp[k]);
/* Also initialise the star formation */
star_formation_first_init_part(phys_const, us, cosmo, star_formation, &p[k],
&xp[k]);
/* And the cooling */
cooling_first_init_part(phys_const, us, hydro_props, cosmo, cool_func,
&p[k], &xp[k]);
/* And the tracers */
tracers_first_init_xpart(&p[k], &xp[k], us, phys_const, cosmo, hydro_props,
cool_func);
/* And the black hole markers */
black_holes_mark_part_as_not_swallowed(&p[k].black_holes_data);
/* And the sink markers */
sink_mark_part_as_not_swallowed(&p[k].sink_data);
/* Also initialise the splitting data */
particle_splitting_mark_part_as_not_split(&xp[k].split_data, p[k].id);
/* And the radiative transfer */
rt_first_init_timestep_data(&p[k]);
rt_first_init_part(&p[k], cosmo, rt_props);
#ifdef SWIFT_DEBUG_CHECKS
/* Check part->gpart->part linkeage. */
if (p[k].gpart && p[k].gpart->id_or_neg_offset != -(k + delta))
error("Invalid gpart -> part link");
/* Initialise the time-integration check variables */
p[k].ti_drift = 0;
p[k].ti_kick = 0;
#endif
}
}
/**
* @brief Initialises all the particles by setting them into a valid state
*
* Calls hydro_first_init_part() on all the particles
* Calls chemistry_first_init_part() on all the particles
* Calls cooling_first_init_part() on all the particles
*/
void space_first_init_parts(struct space *s, int verbose) {
const ticks tic = getticks();
if (s->nr_parts > 0)
threadpool_map(&s->e->threadpool, space_first_init_parts_mapper, s->parts,
s->nr_parts, sizeof(struct part), threadpool_auto_chunk_size,
s);
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
void space_first_init_gparts_mapper(void *restrict map_data, int count,
void *restrict extra_data) {
struct gpart *restrict gp = (struct gpart *)map_data;
const struct space *restrict s = (struct space *)extra_data;
const struct cosmology *cosmo = s->e->cosmology;
const float a_factor_vel = cosmo->a;
const struct gravity_props *grav_props = s->e->gravity_properties;
/* Convert velocities to internal units */
for (int k = 0; k < count; k++) {
gp[k].v_full[0] *= a_factor_vel;
gp[k].v_full[1] *= a_factor_vel;
gp[k].v_full[2] *= a_factor_vel;
#ifdef HYDRO_DIMENSION_2D
gp[k].x[2] = 0.f;
gp[k].v_full[2] = 0.f;
#endif
#ifdef HYDRO_DIMENSION_1D
gp[k].x[1] = gp[k].x[2] = 0.f;
gp[k].v_full[1] = gp[k].v_full[2] = 0.f;
#endif
}
/* Initialise the rest */
for (int k = 0; k < count; k++) {
gravity_first_init_gpart(&gp[k], grav_props);
if (gp[k].type == swift_type_neutrino)
gravity_first_init_neutrino(&gp[k], s->e);
#ifdef WITH_CSDS
csds_part_data_init(&gp[k].csds_data);
#endif
#ifdef SWIFT_DEBUG_CHECKS
/* Initialise the time-integration check variables */
gp[k].ti_drift = 0;
gp[k].ti_kick = 0;
gp[k].ti_kick_mesh = 0;
#endif
}
}
/**
* @brief Initialises all the g-particles by setting them into a valid state
*
* Calls gravity_first_init_gpart() on all the particles
*/
void space_first_init_gparts(struct space *s, int verbose) {
const ticks tic = getticks();
if (s->nr_gparts > 0)
threadpool_map(&s->e->threadpool, space_first_init_gparts_mapper, s->gparts,
s->nr_gparts, sizeof(struct gpart),
threadpool_auto_chunk_size, s);
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
void space_first_init_sparts_mapper(void *restrict map_data, int count,
void *restrict extra_data) {
struct spart *restrict sp = (struct spart *)map_data;
const struct space *restrict s = (struct space *)extra_data;
const struct engine *e = s->e;
const struct chemistry_global_data *chemistry = e->chemistry;
#ifdef SWIFT_DEBUG_CHECKS
const ptrdiff_t delta = sp - s->sparts;
#endif
const float initial_h = s->initial_spart_h;
const int with_feedback = (e->policy & engine_policy_feedback);
const int with_cosmology = (e->policy & engine_policy_cosmology);
const struct cosmology *cosmo = e->cosmology;
const struct stars_props *stars_properties = e->stars_properties;
const struct feedback_props *feedback_properties = e->feedback_props;
const struct phys_const *phys_const = s->e->physical_constants;
const struct unit_system *us = s->e->internal_units;
const float a_factor_vel = cosmo->a;
/* Convert velocities to internal units */
for (int k = 0; k < count; k++) {
sp[k].v[0] *= a_factor_vel;
sp[k].v[1] *= a_factor_vel;
sp[k].v[2] *= a_factor_vel;
/* Imposed smoothing length from parameter file */
if (initial_h != -1.f) {
sp[k].h = initial_h;
}
#ifdef HYDRO_DIMENSION_2D
sp[k].x[2] = 0.f;
sp[k].v[2] = 0.f;
#endif
#ifdef HYDRO_DIMENSION_1D
sp[k].x[1] = sp[k].x[2] = 0.f;
sp[k].v[1] = sp[k].v[2] = 0.f;
#endif
}
/* Check that the smoothing lengths are non-zero */
for (int k = 0; k < count; k++) {
if (with_feedback && sp[k].h <= 0.)
error("Invalid value of smoothing length for spart %lld h=%e", sp[k].id,
sp[k].h);
}
/* Initialise the rest */
for (int k = 0; k < count; k++) {
stars_first_init_spart(&sp[k], stars_properties, with_cosmology, cosmo->a,
e->time);
#ifdef WITH_CSDS
csds_part_data_init(&sp[k].csds_data);
#endif
/* And the tracers */
tracers_first_init_spart(&sp[k], us, phys_const, cosmo);
/* Also initialise the chemistry */
chemistry_first_init_spart(chemistry, &sp[k]);
/* Also initialise the feedback */
feedback_first_init_spart(&sp[k], feedback_properties);
/* Also initialise the splitting data */
particle_splitting_mark_part_as_not_split(&sp[k].split_data, sp[k].id);
/* And radiative transfer data */
rt_first_init_spart(&sp[k]);
#ifdef SWIFT_DEBUG_CHECKS
if (sp[k].gpart && sp[k].gpart->id_or_neg_offset != -(k + delta))
error("Invalid gpart -> spart link");
/* Initialise the time-integration check variables */
sp[k].ti_drift = 0;
sp[k].ti_kick = 0;
#endif
}
}
/**
* @brief Initialises all the s-particles by setting them into a valid state
*
* Calls stars_first_init_spart() on all the particles
*/
void space_first_init_sparts(struct space *s, int verbose) {
const ticks tic = getticks();
if (s->nr_sparts > 0)
threadpool_map(&s->e->threadpool, space_first_init_sparts_mapper, s->sparts,
s->nr_sparts, sizeof(struct spart),
threadpool_auto_chunk_size, s);
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
void space_first_init_bparts_mapper(void *restrict map_data, int count,
void *restrict extra_data) {
struct bpart *restrict bp = (struct bpart *)map_data;
const struct space *restrict s = (struct space *)extra_data;
const struct engine *e = s->e;
const struct black_holes_props *props = e->black_holes_properties;
#ifdef SWIFT_DEBUG_CHECKS
const ptrdiff_t delta = bp - s->bparts;
#endif
const float initial_h = s->initial_bpart_h;
const struct cosmology *cosmo = e->cosmology;
const struct phys_const *phys_const = s->e->physical_constants;
const struct unit_system *us = s->e->internal_units;
const float a_factor_vel = cosmo->a;
/* Convert velocities to internal units */
for (int k = 0; k < count; k++) {
bp[k].v[0] *= a_factor_vel;
bp[k].v[1] *= a_factor_vel;
bp[k].v[2] *= a_factor_vel;
/* Imposed smoothing length from parameter file */
if (initial_h != -1.f) {
bp[k].h = initial_h;
}
#ifdef HYDRO_DIMENSION_2D
bp[k].x[2] = 0.f;
bp[k].v[2] = 0.f;
#endif
#ifdef HYDRO_DIMENSION_1D
bp[k].x[1] = bp[k].x[2] = 0.f;
bp[k].v[1] = bp[k].v[2] = 0.f;
#endif
}
/* Check that the smoothing lengths are non-zero */
for (int k = 0; k < count; k++) {
if (bp[k].h <= 0.)
error("Invalid value of smoothing length for bpart %lld h=%e", bp[k].id,
bp[k].h);
}
/* Initialise the rest */
for (int k = 0; k < count; k++) {
black_holes_first_init_bpart(&bp[k], props);
/* And the tracers */
tracers_first_init_bpart(&bp[k], us, phys_const, cosmo);
/* And the splitting data */
particle_splitting_mark_part_as_not_split(&bp[k].split_data, bp[k].id);
/* And the black hole merger markers */
black_holes_mark_bpart_as_not_swallowed(&bp[k].merger_data);
#ifdef SWIFT_DEBUG_CHECKS
if (bp[k].gpart && bp[k].gpart->id_or_neg_offset != -(k + delta))
error("Invalid gpart -> bpart link");
/* Initialise the time-integration check variables */
bp[k].ti_drift = 0;
bp[k].ti_kick = 0;
#endif
}
}
/**
* @brief Initialises all the b-particles by setting them into a valid state
*
* Calls stars_first_init_bpart() on all the particles
*/
void space_first_init_bparts(struct space *s, int verbose) {
const ticks tic = getticks();
if (s->nr_bparts > 0)
threadpool_map(&s->e->threadpool, space_first_init_bparts_mapper, s->bparts,
s->nr_bparts, sizeof(struct bpart),
threadpool_auto_chunk_size, s);
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
void space_first_init_sinks_mapper(void *restrict map_data, int count,
void *restrict extra_data) {
struct sink *restrict sink = (struct sink *)map_data;
const struct space *restrict s = (struct space *)extra_data;
const struct engine *e = s->e;
const struct sink_props *props = e->sink_properties;
const struct chemistry_global_data *chemistry = e->chemistry;
#ifdef SWIFT_DEBUG_CHECKS
const ptrdiff_t delta = sink - s->sinks;
#endif
const struct cosmology *cosmo = e->cosmology;
const float a_factor_vel = cosmo->a;
/* Convert velocities to internal units */
for (int k = 0; k < count; k++) {
sink[k].v[0] *= a_factor_vel;
sink[k].v[1] *= a_factor_vel;
sink[k].v[2] *= a_factor_vel;
#ifdef HYDRO_DIMENSION_2D
sink[k].x[2] = 0.f;
sink[k].v[2] = 0.f;
#endif
#ifdef HYDRO_DIMENSION_1D
sink[k].x[1] = sink[k].x[2] = 0.f;
sink[k].v[1] = sink[k].v[2] = 0.f;
#endif
}
/* Initialise the rest */
for (int k = 0; k < count; k++) {
/* Initialize the sinks */
sink_first_init_sink(&sink[k], props, e);
/* And the sink merger markers */
sink_mark_sink_as_not_swallowed(&sink[k].merger_data);
/* Also initialize the chemistry */
chemistry_first_init_sink(chemistry, &sink[k]);
/* Note: Here we can add X_first_init_sink() for other modules */
/* TODO (for Darwin): add CSDS when it's ready */
#ifdef SWIFT_DEBUG_CHECKS
if (sink[k].gpart && sink[k].gpart->id_or_neg_offset != -(k + delta))
error("Invalid gpart -> sink link");
/* Initialise the time-integration check variables */
sink[k].ti_drift = 0;
sink[k].ti_kick = 0;
#endif
}
}
/**
* @brief Initialises all the sink-particles by setting them into a valid state
*
* Calls stars_first_init_sink() on all the particles
*/
void space_first_init_sinks(struct space *s, int verbose) {
const ticks tic = getticks();
if (s->nr_sinks > 0)
threadpool_map(&s->e->threadpool, space_first_init_sinks_mapper, s->sinks,
s->nr_sinks, sizeof(struct sink), threadpool_auto_chunk_size,
s);
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}