CosmoBolognaLib
Free Software C++/Python libraries for cosmological calculations
LogNormal.cpp
Go to the documentation of this file.
1 /********************************************************************
2  * Copyright (C) 2010 by Federico Marulli and Alfonso Veropalumbo *
3  * federico.marulli3@unibo.it *
4  * *
5  * This program is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU General Public License as *
7  * published by the Free Software Foundation; either version 2 of *
8  * the License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public *
16  * License along with this program; if not, write to the Free *
17  * Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  *******************************************************************/
20 
34 #include "FFTlog.h"
35 #include "LogNormal.h"
36 
37 using namespace std;
38 
39 using namespace cbl;
40 using namespace catalogue;
41 using namespace lognormal;
42 
43 
44 // ============================================================================
45 
46 
47 std::shared_ptr<catalogue::Catalogue> cbl::lognormal::LogNormal::catalogue (const size_t i)
48 {
49  if (i<m_catalogue.size())
50  return m_catalogue[i];
51 
52  else {
53  ErrorCBL("The log-normal catalogue "+conv(i+1, par::fINT)+" does not exist!", "LogNormal_catalogue", "LogNormal.cpp");
54  return NULL;
55  }
56 }
57 
58 
59 // ============================================================================
60 
61 
62 void cbl::lognormal::LogNormal::generate (const int n_lognormal_mocks, const std::string output_dir, const std::string filename, const int start, const int seed)
63 {
64  if (n_lognormal_mocks==0)
65  ErrorCBL("set number of log-normal realizations first!", "generate", "LogNormal.cpp");
66 
67  random::UniformRandomNumbers ran(0., 1., seed);
68 
69 
70  // compute the visibility mask from the input random catalogue
71 
72  const double minX_random = m_random.Min(Var::_X_);
73  const double minY_random = m_random.Min(Var::_Y_);
74  const double minZ_random = m_random.Min(Var::_Z_);
75 
76  const double DeltaX = (m_random.Max(Var::_X_)-minX_random);
77  const double DeltaY = (m_random.Max(Var::_Y_)-minY_random);
78  const double DeltaZ = (m_random.Max(Var::_Z_)-minZ_random);
79 
80  const int nTot = m_random.nObjects();
81 
82  int nx = DeltaX/m_cell_size; // nx: number of grid cells along the x axis
83  nx = (nx%2==0) ? nx : nx+1; // if nx is odd, add 1
84  const double cell_size_x = DeltaX/nx;
85 
86  int ny = DeltaY/m_cell_size;
87  ny = (ny%2==0) ? ny : ny+1;
88  const double cell_size_y = DeltaY/ny;
89 
90  int nz = DeltaZ/m_cell_size;
91  nz = (nz%2==0) ? nz : nz+1;
92  const double cell_size_z = DeltaZ/nz;
93 
94  const int nzp = nz*0.5+1;
95 
96  const int nRtot = nx*ny*nz;
97  const int nKtot = nx*ny*nzp;
98 
99  double *grid, *xxii;
100  fftw_complex *ppkk;
101  grid = fftw_alloc_real(nRtot);
102  xxii = fftw_alloc_real(nRtot);
103  ppkk = fftw_alloc_complex(nKtot);
104 
105  for (int i=0; i<nRtot; i++) {
106  grid[i] = 0;
107  xxii[i] = 0;
108  }
109 
110  for (int i=0; i<nKtot; i++) {
111  ppkk[i][0] = 0;
112  ppkk[i][1] = 0;
113  }
114 
115  for (int i=0; i<nTot; i++) { // loop on the random objects to put them in the grid cells
116  int i1 = min(int((m_random.xx(i)-minX_random)/cell_size_x), nx-1);
117  int j1 = min(int((m_random.yy(i)-minY_random)/cell_size_y), ny-1);
118  int z1 = min(int((m_random.zz(i)-minZ_random)/cell_size_z), nz-1);
119  long int index = z1+nz*(j1+ny*i1);
120  grid[index] += 1./nTot; // grid[index] : the fraction of random objects in the index-th grid cell
121  }
122 
123  const double fact = (m_real) ? pow(m_bias, 2) : pow(m_bias, 2)*xi_ratio(m_cosmology.linear_growth_rate(m_redshift, 0.)/m_bias);
124 
125  vector<double> kG = logarithmic_bin_vector(500, 1.e-4, 1.e2);
126  vector<double> PkG = m_cosmology.Pk_matter(kG, m_method_Pk, m_NL, m_redshift);
127 
128  for (size_t i=0; i<kG.size(); i++)
129  PkG[i] = fact*PkG[i];
130 
131 
132  cbl::glob::FuncGrid interpPk(kG, PkG, "Spline");
133 
134  const double xfact = 2.*par::pi/(nx*cell_size_x);
135  const double yfact = 2.*par::pi/(ny*cell_size_y);
136  const double zfact = 2.*par::pi/(nz*cell_size_z);
137 
138  const double Volume = nRtot*cell_size_x*cell_size_y*cell_size_z;
139 
140  // interpolate the power spectrum on the 3D grid
141  for (int i=0; i<nx; i++) {
142  const double kx = (i<=nx/2) ? xfact*i : -(nx-i)*xfact;
143  for (int j=0; j<ny; j++) {
144  const double ky = (j<=ny/2) ? yfact*j : -(ny-j)*yfact;
145  for (int k=0; k<nzp; k++) {
146  const double kz = zfact*k;
147  const double kk = pow(kx*kx+ky*ky+kz*kz, 0.5);
148  const long int kindex = k+nzp*(j+ny*i);
149  ppkk[kindex][0] = interpPk(kk)/Volume; //interpolated(kk, kG, PkG, "Poly")/Volume;
150  }
151  }
152  }
153 
154  coutCBL << "I'm computing Fourier transforms..."<<endl;
155 
156 
157  // compute the Fourier transform of the 3D power spectrum divided by the volume to get the 3D two-point correlation function
158  fftw_plan plan_xi_from_pk = fftw_plan_dft_c2r_3d(nx, ny, nz, ppkk, xxii, FFTW_ESTIMATE);
159  fftw_execute(plan_xi_from_pk);
160  fftw_destroy_plan(plan_xi_from_pk);
161 
162  for (int i=0; i<nRtot; i++)
163  xxii[i] = log(1+xxii[i]);
164 
165  // compute the Fourier transform of the 3D two-point correlation function to get the 3D power spectrum
166  fftw_plan plan_pk_from_xi = fftw_plan_dft_r2c_3d(nx, ny, nz, xxii, ppkk, FFTW_ESTIMATE);
167  fftw_execute(plan_pk_from_xi);
168  fftw_destroy_plan(plan_pk_from_xi);
169 
170 
171  for (int nn=0; nn<n_lognormal_mocks; nn++) { // loop on the log-normal mocks to be constructed
172 
173  coutCBL << "I'm constructing the log-normal mock: " << nn+1 << "..." << endl;
174 
175  double *densX;
176  fftw_complex *densK;
177  densK = fftw_alloc_complex(nKtot);
178  densX = fftw_alloc_real(nRtot);
179 
180  for (int i=0; i<nRtot; i++)
181  densX[i] = 0;
182 
183  for (int i=0; i<nKtot; i++) {
184  densK[i][0] = 0;
185  densK[i][1] = 0;
186  }
187 
188 
189  // compute the density field in Fourier space from the 3D power spectrum
190 
191  random::NormalRandomNumbers rang(0., 1., seed);
192 
193  for (int i=0; i<nx; i++)
194  for (int j=0; j<ny; j++)
195  for (int k=0; k<nzp; k++) {
196 
197  const int kindex = k+nzp*(j+ny*i);
198  const double dk = sqrt(max(0., ppkk[kindex][0]/nRtot)*0.5);
199 
200  const double v1 = dk*rang();
201  const double v2 = dk*rang();
202 
203  if (i==0 && j==0 && k==0) {
204  densK[kindex][0] = 0;
205  densK[kindex][1] = 0;
206  }
207  else if (i==nx/2 || j==ny/2){
208  densK[kindex][0] = v1;
209  densK[kindex][1] = 0.;
210  }
211  else {
212  densK[kindex][0] = v1;
213  densK[kindex][1] = v2;
214  }
215  }
216 
217 
218  // compute the Fourier transform of the 3D density field in Fourier space to the real space one
219  fftw_plan plan_dr_from_dk = fftw_plan_dft_c2r_3d(nx, ny, nz, densK, densX, FFTW_ESTIMATE);
220  fftw_execute(plan_dr_from_dk);
221  fftw_destroy_plan(plan_dr_from_dk);
222 
223  // compute the variance of the density field
224  vector<double> ff;
225  for (int i=0; i<nx; i++)
226  for (int j=0; j<ny; j++)
227  for (int k=0; k<nz; k++)
228  ff.push_back(densX[k+nz*(j+ny*i)]);
229 
230  const double sigma = Sigma(ff);
231 
232  //coutCBL << "Log-normal mock " << nn+1 << ": average density = " << Average(ff) << ", sigma = "<< sigma << endl;
233 
234 
235  // draw a Poisson sampling of the grid density field
236 
237  default_random_engine generator;
238  vector<shared_ptr<Object>> mock_sample;
239 
240  for (int i=0; i<nx; i++) {
241  for (int j=0; j<ny; j++) {
242  for (int k=0; k<nz; k++) {
243  long int index = k+nz*(j+ny*i);
244 
245  // number of objects in the (i, j, k) grid cell
246  const double nObjects = m_nObjects*grid[index]*(exp(densX[index]-sigma*sigma*0.5)); // transform the density field to get a log-normal distribution
247 
248  // number of objects (from Poissonian PDF) whose coordinates will be randomly extracted (flat PDF for x,y,z) in the grid cells
249  poisson_distribution<int> distribution(nObjects);
250  int no = distribution(generator);
251 
252  for (int nnoo=0; nnoo<no; nnoo++) {
253  comovingCoordinates coord;
254  coord.xx = cell_size_x*(i+ran())+minX_random;
255  coord.yy = cell_size_y*(j+ran())+minY_random;
256  coord.zz = cell_size_z*(k+ran())+minZ_random;
257  shared_ptr<Galaxy> SMP(new Galaxy(coord));
258  mock_sample.push_back(SMP);
259  }
260 
261  }
262  }
263  }
264 
265  shared_ptr<Catalogue> p_cat(new Catalogue{mock_sample});
266 
267  p_cat->write_comoving_coordinates(output_dir+filename+"_"+conv(nn+start, par::fINT)+".dat");
268 
269  m_catalogue.emplace_back(p_cat);
270  }
271 }
Wrapper for fftlog wripper.
#define coutCBL
CBL print message.
Definition: Kernel.h:734
Implementation of the log-normal data structure.
The class Catalogue.
Definition: Catalogue.h:654
The class Galaxy.
Definition: Galaxy.h:54
The class FuncGrid.
Definition: FuncGrid.h:55
void generate(const int n_lognormal_mocks, const std::string output_dir, const std::string filename="lognormal", const int start=1, const int seed=3213)
generate the log-normal mock catalogues
Definition: LogNormal.cpp:62
std::shared_ptr< catalogue::Catalogue > catalogue(const size_t i)
get the private member LogNormal::m_LNCat[i]
Definition: LogNormal.cpp:47
The class NormalRandomNumbers.
The class UniformRandomNumbers.
static const char fINT[]
conversion symbol for: int -> std::string
Definition: Constants.h:121
static const double pi
: the ratio of a circle's circumference to its diameter
Definition: Constants.h:199
The global namespace of the CosmoBolognaLib
Definition: CAMB.h:38
void distribution(std::vector< double > &xx, std::vector< double > &fx, std::vector< double > &err, const std::vector< double > FF, const std::vector< double > WW, const int nbin, const bool linear=true, const std::string file_out=par::defaultString, const double fact=1., const double V1=par::defaultDouble, const double V2=par::defaultDouble, const std::string bin_type="Linear", const bool conv=false, const double sigma=0.)
derive and store the number distribution of a given std::vector
Definition: Func.cpp:1654
std::string conv(const T val, const char *fact)
convert a number to a std::string
Definition: Kernel.h:903
std::vector< T > logarithmic_bin_vector(const size_t nn, const T min, const T max)
fill a std::vector with logarithmically spaced values
Definition: Kernel.h:1621
int ErrorCBL(const std::string msg, const std::string functionCBL, const std::string fileCBL, const cbl::glob::ExitCode exitCode=cbl::glob::ExitCode::_error_)
throw an exception: it is used for handling exceptions inside the CosmoBolognaLib
Definition: Kernel.h:780
double xi_ratio(const double beta)
the ratio between the redshift-space and real-space correlation functions
Definition: FuncXi.cpp:287
double Sigma(const std::vector< double > vect)
the standard deviation of a std::vector
Definition: Func.cpp:925