43 this->
pdata =
nullptr;
47 for (
int iaxis = 0; iaxis < 3; iaxis++) {
63 "Number of particles is non-positive.\n"
83 if (this->
pdata !=
nullptr) {
95 return this->
pdata[pid];
104 const std::string& catalogue_filepath,
105 const std::string& catalogue_columns,
108 if (!(this->
source.empty())) {
111 "Catalogue already loaded from another source: %s.", this->
source.c_str()
115 "Catalogue already loaded from another source: %s.\n",
119 this->
source =
"extfile:" + catalogue_filepath;
126 const std::vector<std::string> names_ordered = {
127 "x",
"y",
"z",
"nz",
"ws",
"wc"
130 std::istringstream iss(catalogue_columns);
131 std::vector<std::string> colnames;
133 while (std::getline(iss, name,
',')) {
134 colnames.push_back(name);
138 std::vector<int> name_indices(names_ordered.size(), -1);
139 for (
int iname = 0; iname < int(names_ordered.size()); iname++) {
140 std::ptrdiff_t col_idx = std::distance(
142 std::find(colnames.begin(), colnames.end(), names_ordered[iname])
144 if (0 <= col_idx && col_idx <
int(colnames.size())) {
145 name_indices[iname] = col_idx;
150 if (name_indices[3] == -1) {
153 "Catalogue 'nz' field is unavailable and "
154 "will be set to the mean density in the bounding box (source=%s).",
166 fin.open(catalogue_filepath.c_str(), std::ios::in);
178 std::string line_str;
179 while (std::getline(fin, line_str)) {
184 if (line_str.empty() || line_str[0] ==
'#') {
continue;}
195 double nz_box_default = 0.;
197 nz_box_default = this->
ntotal / volume;
200 fin.open(catalogue_filepath.c_str(), std::ios::in);
205 while (std::getline(fin, line_str)) {
210 if (line_str.empty() || line_str[0] ==
'#') {
continue;}
213 std::vector<double> row;
215 std::stringstream ss(
216 line_str, std::ios_base::out | std::ios_base::in | std::ios_base::binary
218 while (ss >> entry) {row.push_back(entry);}
221 this->
pdata[idx_line].
pos[0] = row[name_indices[0]];
222 this->
pdata[idx_line].
pos[1] = row[name_indices[1]];
223 this->
pdata[idx_line].
pos[2] = row[name_indices[2]];
225 if (name_indices[3] != -1) {
226 nz = row[name_indices[3]];
231 if (name_indices[4] != -1) {
232 ws = row[name_indices[4]];
237 if (name_indices[5] != -1) {
238 wc = row[name_indices[5]];
246 this->
pdata[idx_line].
w = ws * wc;
267 std::vector<double> x, std::vector<double> y, std::vector<double> z,
268 std::vector<double> nz, std::vector<double> ws, std::vector<double> wc
276 &&
ntotal ==
int(z.size())
277 &&
ntotal ==
int(nz.size())
278 &&
ntotal ==
int(ws.size())
279 &&
ntotal ==
int(wc.size())
283 "Inconsistent particle data dimensions (source=%s).",
288 "Inconsistent particle data dimensions (source=%s).\n",
297#pragma omp parallel for simd
299 for (
int pid = 0; pid <
ntotal; pid++) {
306 this->
pdata[pid].
w = ws[pid] * wc[pid];
324 if (this->
pdata ==
nullptr) {
334#if defined(__GNUC__) && !defined(__clang__)
335#pragma omp parallel for simd reduction(+:wtotal, wstotal)
337#pragma omp parallel for reduction(+:wtotal, wstotal)
340 for (
int pid = 0; pid < this->
ntotal; pid++) {
351 "ntotal = %d, wtotal = %.3f, wstotal = %.3f (source=%s).",
352 this->ntotal, this->wtotal, this->
wstotal, this->
source.c_str()
358 if (this->
pdata ==
nullptr) {
367 for (
int iaxis = 0; iaxis < 3; iaxis++) {
374#pragma omp parallel for reduction(min:pos_min) reduction(max:pos_max)
376 for (
int pid = 0; pid < this->
ntotal; pid++) {
377 for (
int iaxis = 0; iaxis < 3; iaxis++) {
385 for (
int iaxis = 0; iaxis < 3; iaxis++) {
386 this->pos_min[iaxis] =
pos_min[iaxis];
387 this->pos_max[iaxis] =
pos_max[iaxis];
393 "Extents of particle coordinates: "
394 "{'x': (%.3f, %.3f | %.3f),"
395 " 'y': (%.3f, %.3f | %.3f),"
396 " 'z': (%.3f, %.3f | %.3f)} "
398 this->pos_min[0], this->pos_max[0], this->
pos_span[0],
399 this->pos_min[1], this->pos_max[1], this->
pos_span[1],
400 this->pos_min[2], this->pos_max[2], this->
pos_span[2],
412 if (this->
pdata ==
nullptr) {
420#pragma omp parallel for
422 for (
int pid = 0; pid < this->
ntotal; pid++) {
423 for (
int iaxis = 0; iaxis < 3; iaxis++) {
424 this->
pdata[pid].
pos[iaxis] -= dpos[iaxis];
431void ParticleCatalogue::\
432offset_coords_for_periodicity(
const double boxsize[3]) {
434#pragma omp parallel for
436 for (
int pid = 0; pid < this->
ntotal; pid++) {
437 for (
int iaxis = 0; iaxis < 3; iaxis++) {
438 if (this->
pdata[pid].pos[iaxis] >= boxsize[iaxis]) {
439 this->
pdata[pid].
pos[iaxis] = std::fmod(
440 this->
pdata[pid].pos[iaxis], boxsize[iaxis]
443 if (this->
pdata[pid].pos[iaxis] < 0.) {
444 this->
pdata[pid].
pos[iaxis] = std::fmod(
445 this->
pdata[pid].pos[iaxis], boxsize[iaxis]
456 const double boxsize[3]
459 for (
int iaxis = 0; iaxis < 3; iaxis++) {
460 if (catalogue.
pos_span[iaxis] > boxsize[iaxis]) {
463 "Catalogue extent exceeds the box size along axis %d: "
464 "span = %.3f, boxsize = %.3f (source=%s). "
465 "Some particles may lie outside the box after centring.",
467 catalogue.
pos_span[iaxis], boxsize[iaxis],
479 xmid - boxsize[0]/2., ymid - boxsize[1]/2., zmid - boxsize[2]/2.
487 const double boxsize[3]
490 for (
int iaxis = 0; iaxis < 3; iaxis++) {
491 if (catalogue.
pos_span[iaxis] > boxsize[iaxis]) {
494 "Catalogue extent exceeds the box size along axis %d: "
495 "span = %.3f, boxsize = %.3f (source=%s). "
496 "Some particles may lie outside the box after centring.",
498 catalogue.
pos_span[iaxis], boxsize[iaxis],
506 for (
int iaxis = 0; iaxis < 3; iaxis++) {
507 if (catalogue_ref.
pos_span[iaxis] > boxsize[iaxis]) {
510 "Catalogue extent exceeds the box size along axis %d: "
511 "span = %.3f, boxsize = %.3f (source=%s). "
512 "Some particles may lie outside the box after centring.",
514 catalogue_ref.
pos_span[iaxis], boxsize[iaxis],
515 catalogue_ref.
source.c_str()
521 double xmid = (catalogue_ref.
pos_min[0] + catalogue_ref.
pos_max[0]) / 2.;
522 double ymid = (catalogue_ref.
pos_min[1] + catalogue_ref.
pos_max[1]) / 2.;
523 double zmid = (catalogue_ref.
pos_min[2] + catalogue_ref.
pos_max[2]) / 2.;
526 xmid - boxsize[0]/2., ymid - boxsize[1]/2., zmid - boxsize[2]/2.
535 const double boxsize[3],
const double boxsize_pad[3]
538 for (
int iaxis = 0; iaxis < 3; iaxis++) {
539 if (catalogue.
pos_span[iaxis] > boxsize[iaxis]) {
542 "Catalogue extent exceeds the box size along axis %d: "
543 "span = %.3f, boxsize = %.3f (source=%s). "
544 "Some particles may lie outside the box after padding.",
546 catalogue.
pos_span[iaxis], boxsize[iaxis],
554 catalogue.
pos_min[0] - boxsize_pad[0] * boxsize[0],
555 catalogue.
pos_min[1] - boxsize_pad[1] * boxsize[1],
556 catalogue.
pos_min[2] - boxsize_pad[2] * boxsize[2]
564 const double boxsize[3],
const double boxsize_pad[3]
567 for (
int iaxis = 0; iaxis < 3; iaxis++) {
568 if (catalogue.
pos_span[iaxis] > boxsize[iaxis]) {
571 "Catalogue extent exceeds the box size along axis %d: "
572 "span = %.3f, boxsize = %.3f (source=%s). "
573 "Some particles may lie outside the box after padding.",
575 catalogue.
pos_span[iaxis], boxsize[iaxis],
583 for (
int iaxis = 0; iaxis < 3; iaxis++) {
584 if (catalogue_ref.
pos_span[iaxis] > boxsize[iaxis]) {
587 "Catalogue extent exceeds the box size along axis %d: "
588 "span = %.3f, boxsize = %.3f (source=%s). "
589 "Some particles may lie outside the box after padding.",
591 catalogue_ref.
pos_span[iaxis], boxsize[iaxis],
592 catalogue_ref.
source.c_str()
599 catalogue_ref.
pos_min[0] - boxsize_pad[0] * boxsize[0],
600 catalogue_ref.
pos_min[1] - boxsize_pad[1] * boxsize[1],
601 catalogue_ref.
pos_min[2] - boxsize_pad[2] * boxsize[2]
610 const double boxsize[3],
const int ngrid[3],
const double ngrid_pad[3]
618 dvec[0] -= ngrid_pad[0] * boxsize[0] / double(ngrid[0]);
619 dvec[1] -= ngrid_pad[1] * boxsize[1] / double(ngrid[1]);
620 dvec[2] -= ngrid_pad[2] * boxsize[2] / double(ngrid[2]);
627 const double boxsize[3],
const int ngrid[3],
const double ngrid_pad[3]
632 catalogue_ref.
pos_min[0] - ngrid_pad[0] * boxsize[0] / double(ngrid[0]),
633 catalogue_ref.
pos_min[1] - ngrid_pad[1] * boxsize[1] / double(ngrid[1]),
634 catalogue_ref.
pos_min[2] - ngrid_pad[2] * boxsize[2] / double(ngrid[2])
void initialise_particles(const int num)
Initialise particle data container.
static void centre_in_box(ParticleCatalogue &catalogue, const double boxsize[3])
Centre a catalogue in a box.
int load_particle_data(std::vector< double > x, std::vector< double > y, std::vector< double > z, std::vector< double > nz, std::vector< double > ws, std::vector< double > wc)
Read in particle data.
void calc_pos_extents(bool init=true)
Calculate the extents of particle positions.
~ParticleCatalogue()
Destruct the particle catalogue.
ParticleCatalogue(int verbose=-1)
Construct the particle catalogue with initial values.
std::string source
catalogue source
void reset_particles()
Reset particle data container.
void calc_total_weights()
Calculate total overall weight of particles.
ParticleData & operator[](const int pid)
Return individual particle information.
void offset_coords(const double dpos[3])
Offset particle positions by a given vector.
void finalise_particles()
Finalise particle data container.
static void pad_grids(ParticleCatalogue &catalogue, const double boxsize[3], const int ngrid[3], const double ngrid_pad[3])
Pad a catalogue in a box.
double pos_span[3]
span of particle coordinates
ParticleData * pdata
particle data
int load_catalogue_file(const std::string &catalogue_filepath, const std::string &catalogue_columns, double volume=0.)
Read in a catalogue file.
double pos_min[3]
minimum values of particle coordinates
int ntotal
total number of particles
static void pad_in_box(ParticleCatalogue &catalogue, const double boxsize[3], const double boxsize_pad[3])
Pad a catalogue in a box.
double wtotal
total overall weight of particles
double wstotal
total sample weight of particles
double pos_max[3]
maximum values of particle coordinates
Exception raised when an input/output operation fails.
Exception raised when the data to be operated on are invalid.
Exception raised when parameters are invalid.
void info(const char *fmt_string,...)
Emit a information-level message.
void error(const char *fmt_string,...)
Emit a warning-level message.
void warn(const char *fmt_string,...)
Emit a warning-level message.
void reset_level(LogLevel level)
Reset the logger threshold level.
double gbytesMem
current memory usage in gibibytes
double size_in_gb(long long num)
Return size in gibibytes.
void update_maxmem()
Update the maximum memory usage estimate.
Logger logger
default logger (at NSET logging level)
Particle containers with I/O methods and operations.
double pos[3]
particle position vector
double w
particle overall weight
double ws
particle sample weight
double nz
redshift-dependent expected number density
double wc
particle clustering weight