/*******************************************************************************
* 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 "cell.h"
#include "engine.h"
#include "error.h"
#include "hydro.h"
#include "threadpool.h"
/* Some standard headers. */
#include
/**
* @brief Information required to compute the particle cell indices.
*/
struct space_index_data {
struct space *s;
int *ind;
int *cell_counts;
size_t count_inhibited_part;
size_t count_inhibited_gpart;
size_t count_inhibited_spart;
size_t count_inhibited_bpart;
size_t count_inhibited_sink;
size_t count_extra_part;
size_t count_extra_gpart;
size_t count_extra_spart;
size_t count_extra_bpart;
size_t count_extra_sink;
};
/**
* @brief #threadpool mapper function to compute the particle cell indices.
*
* @param map_data Pointer towards the particles.
* @param nr_parts The number of particles to treat.
* @param extra_data Pointers to the space and index list
*/
void space_parts_get_cell_index_mapper(void *map_data, int nr_parts,
void *extra_data) {
/* Unpack the data */
struct part *restrict parts = (struct part *)map_data;
struct space_index_data *data = (struct space_index_data *)extra_data;
struct space *s = data->s;
int *const ind = data->ind + (ptrdiff_t)(parts - s->parts);
/* Get some constants */
const double dim_x = s->dim[0];
const double dim_y = s->dim[1];
const double dim_z = s->dim[2];
const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
const double ih_x = s->iwidth[0];
const double ih_y = s->iwidth[1];
const double ih_z = s->iwidth[2];
/* Init the local count buffer. */
int *cell_counts = (int *)calloc(s->nr_cells, sizeof(int));
if (cell_counts == NULL)
error("Failed to allocate temporary cell count buffer.");
/* Init the local collectors */
float min_mass = FLT_MAX;
float sum_vel_norm = 0.f;
size_t count_inhibited_part = 0;
size_t count_extra_part = 0;
/* Loop over the parts. */
for (int k = 0; k < nr_parts; k++) {
/* Get the particle */
struct part *restrict p = &parts[k];
double old_pos_x = p->x[0];
double old_pos_y = p->x[1];
double old_pos_z = p->x[2];
#ifdef SWIFT_DEBUG_CHECKS
if (!s->periodic && p->time_bin != time_bin_inhibited) {
if (old_pos_x < 0. || old_pos_x > dim_x)
error("Particle outside of volume along X.");
if (old_pos_y < 0. || old_pos_y > dim_y)
error("Particle outside of volume along Y.");
if (old_pos_z < 0. || old_pos_z > dim_z)
error("Particle outside of volume along Z.");
}
#endif
/* Put it back into the simulation volume */
double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
/* Treat the case where a particle was wrapped back exactly onto
* the edge because of rounding issues (more accuracy around 0
* than around dim) */
if (pos_x == dim_x) pos_x = 0.0;
if (pos_y == dim_y) pos_y = 0.0;
if (pos_z == dim_z) pos_z = 0.0;
/* Get its cell index */
const int index =
cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
#ifdef SWIFT_DEBUG_CHECKS
if (index < 0 || index >= cdim[0] * cdim[1] * cdim[2])
error("Invalid index=%d cdim=[%d %d %d] p->x=[%e %e %e]", index, cdim[0],
cdim[1], cdim[2], pos_x, pos_y, pos_z);
if (pos_x >= dim_x || pos_y >= dim_y || pos_z >= dim_z || pos_x < 0. ||
pos_y < 0. || pos_z < 0.)
error("Particle outside of simulation box. p->x=[%e %e %e]", pos_x, pos_y,
pos_z);
#endif
if (p->time_bin == time_bin_inhibited) {
/* Is this particle to be removed? */
ind[k] = -1;
++count_inhibited_part;
} else if (p->time_bin == time_bin_not_created) {
/* Is this a place-holder for on-the-fly creation? */
ind[k] = index;
cell_counts[index]++;
++count_extra_part;
} else {
/* Normal case: list its top-level cell index */
ind[k] = index;
cell_counts[index]++;
/* Compute minimal mass */
min_mass = min(min_mass, hydro_get_mass(p));
/* Compute sum of velocity norm */
sum_vel_norm += p->v[0] * p->v[0] + p->v[1] * p->v[1] + p->v[2] * p->v[2];
/* Update the position */
p->x[0] = pos_x;
p->x[1] = pos_y;
p->x[2] = pos_z;
}
}
/* Write the counts back to the global array. */
for (int k = 0; k < s->nr_cells; k++)
if (cell_counts[k]) atomic_add(&data->cell_counts[k], cell_counts[k]);
free(cell_counts);
/* Write the count of inhibited and extra parts */
if (count_inhibited_part)
atomic_add(&data->count_inhibited_part, count_inhibited_part);
if (count_extra_part) atomic_add(&data->count_extra_part, count_extra_part);
/* Write back the minimal part mass and velocity sum */
atomic_min_f(&s->min_part_mass, min_mass);
atomic_add_f(&s->sum_part_vel_norm, sum_vel_norm);
}
/**
* @brief #threadpool mapper function to compute the g-particle cell indices.
*
* @param map_data Pointer towards the g-particles.
* @param nr_gparts The number of g-particles to treat.
* @param extra_data Pointers to the space and index list
*/
void space_gparts_get_cell_index_mapper(void *map_data, int nr_gparts,
void *extra_data) {
/* Unpack the data */
struct gpart *restrict gparts = (struct gpart *)map_data;
struct space_index_data *data = (struct space_index_data *)extra_data;
struct space *s = data->s;
int *const ind = data->ind + (ptrdiff_t)(gparts - s->gparts);
/* Get some constants */
const double dim_x = s->dim[0];
const double dim_y = s->dim[1];
const double dim_z = s->dim[2];
const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
const double ih_x = s->iwidth[0];
const double ih_y = s->iwidth[1];
const double ih_z = s->iwidth[2];
/* Init the local count buffer. */
int *cell_counts = (int *)calloc(s->nr_cells, sizeof(int));
if (cell_counts == NULL)
error("Failed to allocate temporary cell count buffer.");
/* Init the local collectors */
float min_mass = FLT_MAX;
float sum_vel_norm = 0.f;
size_t count_inhibited_gpart = 0;
size_t count_extra_gpart = 0;
for (int k = 0; k < nr_gparts; k++) {
/* Get the particle */
struct gpart *restrict gp = &gparts[k];
double old_pos_x = gp->x[0];
double old_pos_y = gp->x[1];
double old_pos_z = gp->x[2];
#ifdef SWIFT_DEBUG_CHECKS
if (!s->periodic && gp->time_bin != time_bin_inhibited) {
if (old_pos_x < 0. || old_pos_x > dim_x)
error("Particle outside of volume along X.");
if (old_pos_y < 0. || old_pos_y > dim_y)
error("Particle outside of volume along Y.");
if (old_pos_z < 0. || old_pos_z > dim_z)
error("Particle outside of volume along Z.");
}
#endif
/* Put it back into the simulation volume */
double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
/* Treat the case where a particle was wrapped back exactly onto
* the edge because of rounding issues (more accuracy around 0
* than around dim) */
if (pos_x == dim_x) pos_x = 0.0;
if (pos_y == dim_y) pos_y = 0.0;
if (pos_z == dim_z) pos_z = 0.0;
/* Get its cell index */
const int index =
cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
#ifdef SWIFT_DEBUG_CHECKS
if (index < 0 || index >= cdim[0] * cdim[1] * cdim[2])
error("Invalid index=%d cdim=[%d %d %d] p->x=[%e %e %e]", index, cdim[0],
cdim[1], cdim[2], pos_x, pos_y, pos_z);
if (pos_x >= dim_x || pos_y >= dim_y || pos_z >= dim_z || pos_x < 0. ||
pos_y < 0. || pos_z < 0.)
error("Particle outside of simulation box. p->x=[%e %e %e]", pos_x, pos_y,
pos_z);
#endif
if (gp->time_bin == time_bin_inhibited) {
/* Is this particle to be removed? */
ind[k] = -1;
++count_inhibited_gpart;
} else if (gp->time_bin == time_bin_not_created) {
/* Is this a place-holder for on-the-fly creation? */
ind[k] = index;
cell_counts[index]++;
++count_extra_gpart;
} else {
/* List its top-level cell index */
ind[k] = index;
cell_counts[index]++;
if (gp->type == swift_type_dark_matter) {
/* Compute minimal mass */
min_mass = min(min_mass, gp->mass);
/* Compute sum of velocity norm */
sum_vel_norm += gp->v_full[0] * gp->v_full[0] +
gp->v_full[1] * gp->v_full[1] +
gp->v_full[2] * gp->v_full[2];
}
/* Update the position */
gp->x[0] = pos_x;
gp->x[1] = pos_y;
gp->x[2] = pos_z;
}
}
/* Write the counts back to the global array. */
for (int k = 0; k < s->nr_cells; k++)
if (cell_counts[k]) atomic_add(&data->cell_counts[k], cell_counts[k]);
free(cell_counts);
/* Write the count of inhibited and extra gparts */
if (count_inhibited_gpart)
atomic_add(&data->count_inhibited_gpart, count_inhibited_gpart);
if (count_extra_gpart)
atomic_add(&data->count_extra_gpart, count_extra_gpart);
/* Write back the minimal part mass and velocity sum */
atomic_min_f(&s->min_gpart_mass, min_mass);
atomic_add_f(&s->sum_gpart_vel_norm, sum_vel_norm);
}
/**
* @brief #threadpool mapper function to compute the s-particle cell indices.
*
* @param map_data Pointer towards the s-particles.
* @param nr_sparts The number of s-particles to treat.
* @param extra_data Pointers to the space and index list
*/
void space_sparts_get_cell_index_mapper(void *map_data, int nr_sparts,
void *extra_data) {
/* Unpack the data */
struct spart *restrict sparts = (struct spart *)map_data;
struct space_index_data *data = (struct space_index_data *)extra_data;
struct space *s = data->s;
int *const ind = data->ind + (ptrdiff_t)(sparts - s->sparts);
/* Get some constants */
const double dim_x = s->dim[0];
const double dim_y = s->dim[1];
const double dim_z = s->dim[2];
const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
const double ih_x = s->iwidth[0];
const double ih_y = s->iwidth[1];
const double ih_z = s->iwidth[2];
/* Init the local count buffer. */
int *cell_counts = (int *)calloc(s->nr_cells, sizeof(int));
if (cell_counts == NULL)
error("Failed to allocate temporary cell count buffer.");
/* Init the local collectors */
float min_mass = FLT_MAX;
float sum_vel_norm = 0.f;
size_t count_inhibited_spart = 0;
size_t count_extra_spart = 0;
for (int k = 0; k < nr_sparts; k++) {
/* Get the particle */
struct spart *restrict sp = &sparts[k];
double old_pos_x = sp->x[0];
double old_pos_y = sp->x[1];
double old_pos_z = sp->x[2];
#ifdef SWIFT_DEBUG_CHECKS
if (!s->periodic && sp->time_bin != time_bin_inhibited) {
if (old_pos_x < 0. || old_pos_x > dim_x)
error("Particle outside of volume along X.");
if (old_pos_y < 0. || old_pos_y > dim_y)
error("Particle outside of volume along Y.");
if (old_pos_z < 0. || old_pos_z > dim_z)
error("Particle outside of volume along Z.");
}
#endif
/* Put it back into the simulation volume */
double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
/* Treat the case where a particle was wrapped back exactly onto
* the edge because of rounding issues (more accuracy around 0
* than around dim) */
if (pos_x == dim_x) pos_x = 0.0;
if (pos_y == dim_y) pos_y = 0.0;
if (pos_z == dim_z) pos_z = 0.0;
/* Get its cell index */
const int index =
cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
#ifdef SWIFT_DEBUG_CHECKS
if (index < 0 || index >= cdim[0] * cdim[1] * cdim[2])
error("Invalid index=%d cdim=[%d %d %d] p->x=[%e %e %e]", index, cdim[0],
cdim[1], cdim[2], pos_x, pos_y, pos_z);
if (pos_x >= dim_x || pos_y >= dim_y || pos_z >= dim_z || pos_x < 0. ||
pos_y < 0. || pos_z < 0.)
error("Particle outside of simulation box. p->x=[%e %e %e]", pos_x, pos_y,
pos_z);
#endif
/* Is this particle to be removed? */
if (sp->time_bin == time_bin_inhibited) {
ind[k] = -1;
++count_inhibited_spart;
} else if (sp->time_bin == time_bin_not_created) {
/* Is this a place-holder for on-the-fly creation? */
ind[k] = index;
cell_counts[index]++;
++count_extra_spart;
} else {
/* List its top-level cell index */
ind[k] = index;
cell_counts[index]++;
/* Compute minimal mass */
min_mass = min(min_mass, sp->mass);
/* Compute sum of velocity norm */
sum_vel_norm +=
sp->v[0] * sp->v[0] + sp->v[1] * sp->v[1] + sp->v[2] * sp->v[2];
/* Update the position */
sp->x[0] = pos_x;
sp->x[1] = pos_y;
sp->x[2] = pos_z;
}
}
/* Write the counts back to the global array. */
for (int k = 0; k < s->nr_cells; k++)
if (cell_counts[k]) atomic_add(&data->cell_counts[k], cell_counts[k]);
free(cell_counts);
/* Write the count of inhibited and extra sparts */
if (count_inhibited_spart)
atomic_add(&data->count_inhibited_spart, count_inhibited_spart);
if (count_extra_spart)
atomic_add(&data->count_extra_spart, count_extra_spart);
/* Write back the minimal part mass and velocity sum */
atomic_min_f(&s->min_spart_mass, min_mass);
atomic_add_f(&s->sum_spart_vel_norm, sum_vel_norm);
}
/**
* @brief #threadpool mapper function to compute the b-particle cell indices.
*
* @param map_data Pointer towards the b-particles.
* @param nr_bparts The number of b-particles to treat.
* @param extra_data Pointers to the space and index list
*/
void space_bparts_get_cell_index_mapper(void *map_data, int nr_bparts,
void *extra_data) {
/* Unpack the data */
struct bpart *restrict bparts = (struct bpart *)map_data;
struct space_index_data *data = (struct space_index_data *)extra_data;
struct space *s = data->s;
int *const ind = data->ind + (ptrdiff_t)(bparts - s->bparts);
/* Get some constants */
const double dim_x = s->dim[0];
const double dim_y = s->dim[1];
const double dim_z = s->dim[2];
const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
const double ih_x = s->iwidth[0];
const double ih_y = s->iwidth[1];
const double ih_z = s->iwidth[2];
/* Init the local count buffer. */
int *cell_counts = (int *)calloc(s->nr_cells, sizeof(int));
if (cell_counts == NULL)
error("Failed to allocate temporary cell count buffer.");
/* Init the local collectors */
float min_mass = FLT_MAX;
float sum_vel_norm = 0.f;
size_t count_inhibited_bpart = 0;
size_t count_extra_bpart = 0;
for (int k = 0; k < nr_bparts; k++) {
/* Get the particle */
struct bpart *restrict bp = &bparts[k];
double old_pos_x = bp->x[0];
double old_pos_y = bp->x[1];
double old_pos_z = bp->x[2];
#ifdef SWIFT_DEBUG_CHECKS
if (!s->periodic && bp->time_bin != time_bin_inhibited) {
if (old_pos_x < 0. || old_pos_x > dim_x)
error("Particle outside of volume along X.");
if (old_pos_y < 0. || old_pos_y > dim_y)
error("Particle outside of volume along Y.");
if (old_pos_z < 0. || old_pos_z > dim_z)
error("Particle outside of volume along Z.");
}
#endif
/* Put it back into the simulation volume */
double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
/* Treat the case where a particle was wrapped back exactly onto
* the edge because of rounding issues (more accuracy around 0
* than around dim) */
if (pos_x == dim_x) pos_x = 0.0;
if (pos_y == dim_y) pos_y = 0.0;
if (pos_z == dim_z) pos_z = 0.0;
/* Get its cell index */
const int index =
cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
#ifdef SWIFT_DEBUG_CHECKS
if (index < 0 || index >= cdim[0] * cdim[1] * cdim[2])
error("Invalid index=%d cdim=[%d %d %d] p->x=[%e %e %e]", index, cdim[0],
cdim[1], cdim[2], pos_x, pos_y, pos_z);
if (pos_x >= dim_x || pos_y >= dim_y || pos_z >= dim_z || pos_x < 0. ||
pos_y < 0. || pos_z < 0.)
error("Particle outside of simulation box. p->x=[%e %e %e]", pos_x, pos_y,
pos_z);
#endif
/* Is this particle to be removed? */
if (bp->time_bin == time_bin_inhibited) {
ind[k] = -1;
++count_inhibited_bpart;
} else if (bp->time_bin == time_bin_not_created) {
/* Is this a place-holder for on-the-fly creation? */
ind[k] = index;
cell_counts[index]++;
++count_extra_bpart;
} else {
/* List its top-level cell index */
ind[k] = index;
cell_counts[index]++;
/* Compute minimal mass */
min_mass = min(min_mass, bp->mass);
/* Compute sum of velocity norm */
sum_vel_norm +=
bp->v[0] * bp->v[0] + bp->v[1] * bp->v[1] + bp->v[2] * bp->v[2];
/* Update the position */
bp->x[0] = pos_x;
bp->x[1] = pos_y;
bp->x[2] = pos_z;
}
}
/* Write the counts back to the global array. */
for (int k = 0; k < s->nr_cells; k++)
if (cell_counts[k]) atomic_add(&data->cell_counts[k], cell_counts[k]);
free(cell_counts);
/* Write the count of inhibited and extra bparts */
if (count_inhibited_bpart)
atomic_add(&data->count_inhibited_bpart, count_inhibited_bpart);
if (count_extra_bpart)
atomic_add(&data->count_extra_bpart, count_extra_bpart);
/* Write back the minimal part mass and velocity sum */
atomic_min_f(&s->min_bpart_mass, min_mass);
atomic_add_f(&s->sum_bpart_vel_norm, sum_vel_norm);
}
/**
* @brief #threadpool mapper function to compute the sink-particle cell indices.
*
* @param map_data Pointer towards the sink-particles.
* @param nr_sinks The number of sink-particles to treat.
* @param extra_data Pointers to the space and index list
*/
void space_sinks_get_cell_index_mapper(void *map_data, int nr_sinks,
void *extra_data) {
/* Unpack the data */
struct sink *restrict sinks = (struct sink *)map_data;
struct space_index_data *data = (struct space_index_data *)extra_data;
struct space *s = data->s;
int *const ind = data->ind + (ptrdiff_t)(sinks - s->sinks);
/* Get some constants */
const double dim_x = s->dim[0];
const double dim_y = s->dim[1];
const double dim_z = s->dim[2];
const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
const double ih_x = s->iwidth[0];
const double ih_y = s->iwidth[1];
const double ih_z = s->iwidth[2];
/* Init the local count buffer. */
int *cell_counts = (int *)calloc(s->nr_cells, sizeof(int));
if (cell_counts == NULL)
error("Failed to allocate temporary cell count buffer.");
/* Init the local collectors */
float min_mass = FLT_MAX;
float sum_vel_norm = 0.f;
size_t count_inhibited_sink = 0;
size_t count_extra_sink = 0;
for (int k = 0; k < nr_sinks; k++) {
/* Get the particle */
struct sink *restrict sink = &sinks[k];
double old_pos_x = sink->x[0];
double old_pos_y = sink->x[1];
double old_pos_z = sink->x[2];
#ifdef SWIFT_DEBUG_CHECKS
if (!s->periodic && sink->time_bin != time_bin_inhibited) {
if (old_pos_x < 0. || old_pos_x > dim_x)
error("Particle outside of volume along X.");
if (old_pos_y < 0. || old_pos_y > dim_y)
error("Particle outside of volume along Y.");
if (old_pos_z < 0. || old_pos_z > dim_z)
error("Particle outside of volume along Z.");
}
#endif
/* Put it back into the simulation volume */
double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
/* Treat the case where a particle was wrapped back exactly onto
* the edge because of rounding issues (more accuracy around 0
* than around dim) */
if (pos_x == dim_x) pos_x = 0.0;
if (pos_y == dim_y) pos_y = 0.0;
if (pos_z == dim_z) pos_z = 0.0;
/* Get its cell index */
const int index =
cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
#ifdef SWIFT_DEBUG_CHECKS
if (index < 0 || index >= cdim[0] * cdim[1] * cdim[2])
error("Invalid index=%d cdim=[%d %d %d] p->x=[%e %e %e]", index, cdim[0],
cdim[1], cdim[2], pos_x, pos_y, pos_z);
if (pos_x >= dim_x || pos_y >= dim_y || pos_z >= dim_z || pos_x < 0. ||
pos_y < 0. || pos_z < 0.)
error("Particle outside of simulation box. p->x=[%e %e %e]", pos_x, pos_y,
pos_z);
#endif
/* Is this particle to be removed? */
if (sink->time_bin == time_bin_inhibited) {
ind[k] = -1;
++count_inhibited_sink;
} else if (sink->time_bin == time_bin_not_created) {
/* Is this a place-holder for on-the-fly creation? */
ind[k] = index;
cell_counts[index]++;
++count_extra_sink;
} else {
/* List its top-level cell index */
ind[k] = index;
cell_counts[index]++;
/* Compute minimal mass */
min_mass = min(min_mass, sink->mass);
/* Compute sum of velocity norm */
sum_vel_norm += sink->v[0] * sink->v[0] + sink->v[1] * sink->v[1] +
sink->v[2] * sink->v[2];
/* Update the position */
sink->x[0] = pos_x;
sink->x[1] = pos_y;
sink->x[2] = pos_z;
}
}
/* Write the counts back to the global array. */
for (int k = 0; k < s->nr_cells; k++)
if (cell_counts[k]) atomic_add(&data->cell_counts[k], cell_counts[k]);
free(cell_counts);
/* Write the count of inhibited and extra sinks */
if (count_inhibited_sink)
atomic_add(&data->count_inhibited_sink, count_inhibited_sink);
if (count_extra_sink) atomic_add(&data->count_extra_sink, count_extra_sink);
/* Write back the minimal part mass and velocity sum */
atomic_min_f(&s->min_sink_mass, min_mass);
atomic_add_f(&s->sum_sink_vel_norm, sum_vel_norm);
}
/**
* @brief Computes the cell index of all the particles.
*
* Also computes the minimal mass of all #part.
*
* @param s The #space.
* @param ind The array of indices to fill.
* @param cell_counts The cell counters to update.
* @param count_inhibited_parts (return) The number of #part to remove.
* @param count_extra_parts (return) The number of #part for on-the-fly
* creation.
* @param verbose Are we talkative ?
*/
void space_parts_get_cell_index(struct space *s, int *ind, int *cell_counts,
size_t *count_inhibited_parts,
size_t *count_extra_parts, int verbose) {
const ticks tic = getticks();
/* Re-set the counters */
s->min_part_mass = FLT_MAX;
s->sum_part_vel_norm = 0.f;
/* Pack the extra information */
struct space_index_data data;
data.s = s;
data.ind = ind;
data.cell_counts = cell_counts;
data.count_inhibited_part = 0;
data.count_inhibited_gpart = 0;
data.count_inhibited_spart = 0;
data.count_inhibited_bpart = 0;
data.count_inhibited_sink = 0;
data.count_extra_part = 0;
data.count_extra_gpart = 0;
data.count_extra_spart = 0;
data.count_extra_bpart = 0;
data.count_extra_sink = 0;
threadpool_map(&s->e->threadpool, space_parts_get_cell_index_mapper, s->parts,
s->nr_parts, sizeof(struct part), threadpool_auto_chunk_size,
&data);
*count_inhibited_parts = data.count_inhibited_part;
*count_extra_parts = data.count_extra_part;
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
/**
* @brief Computes the cell index of all the g-particles.
*
* Also computes the minimal mass of all dark-matter #gpart.
*
* @param s The #space.
* @param gind The array of indices to fill.
* @param cell_counts The cell counters to update.
* @param count_inhibited_gparts (return) The number of #gpart to remove.
* @param count_extra_gparts (return) The number of #gpart for on-the-fly
* creation.
* @param verbose Are we talkative ?
*/
void space_gparts_get_cell_index(struct space *s, int *gind, int *cell_counts,
size_t *count_inhibited_gparts,
size_t *count_extra_gparts, int verbose) {
const ticks tic = getticks();
/* Re-set the counters */
s->min_gpart_mass = FLT_MAX;
s->sum_gpart_vel_norm = 0.f;
/* Pack the extra information */
struct space_index_data data;
data.s = s;
data.ind = gind;
data.cell_counts = cell_counts;
data.count_inhibited_part = 0;
data.count_inhibited_gpart = 0;
data.count_inhibited_spart = 0;
data.count_inhibited_bpart = 0;
data.count_inhibited_sink = 0;
data.count_extra_part = 0;
data.count_extra_gpart = 0;
data.count_extra_spart = 0;
data.count_extra_bpart = 0;
data.count_extra_sink = 0;
threadpool_map(&s->e->threadpool, space_gparts_get_cell_index_mapper,
s->gparts, s->nr_gparts, sizeof(struct gpart),
threadpool_auto_chunk_size, &data);
*count_inhibited_gparts = data.count_inhibited_gpart;
*count_extra_gparts = data.count_extra_gpart;
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
/**
* @brief Computes the cell index of all the s-particles.
*
* Also computes the minimal mass of all #spart.
*
* @param s The #space.
* @param sind The array of indices to fill.
* @param cell_counts The cell counters to update.
* @param count_inhibited_sparts (return) The number of #spart to remove.
* @param count_extra_sparts (return) The number of #spart for on-the-fly
* creation.
* @param verbose Are we talkative ?
*/
void space_sparts_get_cell_index(struct space *s, int *sind, int *cell_counts,
size_t *count_inhibited_sparts,
size_t *count_extra_sparts, int verbose) {
const ticks tic = getticks();
/* Re-set the counters */
s->min_spart_mass = FLT_MAX;
s->sum_spart_vel_norm = 0.f;
/* Pack the extra information */
struct space_index_data data;
data.s = s;
data.ind = sind;
data.cell_counts = cell_counts;
data.count_inhibited_part = 0;
data.count_inhibited_gpart = 0;
data.count_inhibited_spart = 0;
data.count_inhibited_sink = 0;
data.count_inhibited_bpart = 0;
data.count_extra_part = 0;
data.count_extra_gpart = 0;
data.count_extra_spart = 0;
data.count_extra_bpart = 0;
data.count_extra_sink = 0;
threadpool_map(&s->e->threadpool, space_sparts_get_cell_index_mapper,
s->sparts, s->nr_sparts, sizeof(struct spart),
threadpool_auto_chunk_size, &data);
*count_inhibited_sparts = data.count_inhibited_spart;
*count_extra_sparts = data.count_extra_spart;
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
/**
* @brief Computes the cell index of all the sink-particles.
*
* @param s The #space.
* @param sink_ind The array of indices to fill.
* @param cell_counts The cell counters to update.
* @param count_inhibited_sinks (return) The number of #sink to remove.
* @param count_extra_sinks (return) The number of #sink for on-the-fly
* creation.
* @param verbose Are we talkative ?
*/
void space_sinks_get_cell_index(struct space *s, int *sink_ind,
int *cell_counts, size_t *count_inhibited_sinks,
size_t *count_extra_sinks, int verbose) {
const ticks tic = getticks();
/* Re-set the counters */
s->min_sink_mass = FLT_MAX;
s->sum_sink_vel_norm = 0.f;
/* Pack the extra information */
struct space_index_data data;
data.s = s;
data.ind = sink_ind;
data.cell_counts = cell_counts;
data.count_inhibited_part = 0;
data.count_inhibited_gpart = 0;
data.count_inhibited_spart = 0;
data.count_inhibited_bpart = 0;
data.count_inhibited_sink = 0;
data.count_extra_part = 0;
data.count_extra_gpart = 0;
data.count_extra_spart = 0;
data.count_extra_bpart = 0;
data.count_extra_sink = 0;
threadpool_map(&s->e->threadpool, space_sinks_get_cell_index_mapper, s->sinks,
s->nr_sinks, sizeof(struct sink), threadpool_auto_chunk_size,
&data);
*count_inhibited_sinks = data.count_inhibited_sink;
*count_extra_sinks = data.count_extra_sink;
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}
/**
* @brief Computes the cell index of all the b-particles.
*
* Also computes the minimal mass of all #bpart.
*
* @param s The #space.
* @param bind The array of indices to fill.
* @param cell_counts The cell counters to update.
* @param count_inhibited_bparts (return) The number of #bpart to remove.
* @param count_extra_bparts (return) The number of #bpart for on-the-fly
* creation.
* @param verbose Are we talkative ?
*/
void space_bparts_get_cell_index(struct space *s, int *bind, int *cell_counts,
size_t *count_inhibited_bparts,
size_t *count_extra_bparts, int verbose) {
const ticks tic = getticks();
/* Re-set the counters */
s->min_bpart_mass = FLT_MAX;
s->sum_bpart_vel_norm = 0.f;
/* Pack the extra information */
struct space_index_data data;
data.s = s;
data.ind = bind;
data.cell_counts = cell_counts;
data.count_inhibited_part = 0;
data.count_inhibited_gpart = 0;
data.count_inhibited_spart = 0;
data.count_inhibited_bpart = 0;
data.count_inhibited_sink = 0;
data.count_extra_part = 0;
data.count_extra_gpart = 0;
data.count_extra_spart = 0;
data.count_extra_bpart = 0;
data.count_extra_sink = 0;
threadpool_map(&s->e->threadpool, space_bparts_get_cell_index_mapper,
s->bparts, s->nr_bparts, sizeof(struct bpart),
threadpool_auto_chunk_size, &data);
*count_inhibited_bparts = data.count_inhibited_bpart;
*count_extra_bparts = data.count_extra_bpart;
if (verbose)
message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
clocks_getunit());
}