33const double eps_norm = 1.e-5;
46 return (2*ell + 1) * (2*ELL + 1)
59 if (particles.
pdata ==
nullptr) {
69#if defined(__GNUC__) && !defined(__clang__)
70#pragma omp parallel for simd reduction(+:norm)
72#pragma omp parallel for reduction(+:norm)
75 for (
int pid = 0; pid < particles.
ntotal; pid++) {
76 norm += particles[pid].ws
77 * particles[pid].nz * std::pow(particles[pid].wc, 2);
83 "Particle 'nz' values appear to be all zeros. "
84 "Check the input catalogue contains valid 'nz' field."
88 "Particle 'nz' values appear to be all zeros. "
89 "Check the input catalogue contains valid 'nz' field."
93 double norm_factor = 1. / (alpha * norm);
106 norm_factor /= std::pow(alpha, 2);
117 double pos_min_data[3] = {0., 0., 0.};
118 double pos_min_rand[3] = {0., 0., 0.};
119 for (
int iaxis = 0; iaxis < 3; iaxis++) {
120 pos_min_data[iaxis] = particles_data.
pos_min[iaxis];
121 pos_min_rand[iaxis] = particles_rand.
pos_min[iaxis];
126 double ngrid_pad[3] = {
130 particles_data, particles_rand,
136 double boxsize_pad[3] = {
140 particles_data, particles_rand,
147 particles_data, particles_rand, params.
boxsize
151 double pos_offset_data[3] = {0., 0., 0.};
152 double pos_offset_rand[3] = {0., 0., 0.};
153 for (
int iaxis = 0; iaxis < 3; iaxis++) {
154 pos_offset_data[iaxis] = particles_data.
pos_min[iaxis] - pos_min_data[iaxis];
155 pos_offset_rand[iaxis] = particles_rand.
pos_min[iaxis] - pos_min_rand[iaxis];
162 fftw_complex* weight_data =
nullptr;
163 weight_data = fftw_alloc_complex(particles_data.
ntotal);
165 fftw_complex* weight_rand =
nullptr;
166 weight_rand = fftw_alloc_complex(particles_rand.
ntotal);
173#if defined(__GNUC__) && !defined(__clang__)
174#pragma omp parallel for simd
176#pragma omp parallel for
179 for (
int pid = 0; pid < particles_data.
ntotal; pid++) {
180 weight_data[pid][0] = particles_data[pid].w;
181 weight_data[pid][1] = 0.;
185#if defined(__GNUC__) && !defined(__clang__)
186#pragma omp parallel for simd
188#pragma omp parallel for
191 for (
int pid = 0; pid < particles_rand.
ntotal; pid++) {
192 weight_rand[pid][0] = particles_rand[pid].w;
193 weight_rand[pid][1] = 0.;
199 fftw_free(weight_data); weight_data =
nullptr;
200 fftw_free(weight_rand); weight_rand =
nullptr;
209#if defined(__GNUC__) && !defined(__clang__)
210#pragma omp parallel for simd reduction(+:norm)
212#pragma omp parallel for reduction(+:norm)
215 for (
long long gid = 0; gid < params.
nmesh; gid++) {
216 norm += mesh_data.
field[gid][0] * mesh_rand.
field[gid][0];
219 double vol_cell = params.
volume / double(params.
nmesh);
221 double norm_factor = 1. / (alpha * vol_cell * norm);
234 double padding,
double cellsize,
const std::string& assignment
239 double boxsize_norm = (1. + padding) * std::max(
244 int ngrid_norm = std::ceil(boxsize_norm / cellsize);
246 ngrid_norm += ngrid_norm % 2;
247 boxsize_norm = ngrid_norm * cellsize;
249 for (
int iaxis = 0; iaxis < 3; iaxis++) {
250 params_norm.
boxsize[iaxis] = boxsize_norm;
251 params_norm.
ngrid[iaxis] = ngrid_norm;
260 particles_data, particles_rand, params_norm, alpha
274 if (particles.
pdata ==
nullptr) {
281 double shotnoise = 0.;
284#if defined(__GNUC__) && !defined(__clang__)
285#pragma omp parallel for simd reduction(+:shotnoise)
287#pragma omp parallel for reduction(+:shotnoise)
290 for (
int pid = 0; pid < particles.
ntotal; pid++) {
292 std::pow(particles[pid].ws, 2) * std::pow(particles[pid].wc, 2);
301 double alpha,
int ell,
int m
303 double sn_data_real = 0., sn_data_imag = 0.;
306#pragma omp parallel for reduction(+:sn_data_real, sn_data_imag)
308 for (
int pid = 0; pid < particles_data.
ntotal; pid++) {
310 los_data[pid].
pos[0], los_data[pid].
pos[1], los_data[pid].
pos[2]
316 std::complex<double> sn_part = ylm * std::pow(particles_data[pid].w, 2);
317 double sn_part_real = sn_part.real();
318 double sn_part_imag = sn_part.imag();
320 sn_data_real += sn_part_real;
321 sn_data_imag += sn_part_imag;
324 std::complex<double> sn_data(sn_data_real, sn_data_imag);
326 double sn_rand_real = 0., sn_rand_imag = 0.;
329#pragma omp parallel for reduction(+:sn_rand_real, sn_rand_imag)
331 for (
int pid = 0; pid < particles_rand.
ntotal; pid++) {
333 los_rand[pid].
pos[0], los_rand[pid].
pos[1], los_rand[pid].
pos[2]
339 std::complex<double> sn_part = ylm * std::pow(particles_rand[pid].w, 2);
340 double sn_part_real = sn_part.real();
341 double sn_part_imag = sn_part.imag();
343 sn_rand_real += sn_part_real;
344 sn_rand_imag += sn_part_imag;
347 std::complex<double> sn_rand(sn_rand_real, sn_rand_imag);
349 return sn_data + std::pow(alpha, 2) * sn_rand;
354 double alpha,
int ell,
int m
356 double sn_real = 0., sn_imag = 0.;
359#pragma omp parallel for reduction(+:sn_real, sn_imag)
361 for (
int pid = 0; pid < particles.
ntotal; pid++) {
362 double los_[3] = {los[pid].
pos[0], los[pid].
pos[1], los[pid].
pos[2]};
367 std::complex<double> sn_part = ylm * std::pow(particles[pid].w, 2);
368 double sn_part_real = sn_part.real();
369 double sn_part_imag = sn_part.imag();
371 sn_real += sn_part_real;
372 sn_imag += sn_part_imag;
375 std::complex<double> sn(sn_real, sn_imag);
377 return std::pow(alpha, 2) * sn;
398 "Computing power spectrum from paired survey-type catalogues..."
408 int ell1 = params.
ELL;
411 int* nmodes_save =
new int[kbinning.
num_bins]();
412 double* k_save =
new double[kbinning.
num_bins]();
413 std::complex<double>* pk_save =
new std::complex<double>[kbinning.
num_bins];
414 std::complex<double>* sn_save =
new std::complex<double>[kbinning.
num_bins];
420#if defined(TRV_USE_OMP) && defined(TRV_USE_FFTWOMP)
426 MeshField dn_00(params,
true,
"`dn_00`");
428 catalogue_data, catalogue_rand, los_data, los_rand, alpha, 0, 0
434 for (
int M_ = - params.
ELL; M_ <= params.
ELL; M_++) {
435 MeshField dn_LM(params,
true,
"`dn_LM`");
437 catalogue_data, catalogue_rand, los_data, los_rand, alpha, params.
ELL, M_
442 catalogue_data, catalogue_rand, los_data, los_rand, alpha, params.
ELL, M_
447 for (
int m1 = - ell1; m1 <= ell1; m1++) {
452 dn_LM, dn_00, sn_amp, ell1, m1, kbinning
455 for (
int ibin = 0; ibin < kbinning.
num_bins; ibin++) {
456 pk_save[ibin] += coupling * stats_2pt.
pk[ibin];
457 sn_save[ibin] += coupling * stats_2pt.
sn[ibin];
460 if (M_ == 0 && m1 == 0) {
461 for (
int ibin = 0; ibin < kbinning.
num_bins; ibin++) {
462 nmodes_save[ibin] = stats_2pt.
nmodes[ibin];
463 k_save[ibin] = stats_2pt.
k[ibin];
469 trvs::logger.stat(
"Power spectrum term computed at order M = %d.", M_);
478 for (
int ibin = 0; ibin < kbinning.
num_bins; ibin++) {
480 powspec_out.
keff.push_back(k_save[ibin]);
481 powspec_out.
nmodes.push_back(nmodes_save[ibin]);
482 powspec_out.
pk_raw.push_back(norm_factor * pk_save[ibin]);
483 powspec_out.
pk_shot.push_back(norm_factor * sn_save[ibin]);
487 delete[] nmodes_save;
delete[] k_save;
delete[] pk_save;
delete[] sn_save;
491 "... computed power spectrum from paired survey-type catalogues."
508 "Computing two-point correlation function from "
509 "paired survey-type catalogues..."
519 int ell1 = params.
ELL;
522 int* npairs_save =
new int[rbinning.
num_bins]();
523 double* r_save =
new double[rbinning.
num_bins]();
524 std::complex<double>* xi_save =
new std::complex<double>[rbinning.
num_bins];
530#if defined(TRV_USE_OMP) && defined(TRV_USE_FFTWOMP)
536 MeshField dn_00(params,
true,
"`dn_00`");
538 catalogue_data, catalogue_rand, los_data, los_rand, alpha, 0, 0
544 for (
int M_ = - params.
ELL; M_ <= params.
ELL; M_++) {
545 MeshField dn_LM(params,
true,
"`dn_LM`");
547 catalogue_data, catalogue_rand, los_data, los_rand, alpha, params.
ELL, M_
552 catalogue_data, catalogue_rand, los_data, los_rand, alpha, params.
ELL, M_
557 for (
int m1 = - ell1; m1 <= ell1; m1++) {
562 dn_LM, dn_00, sn_amp, ell1, m1, rbinning
565 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
566 xi_save[ibin] += coupling * stats_2pt.
xi[ibin];
569 if (M_ == 0 && m1 == 0) {
570 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
571 npairs_save[ibin] = stats_2pt.
npairs[ibin];
572 r_save[ibin] = stats_2pt.
r[ibin];
579 "Two-point correlation function term computed at order M = %d.", M_
589 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
591 corrfunc_out.
reff.push_back(r_save[ibin]);
592 corrfunc_out.
npairs.push_back(npairs_save[ibin]);
593 corrfunc_out.
xi.push_back(norm_factor * xi_save[ibin]);
597 delete[] npairs_save;
delete[] r_save;
delete[] xi_save;
601 "... computed two-point correlation function "
602 "from paired survey-type catalogues."
618 "Computing power spectrum from a periodic-box simulation-type catalogue "
619 "in the global plane-parallel approximation."
627 int* nmodes_save =
new int[kbinning.
num_bins]();
628 double* k_save =
new double[kbinning.
num_bins]();
629 std::complex<double>* pk_save =
new std::complex<double>[kbinning.
num_bins];
630 std::complex<double>* sn_save =
new std::complex<double>[kbinning.
num_bins];
633 double norm = double(catalogue_data.
ntotal) * double(catalogue_data.
ntotal)
635 if (std::fabs(1 - norm * norm_factor) > eps_norm) {
638 "Power spectrum normalisation input differs from "
639 "expected value for an unweight field in a periodic box."
648#if defined(TRV_USE_OMP) && defined(TRV_USE_FFTWOMP)
659 std::complex<double> sn_amp = double(catalogue_data.
ntotal);
665 dn, dn, sn_amp, params.
ELL, 0, kbinning
668 for (
int ibin = 0; ibin < kbinning.
num_bins; ibin++) {
669 nmodes_save[ibin] = stats_2pt.
nmodes[ibin];
670 k_save[ibin] = stats_2pt.
k[ibin];
671 pk_save[ibin] += double(2*params.
ELL + 1) * stats_2pt.
pk[ibin];
672 sn_save[ibin] += double(2*params.
ELL + 1) * stats_2pt.
sn[ibin];
681 for (
int ibin = 0; ibin < kbinning.
num_bins; ibin++) {
683 powspec_out.
keff.push_back(k_save[ibin]);
684 powspec_out.
nmodes.push_back(nmodes_save[ibin]);
685 powspec_out.
pk_raw.push_back(norm_factor * pk_save[ibin]);
686 powspec_out.
pk_shot.push_back(norm_factor * sn_save[ibin]);
690 delete[] nmodes_save;
delete[] k_save;
delete[] pk_save;
delete[] sn_save;
694 "... computed power spectrum "
695 "from a periodic-box simulation-type catalogue "
696 "in the global plane-parallel approximation."
712 "Computing two-point correlation function "
713 "from a periodic-box simulation-type catalogue "
714 "in the global plane-parallel approximation."
722 int* npairs_save =
new int[rbinning.
num_bins]();
723 double* r_save =
new double[rbinning.
num_bins]();
724 std::complex<double>* xi_save =
new std::complex<double>[rbinning.
num_bins];
727 double norm = double(catalogue_data.
ntotal) * double(catalogue_data.
ntotal)
729 if (std::fabs(1 - norm * norm_factor) > eps_norm) {
732 "Two-point correlation function normalisation input differs from "
733 "expected value for an unweight field in a periodic box."
742#if defined(TRV_USE_OMP) && defined(TRV_USE_FFTWOMP)
753 std::complex<double> sn_amp = double(catalogue_data.
ntotal);
759 dn, dn, sn_amp, params.
ELL, 0, rbinning
762 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
763 npairs_save[ibin] = stats_2pt.
npairs[ibin];
764 r_save[ibin] = stats_2pt.
r[ibin];
765 xi_save[ibin] += double(2*params.
ELL + 1) * stats_2pt.
xi[ibin];
774 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
776 corrfunc_out.
reff.push_back(r_save[ibin]);
777 corrfunc_out.
npairs.push_back(npairs_save[ibin]);
778 corrfunc_out.
xi.push_back(norm_factor * xi_save[ibin]);
782 delete[] npairs_save;
delete[] r_save;
delete[] xi_save;
786 "... computed two-point correlation function "
787 "from a periodic-box simulation-type catalogue "
788 "in the global plane-parallel approximation."
798 double alpha,
double norm_factor
804 "Computing two-point correlation function window "
805 "from a random catalogue..."
814 int ell1 = params.
ELL;
817 int* npairs_save =
new int[rbinning.
num_bins]();
818 double* r_save =
new double[rbinning.
num_bins]();
819 std::complex<double>* xi_save =
new std::complex<double>[rbinning.
num_bins];
825#if defined(TRV_USE_OMP) && defined(TRV_USE_FFTWOMP)
831 MeshField dn_00(params,
true,
"`dn_00`");
837 for (
int M_ = - params.
ELL; M_ <= params.
ELL; M_++) {
838 MeshField dn_LM(params,
true,
"`dn_LM`");
840 catalogue_rand, los_rand, alpha, params.
ELL, M_
845 catalogue_rand, los_rand, alpha, params.
ELL, M_
850 for (
int m1 = - ell1; m1 <= ell1; m1++) {
855 dn_LM, dn_00, sn_amp, ell1, m1, rbinning
858 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
859 xi_save[ibin] += coupling * stats_2pt.
xi[ibin];
862 if (M_ == 0 && m1 == 0) {
863 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
864 npairs_save[ibin] = stats_2pt.
npairs[ibin];
865 r_save[ibin] = stats_2pt.
r[ibin];
872 "Two-point correlation function window term computed at order M = %d.",
883 for (
int ibin = 0; ibin < rbinning.
num_bins; ibin++) {
885 corrfunc_win_out.
reff.push_back(r_save[ibin]);
886 corrfunc_win_out.
npairs.push_back(npairs_save[ibin]);
887 corrfunc_win_out.
xi.push_back(norm_factor * xi_save[ibin]);
891 delete[] npairs_save;
delete[] r_save;
delete[] xi_save;
895 "... computed two-point correlation function window "
896 "from a random catalogue."
900 return corrfunc_win_out;
Isotropic coordinate binning.
std::vector< double > bin_centres
bin centres
int num_bins
number of bins
Field (pseudo-two-point) statistics.
std::vector< std::complex< double > > sn
shot-noise power in bins
std::vector< std::complex< double > > pk
pseudo power spectrum in bins
std::vector< int > nmodes
number of wavevector modes in bins
std::vector< double > k
average wavenumber in bins
std::vector< std::complex< double > > xi
pseudo two-point correlation function in bins
std::vector< int > npairs
number of separation pairs in bins
void compute_ylm_wgtd_2pt_stats_in_fourier(MeshField &field_a, MeshField &field_b, std::complex< double > shotnoise_amp, int ell, int m, trv::Binning &kbinning)
Compute binned two-point statistics in Fourier space.
void compute_ylm_wgtd_2pt_stats_in_config(MeshField &field_a, MeshField &field_b, std::complex< double > shotnoise_amp, int ell, int m, trv::Binning &rbinning)
Compute binned two-point statistics in configuration space.
Discretely sampled field on a mesh grid from particle catalogues.
void assign_weighted_field_to_mesh(ParticleCatalogue &particles, fftw_complex *weights)
Assign a weighted field to a mesh by interpolation scheme.
double calc_grid_based_powlaw_norm(ParticleCatalogue &particles, int order)
void fourier_transform()
Fourier transform the field.
void compute_ylm_wgtd_field(ParticleCatalogue &particles_data, ParticleCatalogue &particles_rand, LineOfSight *los_data, LineOfSight *los_rand, double alpha, int ell, int m)
Compute the weighted field (fluctuations) further weighted by the reduced spherical harmonics.
fftw_complex * field
complex field on mesh
void compute_unweighted_field_fluctuations_insitu(ParticleCatalogue &particles)
Compute the unweighted field fluctuations.
std::string alignment
box alignment: {"centre" (default), "pad"}
long long nmesh
number of mesh grid cells
std::string assignment
mesh assignment scheme: {"ngp", "cic", "tsc" (default), "pcs"}
int ELL
spherical degree associated with the line of sight
double padfactor
padding factor
double volume
box volume (in Mpc^3/h^3)
std::string padscale
padding scale (if alignment is "pad"): {"box" (default), "grid"}
int ngrid[3]
grid cell number in each dimension
int validate(bool init=false)
Validate parameters.
double boxsize[3]
box size (in Mpc/h) in each dimension
static void centre_in_box(ParticleCatalogue &catalogue, const double boxsize[3])
Centre a catalogue in a box.
void offset_coords(const double dpos[3])
Offset particle positions by a given vector.
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
double pos_min[3]
minimum 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 wstotal
total sample weight of particles
static std::complex< double > calc_reduced_spherical_harmonic(const int ell, const int m, double pos[3])
Calculate the reduced spherical harmonic.
Exception raised when the data to be operated on are invalid.
const double eps_coupling
zero-tolerance for Wigner 3-j coupling coefficients
double wigner_3j(int j1, int j2, int j3, int m1, int m2, int m3)
Calculate Wigner 3-j symbol.
double gbytesMem
current memory usage in gibibytes
void update_maxmem(bool gpu=false)
Update the maximum memory usage estimate.
double size_in_gb(long long num)
Return size in gibibytes.
bool is_gpu_enabled()
Check if GPU mode is enabled.
Logger logger
default logger (at NSET logging level)
double calc_powspec_shotnoise_from_particles(ParticleCatalogue &particles, double alpha=1.)
Calculate particle-based power spectrum shot noise level.
trv::TwoPCFWindowMeasurements compute_corrfunc_window(trv::ParticleCatalogue &catalogue_rand, trv::LineOfSight *los_rand, trv::ParameterSet ¶ms, trv::Binning rbinning, double alpha, double norm_factor)
Compute two-point correlation function window from a random catalogue and optionally save the results...
trv::TwoPCFMeasurements compute_corrfunc(ParticleCatalogue &catalogue_data, ParticleCatalogue &catalogue_rand, LineOfSight *los_data, LineOfSight *los_rand, trv::ParameterSet ¶ms, trv::Binning &rbinning, double norm_factor)
Compute two-point correlation function from paired survey-type catalogues.
double calc_coupling_coeff_2pt(int ell, int ELL, int m, int M)
Calculate the coupling coefficient for spherical-harmonic components of full two-point statistics.
std::complex< double > calc_ylm_wgtd_shotnoise_amp_for_powspec(ParticleCatalogue &particles_data, ParticleCatalogue &particles_rand, LineOfSight *los_data, LineOfSight *los_rand, double alpha, int ell, int m)
Calculate power spectrum shot noise weighted by reduced spherical harmonics.
trv::PowspecMeasurements compute_powspec_in_gpp_box(ParticleCatalogue &catalogue_data, trv::ParameterSet ¶ms, trv::Binning kbinning, double norm_factor)
Compute power spectrum in a periodic box in the global plane-parallel approximation.
double calc_powspec_normalisation_from_particles(ParticleCatalogue &particles, double alpha=1.)
Calculate particle-based power spectrum normalisation.
double calc_powspec_normalisation_from_mesh(trv::ParticleCatalogue &particles, trv::ParameterSet ¶ms, double alpha=1.)
Calculate mesh-based power spectrum normalisation.
trv::PowspecMeasurements compute_powspec(ParticleCatalogue &catalogue_data, ParticleCatalogue &catalogue_rand, LineOfSight *los_data, LineOfSight *los_rand, trv::ParameterSet ¶ms, trv::Binning &kbinning, double norm_factor)
Compute power spectrum from paired survey-type catalogues.
trv::TwoPCFMeasurements compute_corrfunc_in_gpp_box(ParticleCatalogue &catalogue_data, trv::ParameterSet ¶ms, trv::Binning &rbinning, double norm_factor)
Compute two-point correlation function in a periodic box in the global plane-parallel approximation.
double calc_powspec_normalisation_from_meshes(trv::ParticleCatalogue &particles_data, trv::ParticleCatalogue &particles_rand, trv::ParameterSet ¶ms, double alpha)
Calculate power spectrum normalisation from mixed meshes.
double pos[3]
3-d position vector
Power spectrum measurements.
int dim
dimension of data vector
std::vector< double > kbin
central wavenumber in bins
std::vector< int > nmodes
std::vector< std::complex< double > > pk_shot
power spectrum shot noise
std::vector< double > keff
effective wavenumber in bins
std::vector< std::complex< double > > pk_raw
power spectrum raw measurements (with normalisation and shot noise)
Two-point correlation function measurements.
std::vector< double > rbin
central separation in bins
std::vector< int > npairs
int dim
dimension of data vector
std::vector< std::complex< double > > xi
two-point correlation function measurements (with normalisation)
std::vector< double > reff
effective separation in bins
Two-point correlation function window measurements.
std::vector< std::complex< double > > xi
int dim
dimension of data vector
std::vector< double > reff
effective separation in bins
std::vector< double > rbin
central separation in bins
std::vector< int > npairs
Two-point statistic computations.