12 #include "CBRNG_Random.h" 19 static T mean(
const std::vector<T>& data)
23 #pragma omp parallel for reduction(+:tmp) 24 for (
auto it = data.begin(); it < data.end(); ++it) tmp += *it;
26 return tmp / data.size();
39 #pragma omp parallel for reduction(+:tmp) 40 for (
auto it = data.begin(); it < data.end(); ++it) tmp +=
pow2(*it-mean);
42 return sqrt(tmp / data.size());
51 static T min(
const std::vector<T>& data)
53 return *std::min_element(data.begin(), data.end());
61 static T max(
const std::vector<T>& data)
63 return *std::max_element(data.begin(), data.end());
72 unpert_pos[0] = (par_index / (par_per_dim * par_per_dim)) * Ng;
73 unpert_pos[1] = ((par_index / par_per_dim) % par_per_dim) * Ng;
74 unpert_pos[2] = (par_index % par_per_dim) * Ng;
79 for (
size_t i = 0; i < 3; i++) displ_field[i] = vel_field[i](unpert_pos);
89 #pragma omp parallel for private(unpert_pos) 90 for(
size_t i=0; i< Np; i++)
105 #pragma omp parallel for private(unpert_pos, velocity) 106 for(
size_t i=0; i< Np; i++)
116 BOOST_LOG_TRIVIAL(debug) <<
"Setting initial positions of particles...";
128 #pragma omp parallel for private(unpert_pos, velocity, pert_pos) 129 for(
size_t i=0; i< Np; i++)
133 pert_pos = velocity*D + unpert_pos;
141 BOOST_LOG_TRIVIAL(debug) <<
"Setting initial positions and velocitis of particles...";
154 #pragma omp parallel for private(unpert_pos, velocity, pert_pos) 155 for(
size_t i=0; i< Np; i++)
159 pert_pos = velocity*D + unpert_pos;
168 std::vector<size_t> slab_keys;
169 slab_keys.resize(rho.
N1);
173 FTYPE_t rn1, rn2, rn, tmp;
174 const size_t N = rho.
N;
176 #pragma omp parallel for private(ikey, index, rn1, rn2, rn, tmp) 177 for(
size_t i=0; i < N; ++i)
180 for(
size_t j=0; j < N; ++j)
183 for(
size_t k=0; k< N; ++k)
186 GetRandomDoublesWhiteNoise(rn1, rn2, rn, ikey, index);
187 tmp =
sqrt(-2*log(rn)/rn);
188 rho(i, j, k) = rn2 * tmp;
191 for(
size_t k=0; k < N/2; ++k)
194 GetRandomDoublesWhiteNoise(rn1, rn2, rn, ikey, index);
195 tmp =
sqrt(-2*log(rn)/rn);
196 rho(i, j, 2*k) = rn2 * tmp;
197 rho(i, j, 2*k+1) = rn1 * tmp;
205 FTYPE_t t_std_dev =
std_dev(rho, t_mean);
206 BOOST_LOG_TRIVIAL(debug) <<
"\t[mean = " << t_mean <<
", stdDev = " << t_std_dev <<
"]\t-->";
212 BOOST_LOG_TRIVIAL(debug) <<
"\t[mean = " << t_mean <<
", stdDev = " <<
std_dev(rho, t_mean) <<
"]\t<--";
213 BOOST_LOG_TRIVIAL(debug) <<
"\t[min = " <<
min(rho) <<
", max = " <<
max(rho) <<
"]";
218 return exp(-k*k/k2_G);
225 const FTYPE_t k0 = 2*
PI/L;
227 const size_t N = rho.
N;
228 const size_t len = rho.
length / 2;
229 const FTYPE_t mod = phase *
pow(N / L, 3/2.);
235 #pragma omp parallel for 236 for(
size_t i=0; i < len; i++)
246 #pragma omp parallel for 247 for(
size_t i=0; i < len; i++)
269 BOOST_LOG_TRIVIAL(debug) <<
"Generating gaussian white noise...";
273 BOOST_LOG_TRIVIAL(debug) <<
"Generating density distributions with given power spectrum...";
280 BOOST_LOG_TRIVIAL(debug) <<
"Computing the density field from particle positions...";
283 if (particles.size() != Np){
284 std::string msg =
"Number of particles (" + std::to_string(particles.size()) +
") does not correspond with simulation parameters (" + std::to_string(Np) +
")!";
285 throw std::range_error(msg);
287 const FTYPE_t
m =
pow((FTYPE_t)rho.
N, 3) / Np;
293 #pragma omp parallel for 294 for (
size_t i = 0; i < Np; i++)
296 assign_to(rho, particles[i].position*mesh_mod, m);
302 BOOST_LOG_TRIVIAL(debug) <<
"Computing the velocity field from particle positions...";
307 for(
Mesh& field : vel_field){
310 #pragma omp parallel for 311 for (
size_t i = 0; i < Np; i++)
313 assign_to(vel_field, particles[i].position*mesh_mod, particles[i].velocity*(
m*mesh_mod));
320 BOOST_LOG_TRIVIAL(debug) <<
"WARNING! Trying to compute velocity divergence with particle positions only! Skipping...";
335 const size_t NM = rho_k.
N;
336 const size_t half_length = rho_k.
length / 2;
338 #pragma omp parallel for private(w_k, k_vec) 339 for(
size_t i=0; i < half_length;i++)
343 for (
unsigned int j = 0; j < 3; j++)
if (k_vec[j] != 0) w_k *=
pow(sin(k_vec[j]*
PI/NM)/(k_vec[j]*
PI/NM),
ORDER + 1);
344 power_aux[2*i] = (rho_k[2*i]*rho_k[2*i] + rho_k[2*i+1]*rho_k[2*i+1])/(w_k*w_k);
345 power_aux[2*i+1] = k_vec.norm();
354 const size_t NM = rho_k.
N;
355 const size_t half_length = rho_k.
length / 2;
357 #pragma omp parallel for private(k_vec) 358 for(
size_t i=0; i < half_length;i++)
361 power_aux[2*i] =
pow2(rho_k[2*i]) +
pow2(rho_k[2*i+1]);
362 power_aux[2*i+1] = k_vec.norm();
378 const size_t NM = vel_field[0].N;
379 const size_t half_length = vel_field[0].length / 2;
381 FTYPE_t vel_div_re, vel_div_im, k;
383 #pragma omp parallel for private(w_k, k_vec, k, vel_div_re, vel_div_im) 384 for(
size_t i=0; i < half_length; i++)
387 vel_div_re = vel_div_im = 0;
389 for (
unsigned int j = 0; j < 3; j++){
390 k = k_vec[j]*2*
PI /
NM;
391 if (k != 0) w_k *=
pow(sin(k/2)/(k/2),
ORDER + 1);
392 vel_div_re += vel_field[j][2*i]*k;
393 vel_div_im += vel_field[j][2*i+1]*k;
396 power_aux[2*i] = (vel_div_re*vel_div_re + vel_div_im*vel_div_im)/(w_k*w_k);
397 power_aux[2*i+1] = k_vec.norm();
401 void gen_cqty_binned(
const FTYPE_t x_min,
const FTYPE_t x_max,
const size_t bins_per_decade,
402 const Mesh &qty_mesh,
const size_t half_length,
Data_Vec<FTYPE_t,2>& qty_binned,
const FTYPE_t mod_q,
const FTYPE_t mod_x)
415 size_t req_size = (size_t)ceil(bins_per_decade*log10(x_max/x_min));
416 qty_binned.
resize(req_size);
418 std::vector<size_t> tmp(req_size, 0);
424 #pragma omp parallel for private(x, bin) 425 for (
size_t i = 0; i < half_length; i++){
427 if ((x <x_max) && (x>=x_min)){
428 bin = (size_t)((log10(x) - log10(x_min)) * bins_per_decade);
430 qty_binned[0][bin] +=
x;
432 qty_binned[1][bin] += qty_mesh[2*i];
440 for (
size_t j = 0; j < qty_binned.
size(); ){
443 qty_binned[0][j] *= mod_x /
count;
444 qty_binned[1][j] *= mod_q /
count;
448 tmp.erase(tmp.begin() + j);
454 void gen_cqty_binned(
const FTYPE_t x_min,
const FTYPE_t x_max,
const size_t bins_per_decade,
457 gen_cqty_binned(x_min, x_max, bins_per_decade, qty_mesh, qty_mesh.
length / 2, qty_binned, mod_q, mod_x);
464 BOOST_LOG_TRIVIAL(debug) <<
"Computing binned power spectrum...";
473 BOOST_LOG_TRIVIAL(debug) <<
"Computing binned initial power spectrum...";
477 template<
class P,
typename T,
size_t N>
485 pwr_spec_binned.
resize(req_size);
487 #pragma omp parallel for private(k) 488 for (
size_t j = 0; j < pwr_spec_binned.
size(); j++){
489 k = k_min*
pow(
T(10), j*log_bin);
490 pwr_spec_binned[0][j] = k;
491 pwr_spec_binned[1][j] = P_k(k);
501 BOOST_LOG_TRIVIAL(debug) <<
"Computing potential in k-space...";
503 const size_t N = rho_k.
N;
504 const FTYPE_t d2_k =
pow2(2*
PI/N);
505 const size_t l_half = rho_k.
length/2;
507 #pragma omp parallel for private(k2) 508 for(
size_t i=0; i < l_half;i++){
514 pot_k[2*i] = -rho_k[2*i]/(k2*d2_k);
515 pot_k[2*i+1] = -rho_k[2*i+1]/(k2*d2_k);
522 static FTYPE_t
S2_shape(
const FTYPE_t k2,
const FTYPE_t a)
524 if (a == 0)
return 1.;
526 FTYPE_t t =
sqrt(k2)*a / 2;
527 if (t == 0)
return 1.;
528 return 12 /
pow(t, 4)*(2 - 2 * cos(t) - t*sin(t));
536 for(
unsigned int j=0; j<3; j++)
538 if (k_vec[j] != 0) s2 /=
pow2(sin(k_vec[j] / 2) / (k_vec[j] / 2));
543 FTYPE_t U2, U_n, G_n, k2n;
547 for (
unsigned int j = 0; j < 3; j++) U2 *= (1+2*
pow2(cos(k_vec[j]/2)))/3;
550 k_n[0] = k_vec[0] + 2 *
PI*n1;
551 for (
int n2 = -N_MAX; n2 < N_MAX + 1; n2++)
553 k_n[1] = k_vec[1] + 2 *
PI*n2;
554 for (
int n3 = -N_MAX; n3 < N_MAX + 1; n3++)
556 k_n[2] = k_vec[2] + 2 *
PI*n3;
559 for(
unsigned int j=0; j<3; j++)
561 if (k_n[j] != 0) U_n *= sin(k_n[j] / 2) / (k_n[j] / 2);
567 for(
unsigned int j=0; j<3; j++)
577 if ((G_n != G_n) || (U2 != U2))
579 BOOST_LOG_TRIVIAL(warning) <<
"Gn = " << G_n <<
"\tU2 = " << U2 <<
", k = (" << k_vec[0] <<
", " << k_vec[1] <<
", " << k_vec[2] <<
")";
591 if (a == -1) BOOST_LOG_TRIVIAL(debug) <<
"Computing displacement in k-space...";
592 else if (a == 0) BOOST_LOG_TRIVIAL(debug) <<
"Computing displacement in k-space with CIC opt...";
593 else BOOST_LOG_TRIVIAL(debug) <<
"Computing force in k-space for S2 shaped particles with CIC opt...";
598 FTYPE_t potential_tmp[2];
600 const size_t N = vel_field[0].N;
601 const FTYPE_t d_k = 2*
PI/N;
602 const size_t l_half = vel_field[0].length/2;
604 #pragma omp parallel for private(opt, k_vec, k_vec_phys, potential_tmp) 605 for(
size_t i=0; i < l_half;i++)
607 potential_tmp[0] = pot_k[2*i];
608 potential_tmp[1] = pot_k[2*i+1];
610 k_vec_phys = d_k*k_vec;
612 if (a == -1) opt = 1.;
614 else opt =
CIC_opt(k_vec_phys, a);
615 for(
size_t j=0; j<3;j++)
617 vel_field[j][2*i] = k_vec_phys[j]*potential_tmp[1]*opt;
618 vel_field[j][2*i+1] = -k_vec_phys[j]*potential_tmp[0]*opt;
629 BOOST_LOG_TRIVIAL(debug) <<
"Computing binned density field...";
633 const size_t N = rho.
N;
635 dens_binned.assign(dens_binned.size(), 0);
637 #pragma omp parallel for private(bin, rho_avg) 638 for (
size_t i = 0; i < N; i+=Ng_pwr)
640 for (
size_t j = 0; j < N; j+=Ng_pwr)
642 for (
size_t k = 0; k < N; k+=Ng_pwr)
646 for (
size_t ii = i; ii < i+Ng_pwr; ii++)
648 for (
size_t jj = j; jj < j+Ng_pwr; jj++)
650 for (
size_t kk = k; kk < k+Ng_pwr; kk++)
652 rho_avg+=rho(ii, jj, kk);
656 rho_avg /=
pow((FTYPE_t)Ng_pwr, 3);
657 bin = (size_t)((rho_avg+1)/0.1);
658 if (bin >= dens_binned.size()) bin = dens_binned.size() - 1;
void gen_pow_spec_binned_from_extrap(const Sim_Param &sim, const P &P_k, Data_Vec< T, N > &pwr_spec_binned)
static double S2_shape(const double k2, const double a)
bool get_vel_from_par(const std::vector< Particle_v< double >> &particles, std::vector< Mesh > &vel_field, const Sim_Param &sim)
void get_rho_from_par(const std::vector< T > &particles, Mesh &rho, const Sim_Param &sim)
void gen_rho_dist_k(const Sim_Param &sim, Mesh &rho, const FFTW_PLAN_TYPE &p_F)
Generate density distributions in k-space.
double get_k_sq(size_t N, size_t index)
double lin_pow_spec(double a, double k, const Cosmo_Param &cosmo)
static void set_velocity_one_par(const Vec_3D< size_t > &unpert_pos, Vec_3D< double > &displ_field, const std::vector< Mesh > &vel_field)
class handling particles (position only)
void set_pert_pos(const Sim_Param &sim, const double a, std::vector< Particle_x< double >> &particles, const std::vector< Mesh > &vel_field)
void gen_cqty_binned(const double x_min, const double x_max, const size_t bins_per_decade, const Mesh &qty_mesh, const size_t half_length, Data_Vec< double, 2 > &qty_binned, const double mod_q, const double mod_x)
void gen_displ_k(std::vector< Mesh > &vel_field, const Mesh &pot_k)
: class storing simulation parameters
static double CIC_opt(Vec_3D< double > k_vec, const double a)
size_t size() const noexcept
void fftw_execute_dft_r2c(const FFTW_PLAN_TYPE &p_F, Mesh &rho)
compute forward (real to complex) FFT on mesh (inplace)
size_t count(InputIterator first, InputIterator last, T const &item)
: creates a mesh of N*N*(N+2) cells
void assign_to(Mesh &field, const Vec_3D< double > &position, const double value)
void set_unpert_pos_w_vel(const Sim_Param &sim, std::vector< Particle_v< double >> &particles, const std::vector< Mesh > &vel_field)
static T std_dev(const std::vector< T > &data, T mean)
void gen_pot_k(const Mesh &rho_k, Mesh &pot_k)
static void set_unpert_pos_one_par(Vec_3D< size_t > &unpert_pos, const size_t par_index, const size_t par_per_dim, const size_t Ng)
class handling particles (position only)
void gen_pow_spec_binned(const Sim_Param &sim, const Mesh &power_aux, Data_Vec< double, 2 > &pwr_spec_binned)
declaration in params.hpp
Grid< NDIM, T > sqrt(Grid< NDIM, T > lhs)
interface for common functions for all types of approximations
static CCL_BEGIN_DECLS double x[111][8]
Range k_print
range in which compute the correlation function
static T max(const std::vector< T > &data)
static double truncation_fce(double k, double k2_G)
void gen_dens_binned(const Mesh &rho, std::vector< size_t > &dens_binned, const Sim_Param &sim)
void vel_pwr_spec_k(const std::vector< Mesh > &vel_field, Mesh &power_aux)
void pwr_spec_k(const Mesh &rho_k, Mesh &power_aux)
static std::enable_if< std::is_integral< T >::value, T >::type get_per(T vec, size_t per)
void gen_pow_spec_binned_init(const Sim_Param &sim, const Mesh &power_aux, const size_t half_length, Data_Vec< double, 2 > &pwr_spec_binned)
void get_k_vec(size_t N, size_t index, int *k_vec)
basic functions to work with mesh
float pow(float base, unsigned long int exp)
static void gen_gauss_white_noise(const Sim_Param &sim, Mesh &rho)
void pwr_spec_k_init(const Mesh &rho_k, Mesh &power_aux)
void set_unpert_pos(const Sim_Param &sim, std::vector< Particle_x< double >> &particles)
static T mean(const std::vector< T > &data)
void gen_displ_k_cic(std::vector< Mesh > &vel_field, const Mesh &pot_k)
static T min(const std::vector< T > &data)
void gen_displ_k_S2(std::vector< Mesh > &vel_field, const Mesh &pot_k, const double a)
static void gen_rho_w_pow_k(const Sim_Param &sim, Mesh &rho)
double growth_change(double a, const Cosmo_Param &cosmo)