CosmoBolognaLib
Free Software C++/Python libraries for cosmological calculations
Func.cpp
1 /*******************************************************************
2  * Copyright (C) 2010 by Federico Marulli *
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 "Func.h"
35 #include "LegendrePolynomials.h"
36 #include <boost/math/special_functions/spherical_harmonic.hpp>
37 
38 using namespace std;
39 
40 using namespace cbl;
41 using namespace glob;
42 
43 
44 // ============================================================================
45 
46 
47 double cbl::closest_probability (double xx, std::shared_ptr<void> pp, std::vector<double> par)
48 {
49  (void)par;
50  shared_ptr<cbl::glob::STR_closest_probability> pars = static_pointer_cast<cbl::glob::STR_closest_probability>(pp);
51  return pars->weights[(cbl::index_closest(xx, pars->values))];
52 }
53 
54 
55 // ============================================================================
56 
57 
58 double cbl::distribution_probability (double xx, std::shared_ptr<void> pp, std::vector<double> par)
59 {
60  (void)par;
61  shared_ptr<cbl::glob::STR_distribution_probability> pars = static_pointer_cast<cbl::glob::STR_distribution_probability>(pp);
62  return pars->func->operator()(xx);
63 }
64 
65 
66 // ============================================================================
67 
68 double cbl::chainMeshInterpolate (std::vector<double> xx, std::shared_ptr<void> pars)
69 {
70  shared_ptr<cbl::glob::STR_chainMeshInterpolate> Pars = static_pointer_cast<cbl::glob::STR_chainMeshInterpolate>(pars);
71  cbl::chainmesh::ChainMesh chMesh = Pars->ChainMesh;
72  int distNum = Pars->DistNum;
73  return chMesh.interpolate(xx,distNum);
74 }
75 
76 // ============================================================================
77 
78 
79 double cbl::multivariateGaussian (std::vector<double> xx, std::shared_ptr<void> pars)
80 {
81  shared_ptr<cbl::glob::STR_multivariateGaussian> Pars = static_pointer_cast<cbl::glob::STR_multivariateGaussian>(pars);
82  Eigen::VectorXd MeanVec = Pars->MeanVec;
83  Eigen::MatrixXd CovMat = Pars->CovMat;
84  Eigen::VectorXd XX = cbl::wrapper::eigen::VectorToEigen(xx);
85  double n = XX.rows();
86  double quadform = (XX-MeanVec).transpose()*CovMat.inverse()*(XX-MeanVec);
87  double norm = pow(pow(2.*par::pi,-n)*CovMat.determinant(),-0.5);
88  return norm*exp(-0.5*quadform);
89 }
90 
91 // ============================================================================
92 
93 
94 double cbl::Filter (const double r, const double rc)
95 {
96  double x = pow(r/rc, 3);
97  return pow(2*x*(1.-x), 2)*(0.5-x)*pow(rc, -3);
98 }
99 
100 
101 // ============================================================================================
102 
103 
104 double cbl::degrees (const double angle, const CoordinateUnits inputUnits)
105 {
106  if (inputUnits==CoordinateUnits::_radians_)
107  return angle*180./par::pi;
108 
109  else if (inputUnits==CoordinateUnits::_arcseconds_)
110  return angle/3600.;
111 
112  else if (inputUnits==CoordinateUnits::_arcminutes_)
113  return angle/60.;
114 
115  else if (inputUnits==CoordinateUnits::_degrees_)
116  return angle;
117 
118  else
119  return ErrorCBL("inputUnits type not allowed!", "degrees", "Func.cpp");
120 }
121 
122 
123 // ============================================================================================
124 
125 
126 double cbl::radians (const double angle, const CoordinateUnits inputUnits)
127 {
128  if (inputUnits==CoordinateUnits::_degrees_)
129  return angle/180.*par::pi;
130 
131  else if (inputUnits==CoordinateUnits::_arcseconds_)
132  return angle/180.*par::pi/3600.;
133 
134  else if (inputUnits==CoordinateUnits::_arcminutes_)
135  return angle/180.*par::pi/60.;
136 
137  else if (inputUnits==CoordinateUnits::_radians_)
138  return angle;
139 
140  else
141  return ErrorCBL("inputUnits type not allowed!", "radians", "Func.cpp");
142 }
143 
144 
145 // ============================================================================================
146 
147 
148 double cbl::arcseconds (const double angle, const CoordinateUnits inputUnits)
149 {
150  if (inputUnits==CoordinateUnits::_radians_)
151  return angle*180./par::pi*3600.;
152 
153  else if (inputUnits==CoordinateUnits::_degrees_)
154  return angle*3600.;
155 
156  else if (inputUnits==CoordinateUnits::_arcminutes_)
157  return angle*60.;
158 
159  else if (inputUnits==CoordinateUnits::_arcseconds_)
160  return angle;
161 
162  else
163  return ErrorCBL("inputUnits type not allowed!", "arcseconds", "Func.cpp");
164 }
165 
166 
167 // ============================================================================================
168 
169 
170 double cbl::arcminutes (const double angle, const CoordinateUnits inputUnits)
171 {
172  if (inputUnits==CoordinateUnits::_radians_)
173  return angle*180./par::pi*60.;
174 
175  else if (inputUnits==CoordinateUnits::_degrees_)
176  return angle*60.;
177 
178  else if (inputUnits==CoordinateUnits::_arcseconds_)
179  return angle/60.;
180 
181  else if (inputUnits==CoordinateUnits::_arcminutes_)
182  return angle;
183 
184  else
185  return ErrorCBL("inputUnits type not allowed!", "arcminutes", "Func.cpp");
186 }
187 
188 
189 // ============================================================================================
190 
191 
192 double cbl::converted_angle (const double angle, const CoordinateUnits inputUnits, const CoordinateUnits outputUnits)
193 {
194  if (outputUnits==CoordinateUnits::_radians_)
195  return radians(angle, inputUnits);
196 
197  else if (outputUnits==CoordinateUnits::_degrees_)
198  return degrees(angle, inputUnits);
199 
200  else if (outputUnits==CoordinateUnits::_arcseconds_)
201  return arcseconds(angle, inputUnits);
202 
203  else if (outputUnits==CoordinateUnits::_arcminutes_)
204  return arcminutes(angle, inputUnits);
205 
206  else
207  return ErrorCBL("outputUnits type not allowed!", "converted_angle", "Func.cpp");
208 }
209 
210 
211 // ============================================================================================
212 
213 
214 void cbl::polar_coord (const double XX, const double YY, const double ZZ, double &ra, double &dec, double &dd)
215 {
216  dd = sqrt(XX*XX+YY*YY+ZZ*ZZ);
217  ra = atan2(YY,XX);
218  dec = asin(ZZ/dd);
219 }
220 
221 void cbl::cartesian_coord (const double ra, const double dec, const double dd, double &XX, double &YY, double &ZZ)
222 {
223  XX = dd*cos(dec)*cos(ra);
224  YY = dd*cos(dec)*sin(ra);
225  ZZ = dd*sin(dec);
226 }
227 
228 void cbl::polar_coord (const std::vector<double> XX, const std::vector<double> YY, const std::vector<double> ZZ, std::vector<double> &ra, std::vector<double> &dec, std::vector<double> &dd)
229 {
230  for (size_t i=0; i<XX.size(); i++) {
231  dd[i] = sqrt(XX[i]*XX[i]+YY[i]*YY[i]+ZZ[i]*ZZ[i]);
232  ra[i] = atan2(YY[i],XX[i]);
233  dec[i] = asin(ZZ[i]/dd[i]);
234  }
235 }
236 
237 void cbl::cartesian_coord (const std::vector<double> ra, const std::vector<double> dec, const std::vector<double> dd, std::vector<double> &XX, std::vector<double> &YY, std::vector<double> &ZZ)
238 {
239  for (size_t i=0; i<XX.size(); i++) {
240  XX[i] = dd[i]*cos(dec[i])*cos(ra[i]);
241  YY[i] = dd[i]*cos(dec[i])*sin(ra[i]);
242  ZZ[i] = dd[i]*sin(dec[i]);
243  }
244 }
245 
246 
247 // ============================================================================================
248 
249 
250 double cbl::Euclidean_distance (const double x1, const double x2, const double y1, const double y2, const double z1, const double z2)
251 {
252  return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
253 }
254 
255 
256 // ============================================================================================
257 
258 
259 double cbl::perpendicular_distance (const double ra1, const double ra2, const double dec1, const double dec2, const double d1, const double d2)
260 {
261  double costheta = sin(dec1)*sin(dec2)+cos(dec1)*cos(dec2)*(cos(ra1)*cos(ra2)+sin(ra1)*sin(ra2));
262  double theta = 0.;
263  if (fabs(costheta)<1.-1.e-30) theta = acos(costheta);
264  else if (costheta>=1.-1.e-30) theta = 0.;
265  else theta = par::pi;
266 
267  double rp = (d1+d2)*tan(theta*0.5);
268  rp *= 4.*d1*d2/((d1+d2)*(d1+d2));
269 
270  return rp;
271 }
272 
273 
274 // ============================================================================================
275 
276 
277 double cbl::angular_distance (const double x1, const double x2, const double y1, const double y2, const double z1, const double z2)
278 {
279  return 2.*asin(0.5*Euclidean_distance(x1, x2, y1, y2, z1, z2));
280 }
281 
282 
283 // ============================================================================================
284 
285 
286 double cbl::haversine_distance (const double ra1, const double ra2, const double dec1, const double dec2)
287 {
288  return 2*asin(sqrt(pow(sin((dec2-dec1)*0.5), 2)+cos(dec1)*cos(dec2)*pow(sin((ra2-ra1)*0.5), 2)));
289 }
290 
291 
292 // ============================================================================================
293 
294 
295 double cbl::MC_Int (double func(const double), const double x1, const double x2, const int seed)
296 {
297  int step = 100000;
298  double delta_x = (x2-x1)/step;
299  double xx = x1;
300  vector<double> ff(step+1);
301  for (int i=0; i<step+1; i++) {ff[i] = func(xx); xx += delta_x;}
302 
303  vector<double>::iterator fmin = min_element (ff.begin(),ff.end()),
304  fmax = max_element (ff.begin(),ff.end());
305  double f1 = *fmin;
306  double f2 = *fmax;
307 
308  f1 = (f1>0) ? f1*0.5 : -fabs(f1)*2.;
309  f2 *= 2.;
310 
311  random::UniformRandomNumbers ran(0., 1., seed);
312 
313  double xt, yt, INT;
314  int sub = 0, subn = 0, numTOT = 10000000;
315 
316  if (f1>0) {
317  for (int i=0; i<numTOT; i++) {
318  xt = ran()*(x2-x1)+x1;
319  yt = ran()*(f2-f1);
320  if (yt<func(xt)) sub ++;
321  }
322  INT = double(sub)/double(numTOT)*(x2-x1)*(f2-f1);
323  }
324  else {
325  for (int i=0; i<numTOT; i++) {
326  xt = ran()*(x2-x1)+x1;
327  yt = ran()*f2;
328  if (yt<func(xt)) sub ++;
329  }
330  for (int i=0; i<numTOT; i++) {
331  xt = ran()*(x2-x1)+x1;
332  yt = ran()*f1;
333  if (yt>func(xt)) subn ++;
334  }
335  INT = (double(sub)/double(numTOT)*(x2-x1)*f2)-(double(subn)/double(numTOT)*(x2-x1)*fabs(f1));
336  }
337 
338  return INT;
339 }
340 
341 
342 // ============================================================================================
343 
344 
345 double cbl::MC_Int (double func(const double, const double AA), const double AA, const double x1, const double x2, const int seed)
346 {
347  int step = 100000;
348  double delta_x = (x2-x1)/step;
349  double xx = x1;
350  vector<double> ff(step+1);
351  for (int i=0; i<step+1; i++) {ff[i] = func(xx,AA); xx += delta_x;}
352 
353  vector<double>::iterator fmin = min_element (ff.begin(),ff.end()),
354  fmax = max_element (ff.begin(),ff.end());
355  double f1 = *fmin;
356  double f2 = *fmax;
357 
358  f1 = (f1>0) ? f1*0.5 : -fabs(f1)*2.;
359  f2 *= 2.;
360 
361  random::UniformRandomNumbers ran(0., 1., seed);
362 
363  double xt, yt, INT;
364  int sub = 0, subn = 0, numTOT = 10;
365 
366  if (f1>0) {
367  for (int i=0; i<numTOT; i++) {
368  xt = ran()*(x2-x1)+x1;
369  yt = ran()*(f2-f1);
370  if (yt<func(xt, AA)) sub ++;
371  }
372  INT = double(sub)/double(numTOT)*(x2-x1)*(f2-f1);
373  }
374  else {
375  for (int i=0; i<numTOT; i++) {
376  xt = ran()*(x2-x1)+x1;
377  yt = ran()*f2;
378  if (yt<func(xt,AA)) sub ++;
379  }
380  for (int i=0; i<numTOT; i++) {
381  xt = ran()*(x2-x1)+x1;
382  yt = ran()*f1;
383  if (yt>func(xt,AA)) subn ++;
384  }
385  INT = (double(sub)/double(numTOT)*(x2-x1)*f2)-(double(subn)/double(numTOT)*(x2-x1)*fabs(f1));
386  }
387 
388  return INT;
389 }
390 
391 
392 // ============================================================================================
393 
394 
395 double cbl::MC_Int (double func(const double, const double AA, const double BB, const double CC, const double DD, const double EE), const double AA, const double BB, const double CC, const double DD, const double EE, const double x1, const double x2, const int seed)
396 {
397  int step = 100000;
398  double delta_x = (x2-x1)/step;
399  double xx = x1;
400  vector<double> ff(step+1);
401  for (int i=0; i<step+1; i++) {ff[i] = func(xx,AA,BB,CC,DD,EE); xx += delta_x;}
402 
403  vector<double>::iterator fmin = min_element (ff.begin(),ff.end()),
404  fmax = max_element (ff.begin(),ff.end());
405  double f1 = *fmin;
406  double f2 = *fmax;
407 
408  f1 = (f1>0) ? f1*0.5 : -fabs(f1)*2.;
409  f2 *= 2.;
410 
411  random::UniformRandomNumbers ran(0., 1., seed);
412 
413  double xt, yt, INT;
414  int sub = 0, subn = 0, numTOT = 100000;
415 
416  if (f1>0) {
417  for (int i=0; i<numTOT; i++) {
418  xt = ran()*(x2-x1)+x1;
419  yt = ran()*(f2-f1);
420  if (yt<func(xt,AA,BB,CC,DD,EE)) sub ++;
421  }
422  INT = double(sub)/double(numTOT)*(x2-x1)*(f2-f1);
423  }
424  else {
425  for (int i=0; i<numTOT; i++) {
426  xt = ran()*(x2-x1)+x1;
427  yt = ran()*f2;
428  if (yt<func(xt,AA,BB,CC,DD,EE)) sub ++;
429  }
430  for (int i=0; i<numTOT; i++) {
431  xt = ran()*(x2-x1)+x1;
432  yt = ran()*f1;
433  if (yt>func(xt,AA,BB,CC,DD,EE)) subn ++;
434  }
435  INT = (double(sub)/double(numTOT)*(x2-x1)*f2)-(double(subn)/double(numTOT)*(x2-x1)*fabs(f1));
436  }
437 
438  return INT;
439 }
440 
441 
442 // ============================================================================
443 
444 
445 double cbl::interpolated (const double _xx, const std::vector<double> xx, const std::vector<double> yy, const std::string type)
446 {
447  if (xx.size()!=yy.size() || xx.size()<2)
448  return ErrorCBL(conv(xx.size(), par::fINT)+"!="+conv(yy.size(), par::fINT)+" or "+conv(xx.size(), par::fINT)+"<2", "interpolated", "Func.cpp");
449 
450  size_t size = xx.size();
451 
452  if (_xx<xx[0]) // perform a linear extrapolation
453  return yy[0]+(_xx-xx[0])/(xx[1]-xx[0])*(yy[1]-yy[0]);
454 
455  else if (_xx>xx[size-1])
456  return yy[size-2]+(_xx-xx[size-2])/(xx[size-1]-xx[size-2])*(yy[size-1]-yy[size-2]);
457 
458 
459  gsl_interp_accel *acc = gsl_interp_accel_alloc();
460  const gsl_interp_type *TT;
461 
462  if (type=="Linear")
463  TT = gsl_interp_linear;
464 
465  else if (type=="Poly")
466  TT = gsl_interp_polynomial;
467 
468  else if (type=="Spline")
469  TT = gsl_interp_cspline;
470 
471  else if (type=="Spline_periodic")
472  TT = gsl_interp_cspline_periodic;
473 
474  else if (type=="Akima")
475  TT = gsl_interp_akima;
476 
477  else if (type=="Akima_periodic")
478  TT = gsl_interp_akima_periodic;
479 
480  else if (type=="Steffen")
481  TT = gsl_interp_steffen;
482 
483  else
484  ErrorCBL("the value of string 'type' is not permitted!", "interpolated", "Func.cpp");
485 
486  gsl_interp *interp = gsl_interp_alloc(TT, size);
487  gsl_interp_init(interp, xx.data(), yy.data(), size);
488 
489  double _yy;
490  interp->type->eval(interp->state, xx.data(), yy.data(), interp->size, _xx, acc, &_yy);
491 
492  gsl_interp_free(interp);
493  gsl_interp_accel_free(acc);
494 
495  return _yy;
496 }
497 
498 
499 // ============================================================================
500 
501 
502 double cbl::interpolated_2D (const double _x1, const double _x2, const std::vector<double> x1, const std::vector<double> x2, const std::vector<std::vector<double>> yy, const std::string type)
503 {
504  bool extr = false;
505 
506  const size_t size_x1 = x1.size();
507  const size_t size_x2 = x2.size();
508  double *ydata = new double[size_x1*size_x2];
509 
510  if ((_x1>Max(x1) || Min(x1)>_x1) ||(_x2>Max(x2) || Min(x2)>_x2))
511  extr = 1;
512 
513  gsl_interp_accel *x1acc = gsl_interp_accel_alloc();
514  gsl_interp_accel *x2acc = gsl_interp_accel_alloc();
515  const gsl_interp2d_type *TT = gsl_interp2d_bilinear;
516 
517  if (type=="Linear")
518  TT = gsl_interp2d_bilinear;
519 
520  else if (type=="Cubic")
521  TT = gsl_interp2d_bicubic;
522 
523  for (size_t i=0; i<size_x1; i++)
524  for (size_t j=0; j<size_x2; j++)
525  ydata[i+j*size_x1] = yy[i][j];
526 
527  gsl_interp2d *interp = gsl_interp2d_alloc(TT, size_x1, size_x2);
528  gsl_interp2d_init(interp, x1.data(), x2.data(), ydata, size_x1, size_x2);
529 
530  double val;
531  if (extr)
532  val= gsl_interp2d_eval_extrap(interp, x1.data(), x2.data(), ydata, _x1, _x2, x1acc, x2acc);
533  else
534  val= gsl_interp2d_eval(interp, x1.data(), x2.data(), ydata, _x1, _x2, x1acc, x2acc);
535 
536  gsl_interp2d_free(interp);
537  gsl_interp_accel_free(x1acc);
538  gsl_interp_accel_free(x2acc);
539  delete ydata;
540 
541  return val;
542 }
543 
544 // ============================================================================
545 
546 std::vector<double> cbl::linear_interpolation_3D (const std::vector<double> min, std::vector<double> max, std::vector<int> steps, std::vector<std::vector<std::vector<double>>> func, const std::vector<std::vector<double>> pos)
547 {
548  if (min.size()!= 3 || max.size()!=3 || steps.size() !=3)
549  ErrorCBL("the input grid have a wrong dimension", "linear_interpolation_nD", "Func.cpp");
550 
551  vector<double> output(pos.size());
552  vector<double> step_dim(3);
553  for (auto i=0; i<3; i++) step_dim[i] = (max[i]-min[i])/steps[i];
554 
555  for (size_t i=0; i<pos.size(); i++) {
556 
557  vector<int> inds(3);
558  for (int dim=0; dim<3; dim++) {
559  inds[dim] = (pos[i][dim]-min[dim])/step_dim[dim];
560  if (inds[dim]<0 || (inds[dim]+1)*step_dim[dim]+min[dim] > max[dim])
561  ErrorCBL("Point out of grid", "linear_interpolation_3D", "Func.cpp");
562  }
563  double tempX1 = ((pos[i][0]-(min[0]+inds[0]*step_dim[0]))*func[inds[2]][inds[1]][inds[0]+1] -
564  (pos[i][0]-(min[0]+(inds[0]+1)*step_dim[0]))*func[inds[2]][inds[1]][inds[0]])/step_dim[0];
565  double tempX2 = ((pos[i][0]-(min[0]+inds[0]*step_dim[0]))*func[inds[2]][inds[1]+1][inds[0]+1] -
566  (pos[i][0]-(min[0]+(inds[0]+1)*step_dim[0]))*func[inds[2]][inds[1]+1][inds[0]])/step_dim[0];
567  double tempX3 = ((pos[i][0]-(min[0]+inds[0]*step_dim[0]))*func[inds[2]+1][inds[1]][inds[0]+1] -
568  (pos[i][0]-(min[0]+(inds[0]+1)*step_dim[0]))*func[inds[2]+1][inds[1]][inds[0]])/step_dim[0];
569  double tempX4 = ((pos[i][0]-(min[0]+inds[0]*step_dim[0]))*func[inds[2]+1][inds[1]+1][inds[0]+1] -
570  (pos[i][0]-(min[0]+(inds[0]+1)*step_dim[0]))*func[inds[2]+1][inds[1]+1][inds[0]])/step_dim[0];
571  double tempY1 = ((pos[i][1]-(min[1]+inds[1]*step_dim[1]))*tempX2 - (pos[i][1]-(min[1]+(inds[1]+1)*step_dim[1]))*tempX1)/step_dim[1];
572  double tempY2 = ((pos[i][1]-(min[1]+inds[1]*step_dim[1]))*tempX4 - (pos[i][1]-(min[1]+(inds[1]+1)*step_dim[1]))*tempX3)/step_dim[1];
573  output[i] = ((pos[i][2]-(min[2]+inds[2]*step_dim[2]))*tempY2 - (pos[i][2]-(min[2]+(inds[2]+1)*step_dim[2]))*tempY1)/step_dim[2];
574  }
575 
576  return output;
577 }
578 
579 // ============================================================================
580 
581 
582 void cbl::read_vector (const std::string file_vector, std::vector<double> &xx, std::vector<double> &vec, const std::vector<int> col)
583 {
584  vector<int> cols = {0, 1};
585  cols = (col.size() != 2) ? cols : col;
586  const size_t max_col = Max(cols);
587 
588  xx.erase(xx.begin(), xx.end());
589  vec.erase(vec.begin(), vec.end());
590 
591  ifstream fin(file_vector.c_str()); checkIO(fin, file_vector);
592 
593  string line;
594 
595  while (getline(fin, line)) {
596  stringstream ss(line);
597  vector<double> num; double NN = -1.e30;
598  while (ss>>NN) num.push_back(NN);
599  if (num.size()>=max_col) {
600  xx.push_back(num[cols[0]]);
601  vec.push_back(num[cols[1]]);
602  }
603  }
604 
605  fin.clear(); fin.close();
606 }
607 
608 
609 // ============================================================================
610 
611 
612 void cbl::read_matrix (const std::string file_matrix, std::vector<double> &xx, std::vector<double> &yy, std::vector<std::vector<double>> &matrix, const std::vector<int> col)
613 {
614  vector<int> cols = {0, 1, 2};
615  cols = (col.size() != 3) ? cols : col;
616  const size_t max_col = Max(cols);
617 
618  matrix.erase(matrix.begin(), matrix.end());
619 
620  ifstream fin(file_matrix.c_str()); checkIO(fin, file_matrix);
621 
622  vector<double> vv;
623  matrix.push_back(vv);
624  string line; size_t i = 0;
625 
626  vector<double> _xx, _yy;
627  while (getline(fin, line)) {
628  stringstream ss(line);
629  vector<double> num; double NN = -1.e30;
630  while (ss>>NN) num.push_back(NN);
631  if (num.size()>=max_col) {
632  _xx.push_back(num[cols[0]]);
633  _yy.push_back(num[cols[1]]);
634  matrix[i].push_back(num[cols[2]]);
635  }
636  else {i++; matrix.push_back(vv);}
637  }
638 
639  xx = different_elements(_xx);
640  yy = different_elements(_yy);
641 
642  fin.clear(); fin.close();
643 
644 }
645 
646 //==================================================================================================================
647 
648 double cbl::determinant_matrix (const std::vector<std::vector<double>> mat)
649 {
650  int n = mat.size();
651  int s;
652  gsl_matrix *mm = gsl_matrix_alloc(n, n);
653  gsl_permutation *perm = gsl_permutation_alloc(n);
654 
655  for (int i=0; i<n; i++)
656  for (int j=0; j<n; j++)
657  gsl_matrix_set(mm, i, j, mat[i][j]);
658 
659  // make the LU decomposition of the matrix mm
660  gsl_linalg_LU_decomp(mm, perm, &s);
661  double det = gsl_linalg_LU_det(mm, s);
662 
663  gsl_matrix_free(mm);
664  gsl_permutation_free(perm);
665 
666  return det;
667 }
668 
669 
670 // ============================================================================
671 
672 
673 void cbl::invert_matrix (const std::vector<std::vector<double>> mat, std::vector<std::vector<double>> &mat_inv, const double prec, const int Nres)
674 {
675  int size = mat.size();
676 
677  Eigen::MatrixXd matrix = cbl::wrapper::eigen::MatrixToEigen(mat);
678  Eigen::MatrixXd inverse = matrix.inverse();
679 
680  Eigen::MatrixXd unity = matrix * inverse;
681 
682  for (int i=0; i<size; i++) {
683  for (int j=0; j<size; j++) {
684  const double fact = (i==j) ? 1 : 0;
685  double prod = unity(i, j);
686  if (fabs(fact-prod)>prec)
687  WarningMsgCBL("exceeded precision for element "+conv(i, par::fINT)+" "+conv(j, par::fINT)+"; "+conv(fact, par::fDP4)+" "+conv(prod, par::fDP4)+"!", "invert_matrix", "Func.cpp");
688  }
689  }
690 
691  if (Nres>0) {
692  const double fact = 1.-(size+1.)/(Nres-1.); // correction factor from Hartlap, Simon and Schneider 2006
693  inverse *= fact;
694  }
695 
696  mat_inv = cbl::wrapper::eigen::EigenToMatrix(inverse);
697 
698 
699 }
700 
701 
702 // ============================================================================
703 
704 
705 void cbl::invert_matrix (const std::vector<std::vector<double>> mat, std::vector<std::vector<double>> &mat_inv, const int i1, const int i2, const double prec, const int Nres)
706 {
707  int n = i2-i1;
708  int s;
709  if (n==0)
710  ErrorCBL("the input matrix has null size", "invert_matrix", "Func.cpp");
711 
712  mat_inv.erase(mat_inv.begin(), mat_inv.end());
713  mat_inv = mat;
714 
715  gsl_matrix *mm = gsl_matrix_alloc(n, n);
716  gsl_matrix *im = gsl_matrix_alloc(n, n);
717  gsl_permutation * perm = gsl_permutation_alloc(n);
718 
719  for (int i=i1; i<i2; i++)
720  for (int j=i1; j<i2; j++)
721  gsl_matrix_set(mm, i-i1, j-i1, mat[i][j]);
722 
723  // make the lower–upper (LU) decomposition of the matrix mm
724  gsl_linalg_LU_decomp(mm, perm, &s);
725 
726  // invert the matrix mm
727  gsl_linalg_LU_invert(mm, perm, im);
728 
729  for (int i=0; i<n; i++) {
730  for (int j=0; j<n; j++) {
731  double fact = (i==j) ? 1 : 0;
732  double prod = 0;
733  for (int el=0; el<n; el++)
734  prod += mat[i+i1][el+i1]*gsl_matrix_get(im, el, j);
735 
736  if (fabs(fact-prod)>prec)
737  WarningMsgCBL("Exceeded precision for element "+conv(i,par::fINT)+" "+conv(j,par::fINT)+"; "+conv(fact,par::fDP4)+" "+conv(prod,par::fDP4)+"!", "invert_matrix", "Func.cpp");
738  }
739  }
740 
741  const double fact = (Nres>0) ? 1.-(mat[0].size()+1.)/(Nres-1.) : 1.; // correction factor from Hartlap, Simon and Schneider 2006
742 
743  for (size_t i=0; i<mat.size(); i++) {
744  for (size_t j=0; j<mat[i].size(); j++) {
745  if (int(i)<i2 && int(i)>=i1 && int(j)<i2 && int(j)>=i1)
746  mat_inv[i][j] = gsl_matrix_get(im, i-i1, j-i1)*fact;
747  else
748  mat_inv[i][j] = 0.;
749  }
750  }
751 
752  gsl_matrix_free(mm);
753  gsl_matrix_free(im);
754  gsl_permutation_free(perm);
755 }
756 
757 
758 // ============================================================================
759 
760 
761 void cbl::covariance_matrix (const std::vector<std::vector<double>> mat, std::vector<std::vector<double>> &cov, const bool JK)
762 {
763  cov.erase(cov.begin(), cov.end());
764  vector<double> vv (mat[0].size(), 0.);
765  for (size_t i=0; i<mat[0].size(); i++) cov.push_back(vv);
766 
767 
768  // measure the mean values at each bin
769 
770  vector<double> mean;
771 
772  for (size_t i=0; i<mat[0].size(); i++) { // loop on the i-th bin
773 
774  vector<double> vect_temp;
775  for (size_t j=0; j<mat.size(); j++) // loop on the j-th realisation
776  vect_temp.push_back(mat[j][i]);
777 
778  if (vect_temp.size()>2)
779  mean.push_back(Average(vect_temp));
780  else
781  mean.push_back(-1.e30);
782 
783  }
784 
785 
786  // compute the elements of the covariance matrix
787 
788  for (size_t i=0; i<cov.size(); i++)
789  for (size_t j=0; j<cov.size(); j++) {
790  int nm = 0;
791  for (size_t k=0; k<mat.size(); k++) {
792  if (mean[i]>-1.e30) {
793  cov[i][j] += (mean[i]-mat[k][i])*(mean[j]-mat[k][j]);
794  nm ++;
795  }
796  }
797 
798  if (nm>1) cov[i][j] = (JK) ? double(nm-1)/(nm)*cov[i][j] : cov[i][j]/(nm-1);
799  }
800 
801 }
802 
803 
804 // ============================================================================
805 
806 
807 void cbl::covariance_matrix (const std::vector<std::string> file, std::vector<double> &rad, std::vector<double> &mean, std::vector<std::vector<double>> &cov, const bool JK)
808 {
809  vector<vector<double>> xi_mocks;
810 
811  string line; double r,xi;
812  for (size_t i=0; i<file.size(); i++) {
813  rad.erase(rad.begin(),rad.end());
814 
815  ifstream fin(file[i].c_str()); checkIO(fin, file[i]);
816  getline(fin, line);
817 
818  vector<double> vv;
819  while (getline(fin,line)) {
820  stringstream ss(line);
821  ss >> r; ss >> xi;
822  rad.push_back(r);
823  vv.push_back(xi);
824  }
825  fin.clear(); fin.close();
826 
827  xi_mocks.push_back(vv);
828  }
829 
830  covariance_matrix(xi_mocks, cov, JK);
831 
832  mean.erase(mean.begin(),mean.end());
833 
834  for (size_t i=0; i<rad.size(); i++) {
835  vector<double> vv;
836 
837  for (size_t j=0; j<xi_mocks.size(); j++)
838  if (xi_mocks[j][i]>-1.e30)
839  vv.push_back(xi_mocks[j][i]);
840 
841  mean.push_back(Average(vv));
842  }
843 
844 }
845 
846 // ============================================================================
847 
848 
849 void cbl::covariance_matrix (const std::vector<std::string> file, const std::string covariance_matrix_file, const bool JK)
850 {
851  vector<double> rad, mean;
852  vector<vector<double>> cov;
853  covariance_matrix(file, rad, mean, cov, JK);
854 
855  ofstream fout(covariance_matrix_file.c_str()); checkIO(fout, covariance_matrix_file);
856 
857  for (size_t i=0; i<rad.size(); i++) {
858  for (size_t j=0; j<rad.size(); j++)
859  fout << rad[i] << " " << rad[j] << " " << cov[i][j] << " " << cov[i][j]/sqrt(cov[i][i]*cov[j][j]) << endl;
860  fout << endl;
861  }
862 
863  fout.clear(); fout.close();
864 }
865 
866 
867 // ============================================================================
868 
869 
870 double cbl::Average (const std::vector<double> vect)
871 {
872  if (vect.size()==0) ErrorCBL("the input vector has null size", "Average", "Func.cpp");
873 
874  double aver = 0., NT = 0.;
875 
876 #pragma omp parallel num_threads(omp_get_max_threads())
877  {
878 
879  double averT = 0., nT = 0.;
880 
881 #pragma omp for schedule(static, 2)
882  for (size_t i=0; i<vect.size(); ++i)
883  averT += 1./(++nT)*(vect[i]-averT);
884 
885 #pragma omp critical
886  aver += ((NT+=nT)>0) ? nT/NT*(averT-aver) : 0.;
887 
888  }
889 
890  return aver;
891 }
892 
893 
894 // ============================================================================
895 
896 
897 double cbl::Average (const std::vector<double> vect, const std::vector<double> weight)
898 {
899  if (vect.size()==0 || vect.size()!=weight.size())
900  ErrorCBL("the input vector has null size, or vect.size()!=weight.size()!", "Average", "Func.cpp");
901 
902  double aver = 0., WeightTOT = 0.;
903 
904 #pragma omp parallel num_threads(omp_get_max_threads())
905  {
906 
907  double averT = 0., WeightT = 0.;
908 
909 #pragma omp for schedule(static, 2)
910  for (size_t i=0; i<vect.size(); ++i)
911  averT += weight[i]/(WeightT+=weight[i])*(vect[i]-averT);
912 
913 #pragma omp critical
914  aver += ((WeightTOT+=WeightT)>0) ? WeightT/WeightTOT*(averT-aver) : 0.;
915 
916  }
917 
918  return aver;
919 }
920 
921 
922 // ============================================================================
923 
924 
925 double cbl::Sigma (const std::vector<double> vect)
926 {
927  if (vect.size()==0) ErrorCBL("the input vector has null size", "Sigma", "Func.cpp");
928 
929  double aver_n1 = 0., aver_n = 0., Sn = 0., sigma = 0., NT = 0.;
930 
931 #pragma omp parallel num_threads(omp_get_max_threads())
932  {
933 
934  double aver_n1T = 0., aver_nT = 0., SnT = 0., nT = 0.;
935 
936 #pragma omp for schedule(static, 2)
937  for (size_t i=0; i<vect.size(); ++i) {
938  aver_n1T = aver_nT;
939  aver_nT += 1./(++nT)*(vect[i]-aver_nT);
940  SnT += (vect[i]-aver_n1T)*(vect[i]-aver_nT);
941  }
942 
943 #pragma omp critical
944  {
945  NT += nT;
946  if (NT>0) {
947  aver_n1 = aver_n;
948  aver_n += nT/NT*(aver_nT-aver_n);
949  Sn += SnT+pow((aver_nT-aver_n1), 2)*nT*(NT-nT)/NT;
950  sigma = sqrt(Sn/NT);
951  }
952  }
953 
954  }
955 
956  return sigma;
957 }
958 
959 
960 // ============================================================================
961 
962 
963 double cbl::Sigma (const std::vector<double> vect, const std::vector<double> weight)
964 {
965  if (vect.size()==0 || vect.size()!=weight.size())
966  ErrorCBL("the input vector has null size, or vect.size()!=weight.size()!", "Sigma", "Func.cpp");
967 
968  double aver_n1 = 0., aver_n = 0., Sn = 0., sigma = 0., WeightTOT = 0.;
969 
970 #pragma omp parallel num_threads(omp_get_max_threads())
971  {
972 
973  double aver_n1T = 0., aver_nT = 0., SnT = 0., WeightT = 0.;
974 
975 #pragma omp for schedule(static, 2)
976  for (size_t i=0; i<vect.size(); ++i) {
977  aver_n1T = aver_nT;
978  aver_nT += weight[i]/(WeightT+=weight[i])*(vect[i]-aver_nT);
979  SnT += weight[i]*(vect[i]-aver_n1T)*(vect[i]-aver_nT);
980  }
981 
982 #pragma omp critical
983  {
984  WeightTOT += WeightT;
985  if (WeightTOT>0) {
986  aver_n1 = aver_n;
987  aver_n += WeightT/WeightTOT*(aver_nT-aver_n);
988  Sn += SnT+pow((aver_nT-aver_n1), 2)*WeightT*(WeightTOT-WeightT)/WeightTOT;
989  sigma = sqrt(Sn/WeightTOT);
990  }
991  }
992 
993  }
994 
995  return sigma;
996 }
997 
998 
999 // ============================================================================
1000 
1001 
1002 vector<double> cbl::Quartile (const std::vector<double> Vect)
1003 {
1004  vector<double> vect = Vect;
1005  sort(vect.begin(), vect.end());
1006  vector<double> vect1, vect2;
1007 
1008  int start, n = vect.size();
1009  double first = 0., second = 0., third = 0.;
1010 
1011  if (n>0) {
1012  if (n==1) {
1013  first = -1e10;
1014  second = vect[0];
1015  third = 1e10;
1016  }
1017  if (n>1) {
1018  if (n % 2 == 0) // the number of elemens is even
1019  start = int(vect.size()*0.5);
1020  else
1021  start = int(vect.size()*0.5)+1;
1022 
1023  for (size_t i=0; i<vect.size()*0.5; i++)
1024  vect1.push_back(vect[i]);
1025  for (size_t i=start; i<vect.size(); i++)
1026  vect2.push_back(vect[i]);
1027 
1028  // first quartile
1029  n = vect1.size();
1030  if (n % 2 == 0)
1031  first = (vect1[n*0.5-1]+vect1[(n*0.5)])*0.5;
1032  else
1033  first = vect1[(n+1)*0.5-1];
1034 
1035  // second quartile = median
1036  n = vect.size();
1037  if (n % 2 == 0)
1038  second = (vect[n*0.5-1]+vect[(n*0.5)])*0.5;
1039  else
1040  second = vect[(n+1)*0.5-1];
1041 
1042  // third quartile
1043  n = vect2.size();
1044  if (n % 2 == 0)
1045  third = (vect2[n*0.5-1]+vect2[(n*0.5)])*0.5;
1046  else
1047  third = vect2[(n+1)*0.5-1];
1048  }
1049  }
1050 
1051  return {first, second, third};
1052 }
1053 
1054 
1055 // ============================================================================
1056 
1057 
1058 void cbl::Moment (const std::vector<double> data, double &ave, double &adev, double &sdev, double &var, double &skew, double &curt)
1059 {
1060  ave = gsl_stats_mean(data.data(), 1, data.size());
1061  adev = gsl_stats_absdev_m(data.data(), 1, data.size(), ave);
1062  var = gsl_stats_variance_m(data.data(), 1, data.size(), ave);
1063  sdev = sqrt(var);
1064  skew = gsl_stats_skew_m_sd(data.data(), 1, data.size(), ave, sdev);
1065  curt = gsl_stats_kurtosis_m_sd(data.data(), 1, data.size(), ave, sdev);
1066 }
1067 
1068 
1069 // ============================================================================
1070 
1071 
1072 double cbl::relative_error_beta (const double bias, const double Volume, const double density) // from Eq. 20 of Bianchi et al. 2012
1073 {
1074  double n0 = 1.7e-4; // in (h/Mpc)^3
1075  double CC = 4.9e2; // in (Mpc/h)^1.5
1076 
1077  return CC*pow(bias,0.7)/sqrt(Volume)*exp(n0/(bias*bias*density))*100.;
1078 }
1079 
1080 
1081 // ============================================================================
1082 
1083 
1084 void cbl::measure_var_function (const std::vector<double> var, const int bin, const double V_min, const double V_max, const double Volume, std::vector<double> &Var, std::vector<double> &Phi, std::vector<double> &err)
1085 {
1086  if (var.size()==0) ErrorCBL("there are no objectes in the sample!", "measure_var_function", "Func.cpp");
1087 
1088  Var.erase(Var.begin(),Var.end());
1089  Phi.erase(Phi.begin(),Phi.end());
1090  err.erase(err.begin(),err.end());
1091 
1092  double delta_logV = (log10(V_max)-log10(V_min))/bin;
1093  double V1 = V_min;
1094  double V2 = V_min*pow(10.,delta_logV);
1095 
1096  for (int y=0; y<bin; y++) {
1097  double nHalo = 0.;
1098 
1099  for (size_t k=0; k<var.size(); k++)
1100  if (V1<var[k] && var[k]<=V2) nHalo ++;
1101 
1102  double PHI = nHalo/(V2-V1)/Volume;
1103  double ERR = sqrt(nHalo)/(V2-V1)/Volume;
1104 
1105  Var.push_back(pow(10.,(log10(V1)+log10(V2))*0.5));
1106  Phi.push_back(PHI);
1107  err.push_back(ERR);
1108 
1109  V1 = V2;
1110  V2 = V1*pow(10.,delta_logV);
1111  }
1112 }
1113 
1114 
1115 // ============================================================================================
1116 
1117 
1118 void cbl::bin_function (const std::string file_grid, double func(double, void *), void *par, const int bin, const double x_min, const double x_max, const std::string binning, std::vector<double> &xx, std::vector<double> &yy)
1119 {
1120  if (binning != "lin" && binning != "loglin" && binning != "log")
1121  ErrorCBL("binning can only be: lin, loglin or log!", "bin_function", "Func.cpp");
1122 
1123  xx.resize(bin), yy.resize(bin);
1124 
1125  ifstream fin (file_grid.c_str());
1126 
1127  if (fin) {
1128 
1129  double XX, YY;
1130 
1131  for (int i=0; i<bin; i++) {
1132  fin >>XX>>YY;
1133  xx[i] = XX;
1134  yy[i] = YY;
1135  }
1136  fin.clear(); fin.close();
1137 
1138  if (int(xx.size())!=bin)
1139  ErrorCBL("xx.size()="+conv(xx.size(),par::fINT)+" != bin="+conv(bin,par::fINT)+"!", "bin_function", "Func.cpp");
1140  }
1141 
1142  else {
1143 
1144  coutCBL <<"I'm creating the grid file: "<<file_grid<<"..."<<endl;
1145 
1146  fin.clear(); fin.close();
1147 
1148  double X_min = x_min;
1149  double X_max = x_max;
1150 
1151  if (binning != "lin") {
1152  if (x_min<0 || x_max<0)
1153  ErrorCBL("x_min="+conv(x_min,par::fDP3)+", x_max="+conv(x_max,par::fDP3)+"!", "bin_function", "Func.cpp");
1154 
1155  X_min = log10(x_min);
1156  X_max = log10(x_max);
1157  }
1158 
1159  xx = linear_bin_vector(bin, X_min, X_max);
1160 
1161  ofstream fout(file_grid.c_str()); checkIO(fout, file_grid);
1162 
1163  for (size_t i=0; i<xx.size(); i++) {
1164  yy[i] = (binning=="lin") ? func(xx[i], par) : func(pow(10., xx[i]), par);
1165 
1166  if (binning=="log") {
1167  if (yy[i]<0) ErrorCBL("yy[i]<0!", "bin_function", "Func.cpp");
1168  else yy[i] = log10(yy[i]);
1169  }
1170 
1171  fout <<xx[i]<<" "<<yy[i]<<endl;
1172  coutCBL <<xx[i]<<" "<<yy[i]<<endl;
1173  }
1174  fout.clear(); fout.close(); coutCBL <<"I wrote the file: "<<file_grid<<endl;
1175  }
1176 
1177 }
1178 
1179 
1180 // ============================================================================================
1181 
1182 
1183 void cbl::bin_function_2D (const std::string file_grid, double func(double *, size_t, void *), void *par, const int bin, const double x1_min, const double x1_max, const double x2_min, const double x2_max, const std::string binning, std::vector<double> &xx1, std::vector<double> &xx2, std::vector<std::vector<double>> &yy)
1184 {
1185  if (binning != "lin" && binning != "loglin" && binning != "log")
1186  ErrorCBL("binning can only be: lin, loglin or log !", "bin_function_2D", "Func.cpp");
1187 
1188  xx1.resize(bin), xx2.resize(bin); yy.resize(bin);
1189 
1190  ifstream fin (file_grid.c_str());
1191 
1192  if (fin) {
1193 
1194  double XX1, XX2, YY;
1195 
1196  for (int i=0; i<bin; i++) {
1197  for (int j=0; j<bin; j++) {
1198  fin >>XX1>>XX2>>YY;
1199 
1200  if (j==0) xx1[i] = XX1;
1201  if (i==0) xx2[j] = XX2;
1202  yy[i].push_back(YY);
1203  }
1204  }
1205  fin.clear(); fin.close();
1206 
1207  if (int(xx1.size())!=bin || int(xx2.size())!=bin)
1208  ErrorCBL("xx1.size()="+conv(xx1.size(),par::fINT)+", xx2.size()="+conv(xx2.size(),par::fINT)+" != bin="+conv(bin,par::fINT)+"!", "bin_function_2D", "Func.cpp");
1209 
1210  }
1211 
1212  else {
1213 
1214  coutCBL <<"I'm creating the grid file: "<<file_grid<<"..."<<endl;
1215 
1216  fin.clear(); fin.close();
1217 
1218  double X1_min = x1_min;
1219  double X1_max = x1_max;
1220  double X2_min = x2_min;
1221  double X2_max = x2_max;
1222 
1223  if (binning != "lin") {
1224  if (x1_min<0 || x1_max<0 || x2_min<0 || x2_max<0)
1225  ErrorCBL("x1_min="+conv(x1_min,par::fDP3)+", x1_max="+conv(x1_max,par::fDP3)+", x2_min="+conv(x2_min,par::fDP3)+", x2_max="+conv(x2_max,par::fDP3)+"!", "bin_function_2D", "Func.cpp");
1226 
1227  X1_min = log10(x1_min);
1228  X1_max = log10(x1_max);
1229  X2_min = log10(x2_min);
1230  X2_max = log10(x2_max);
1231  }
1232 
1233  xx1 = linear_bin_vector(bin, X1_min, X1_max);
1234  xx2 = linear_bin_vector(bin, X2_min, X2_max);
1235 
1236  ofstream fout(file_grid.c_str()); checkIO(fout, file_grid);
1237  double vec[2];
1238 
1239  for (int i=0; i<bin; i++) {
1240  for (int j=0; j<bin; j++) {
1241 
1242  if (binning=="lin") {vec[0] = xx1[i]; vec[1] = xx2[j];}
1243  else {vec[0] = pow(10.,xx1[i]); vec[1] = pow(10.,xx2[j]);}
1244 
1245  double ff = (binning=="log") ? log10(func(vec, 2, par)) : func(vec, 2, par);
1246  yy[i].push_back(ff);
1247 
1248  fout <<xx1[i]<<" "<<xx2[j]<<" "<<yy[i][j]<<endl;
1249  coutCBL <<"--> "<<xx1[i]<<" "<<xx2[j]<<" "<<yy[i][j]<<endl;
1250 
1251  }
1252  }
1253 
1254  fout.clear(); fout.close(); coutCBL <<"I wrote the file: "<<file_grid<<endl;
1255  }
1256 
1257 }
1258 
1259 
1260 // ============================================================================================
1261 
1263 
1264 double cbl::func_grid_lin (double xx, void *params)
1265 {
1266  struct cbl::glob::STR_grid *pp = (struct cbl::glob::STR_grid *) params;
1267 
1268  return interpolated(xx, pp->_xx, pp->_yy, "Linear");
1269 }
1270 
1271 
1272 // ============================================================================================
1273 
1274 
1275 double cbl::func_grid_loglin (double xx, void *params)
1276 {
1277  struct cbl::glob::STR_grid *pp = (struct cbl::glob::STR_grid *) params;
1278 
1279  double lgx = log10(xx);
1280 
1281  return interpolated(lgx, pp->_xx, pp->_yy, "Linear");
1282 }
1283 
1284 
1285 // ============================================================================================
1286 
1287 
1288 double cbl::func_grid_log (double xx, void *params)
1289 {
1290  struct cbl::glob::STR_grid *pp = (struct cbl::glob::STR_grid *) params;
1291 
1292  double lgx = log10(xx);
1293 
1294  return pow(10., interpolated(lgx, pp->_xx, pp->_yy, "Linear"));
1295 }
1296 
1297 
1298 // ============================================================================================
1299 
1300 
1301 double cbl::func_grid_lin_2D (double *xx, size_t dim, void *params)
1302 {
1303  (void)dim;
1304 
1305  struct cbl::glob::STR_grid_2D *pp = (struct cbl::glob::STR_grid_2D *) params;
1306 
1307  return interpolated_2D(xx[0], xx[1], pp->_xx1, pp->_xx2, pp->_yy, "Linear");
1308 }
1309 
1310 
1311 // ============================================================================================
1312 
1313 
1314 double cbl::func_grid_loglin_2D (double *xx, size_t dim, void *params)
1315 {
1316  (void)dim;
1317 
1318  struct cbl::glob::STR_grid_2D *pp = (struct cbl::glob::STR_grid_2D *) params;
1319 
1320  double lgx1 = log10(xx[0]);
1321  double lgx2 = log10(xx[1]);
1322 
1323  return interpolated_2D(lgx1, lgx2, pp->_xx1, pp->_xx2, pp->_yy, "Linear");
1324 }
1325 
1326 
1327 // ============================================================================================
1328 
1329 
1330 double cbl::func_grid_log_2D (double *xx, size_t dim, void *params)
1331 {
1332  (void)dim;
1333 
1334  struct cbl::glob::STR_grid_2D *pp = (struct cbl::glob::STR_grid_2D *) params;
1335 
1336  double lgx1 = log10(xx[0]);
1337  double lgx2 = log10(xx[1]);
1338 
1339  return pow(10., interpolated_2D(lgx1, lgx2, pp->_xx1, pp->_xx2, pp->_yy, "Linear"));
1340 }
1341 
1343 
1344 // ============================================================================================
1345 
1346 
1347 void cbl::sdss_atbound (double &angle, const double minval, const double maxval)
1348 {
1349  while (angle < minval)
1350  angle += 360.;
1351 
1352  while (angle > maxval)
1353  angle -= 360.0;
1354 }
1355 
1356 void cbl::sdss_atbound2 (double &theta, double &phi)
1357 {
1358  sdss_atbound(theta, -180.0, 180.0);
1359 
1360  if (fabs(theta)>90) {
1361  theta = 180.0 - theta;
1362  phi += 180.0;
1363  }
1364 
1365  sdss_atbound(theta, -180.0, 180.0);
1366  sdss_atbound(phi, 0.0, 360.0);
1367 
1368  if (fabs(theta)==90.)
1369  phi = 0.0;
1370 }
1371 
1372 
1373 void cbl::eq2sdss (const std::vector<double> ra, const std::vector<double> dec, std::vector<double> &lambda, std::vector<double> &eta)
1374 {
1375  lambda.resize(ra.size());
1376  eta.resize(ra.size());
1377 
1378  double SurveyCenterRa = 185.-90, SurveyCenterDec = 32.5;
1379  double d2r = par::pi/180.;
1380 
1381  for (size_t i=0; i<ra.size(); i++) {
1382  double x = cos((ra[i]-SurveyCenterRa*d2r))*cos(dec[i]);
1383  double y = sin((ra[i]-SurveyCenterRa*d2r))*cos(dec[i]);
1384  double z = sin(dec[i]);
1385 
1386  lambda[i] = -asin(x)/d2r;
1387  eta[i] = atan2(z, y)/d2r - SurveyCenterDec;
1388 
1389  sdss_atbound(eta[i], -180.0, 180.0);
1390  }
1391 }
1392 
1393 
1394 // ============================================================================
1395 
1396 
1397 void cbl::sdss2eq (const std::vector<double> lambda, const std::vector<double> eta, std::vector<double> &ra, std::vector<double> &dec)
1398 {
1399  ra.resize(lambda.size());
1400  dec.resize(lambda.size());
1401 
1402  double SurveyCenterRa = 185., SurveyCenterDec = 32.5;
1403  double d2r = par::pi/180.;
1404 
1405  for (size_t i=0; i<ra.size(); i++) {
1406  double x = -1.0*sin(lambda[i]*d2r);
1407  double y = cos(lambda[i]*d2r)*cos(eta[i]*d2r+SurveyCenterDec*d2r);
1408  double z = cos(lambda[i]*d2r)*sin(eta[i]*d2r+SurveyCenterDec*d2r);
1409 
1410  ra[i] = atan2(y,x)/d2r+SurveyCenterRa-90;
1411  dec[i] = asin(z)/d2r;
1412  sdss_atbound2(dec[i], ra[i]);
1413  }
1414 }
1415 
1416 
1417 // ============================================================================
1418 
1419 
1420 void cbl::sdss_stripe (const std::vector<double> eta, const std::vector<double> lambda, std::vector<int> &stripe, std::vector<int> &str_u)
1421 {
1422  stripe.resize(eta.size());
1423  str_u.resize(eta.size());
1424 
1425  double stripe_sep=2.5;
1426  double cen = 58.75;
1427 
1428  for (size_t i=0; i<eta.size(); i++) {
1429 
1430  if (lambda[i]<90.0) stripe[i] = (eta[i]+cen)/stripe_sep;
1431  if (lambda[i]>90.0) stripe[i] = (eta[i]+cen+180.)/stripe_sep;
1432 
1433  str_u[i] = stripe[i];
1434  }
1435 
1436  sort(str_u.begin(), str_u.end());
1437  vector<int>::iterator it = unique(str_u.begin(), str_u.end());
1438  str_u.resize(distance(str_u.begin(), it));
1439 
1440 }
1441 
1442 
1443 // ============================================================================
1444 
1445 
1446 double cbl::number_from_distribution (const std::vector<double> xx, const std::vector<double> fx, const double xmin, const double xmax, const int seed)
1447 {
1448  return vector_from_distribution(1, xx, fx, xmin, xmax, seed)[0];
1449 }
1450 
1451 
1452 // ============================================================================
1453 
1454 
1455 std::vector<double> cbl::vector_from_distribution (const int nRan, const std::vector<double> xx, const std::vector<double> fx, const double xmin, const double xmax, const int seed)
1456 {
1457  random::UniformRandomNumbers ran(0., 1., seed);
1458 
1459  int sz = 100;
1460  bool Try = true;
1461 
1462  vector<double> Fx, new_x;
1463 
1464  while (Try) {
1465 
1466  vector<double> Fx_test(sz, 0.);
1467  const vector<double> new_x_test = linear_bin_vector(sz, xmin, xmax);
1468 
1469  glob::FuncGrid dist(xx, fx, "Spline");
1470  const double NN = dist.integrate_qag(xmin, xmax);
1471 
1472  for (int i=1; i<sz; ++i)
1473  Fx_test[i] = dist.integrate_qag(xmin, new_x_test[i])/NN;
1474 
1475  if (is_sorted(Fx_test.begin(), Fx_test.end())) {
1476  Fx = Fx_test;
1477  new_x = new_x_test;
1478  Try = false;
1479  }
1480 
1481  sz --;
1482  if (sz<30) ErrorCBL("the input distribution cannot be integrated properly!", "vector_from_distribution", "Func.cpp");
1483 
1484  }
1485 
1486  glob::FuncGrid ff(Fx, new_x, "Spline");
1487 
1488  vector<double> varRandom;
1489 
1490  while (varRandom.size()<unsigned(nRan)) {
1491  double xx = ff(ran());
1492  if (xmin<=xx && xx<=xmax)
1493  varRandom.emplace_back(xx);
1494  }
1495 
1496  return varRandom;
1497 }
1498 
1499 
1500 // ============================================================================
1501 
1502 
1503 std::vector<size_t> cbl::minimum_maximum_indexes (const std::vector<double> xx, const double x_min, const double x_max)
1504 {
1505  size_t ind1 = xx.size(), ind2 = 0;
1506 
1507  for (size_t i=0; i<xx.size(); i++)
1508  if (x_min<xx[i] && xx[i]<x_max) {
1509  ind1 = min(i, ind1);
1510  ind2 = max(i, ind2);
1511  }
1512 
1513  ind2 ++;
1514 
1515  return {ind1, ind2};
1516 }
1517 
1518 
1519 // ============================================================================
1520 
1521 
1522 void cbl::read_invert_covariance (const std::string filecov, std::vector< std::vector<double>> &cov, std::vector<std::vector<double>> &cov_inv, const size_t i1, const size_t i2, const double prec, const int Nres)
1523 {
1524  size_t size = i2-i1+1;
1525 
1526  cov.erase(cov.begin(), cov.end());
1527  cov_inv.erase(cov_inv.begin(), cov_inv.end());
1528 
1529  ifstream fin(filecov.c_str()); checkIO(fin, filecov);
1530 
1531  cov.erase(cov.begin(), cov.end());
1532 
1533  vector<double> vv;
1534  cov.push_back(vv);
1535  string line; size_t i = 0;
1536 
1537  while (getline(fin, line)) {
1538  stringstream ss(line);
1539  vector<double> num; double NN = -1.e30;
1540  while (ss>>NN) num.push_back(NN);
1541  if (num.size()==3 && num[2]>-1.e29)
1542  cov[i].push_back(num[2]);
1543  else {i++; cov.push_back(vv);}
1544  }
1545 
1546  cov.erase(cov.end()-1, cov.end());
1547  fin.clear(); fin.close();
1548 
1549  cov_inv = cov;
1550  vector<vector<double>> cov_lim(size,vector<double>(size, 0)), cov_lim_inv;
1551 
1552  size_t tot_size = cov.size();
1553 
1554  for (size_t i=0; i<tot_size; i++) {
1555  for (size_t j=0; j<tot_size; j++) {
1556  if (i>i2 || i<i1 || j>i2 || j<i1) {
1557  }
1558  else
1559  cov_lim[i-i1][j-i1] = cov[i][j];
1560  }
1561  }
1562 
1563  invert_matrix(cov_lim, cov_lim_inv, prec, Nres);
1564 
1565  for (size_t i=0; i<tot_size; i++) {
1566  for (size_t j=0; j<tot_size; j++) {
1567  if (i>i2 || i<i1 || j>i2 || j<i1)
1568  cov_inv[i][j] = 0.;
1569  else
1570  cov_inv[i][j] = cov_lim_inv[i-i1][j-i1];
1571  }
1572  }
1573 
1574 }
1575 
1576 
1577 // ============================================================================
1578 
1579 
1580 void cbl::convolution (const std::vector<double> f1, const std::vector<double> f2, std::vector<double> &res, const double deltaX)
1581 {
1582  size_t nn = f1.size();
1583  if (nn!=f2.size()) ErrorCBL("the two functions have to have equal sizes!", "convolution", "Func.cpp");
1584 
1585  double *ff1 = new double[nn];
1586  double *ff2 = new double[nn];
1587  double *rr = new double[nn];
1588 
1589  for (size_t i=0; i<nn; i++) {
1590  ff1[i] = f1[i];
1591  ff2[i] = f2[i];
1592  rr[i] = 0.;
1593  }
1594 
1595  gsl_fft_real_wavetable *real;
1596  gsl_fft_halfcomplex_wavetable *hc;
1597  gsl_fft_real_workspace *work;
1598 
1599  work = gsl_fft_real_workspace_alloc(nn);
1600  real = gsl_fft_real_wavetable_alloc(nn);
1601 
1602  gsl_fft_real_transform(ff1, 1., nn, real, work);
1603  gsl_fft_real_transform(ff2, 1., nn, real, work);
1604 
1605  gsl_fft_real_wavetable_free(real);
1606 
1607 
1608  // Combining Fourier series coefficients (complex number product)
1609 
1610  rr[0] = ff1[0]*ff2[0];
1611 
1612  if (nn%2!=0) {
1613  for (unsigned int i=1; i<nn; i+=2) {
1614  rr[i] = ff1[i]*ff2[i]-ff1[i+1]*ff2[i+1];
1615  rr[i+1] = ff1[i]*ff2[i+1]+ff2[i]*ff1[i+1];
1616  }
1617  }
1618  else {
1619  for (unsigned int i=1; i<nn-1; i+=2) {
1620  rr[i] = ff1[i]*ff2[i]-ff1[i+1]*ff2[i+1];
1621  rr[i+1] = ff1[i]*ff2[i+1]+ff2[i]*ff1[i+1];
1622  }
1623  rr[nn-1] = ff1[nn-1]*ff2[nn-1];
1624  }
1625 
1626 
1627  // Back to real space
1628 
1629  hc = gsl_fft_halfcomplex_wavetable_alloc(nn);
1630 
1631  gsl_fft_halfcomplex_inverse(rr, 1., nn, hc, work);
1632 
1633  gsl_fft_halfcomplex_wavetable_free(hc);
1634 
1635 
1636  // Re-order result
1637 
1638  res.resize(nn, 0.);
1639 
1640  for (unsigned int i=0; i<=nn/2; i++)
1641  res[i] = deltaX*rr[i+nn/2];
1642 
1643  for (unsigned int i=nn/2+1; i<nn; i++)
1644  res[i] = deltaX*rr[i-nn/2-1];
1645 
1646  if (nn%2==0) res[nn/2] = res[nn/2-1];
1647 
1648 }
1649 
1650 
1651 // ============================================================================
1652 
1653 
1654 void cbl::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, const std::string file_out, const double fact, const double V1, const double V2, const std::string bin_type, const bool conv, const double sigma)
1655 {
1656  if (xx.size()>0 || fx.size()>0 || FF.size()<=0 || nbin<=0)
1657  ErrorCBL("the following conditions have to be satisfied: xx.size()<=0, fx.size()<=0, FF.size()>0 and nbin>0. The values recived are instead: xx.size() = "+cbl::conv(xx.size(), par::fINT)+", fx.size() = "+cbl::conv(fx.size(), par::fINT)+", FF.size() = "+cbl::conv(FF.size(), par::fINT)+"and nbin = "+cbl::conv(nbin, par::fINT)+"!", "distribution", "Func.cpp");
1658 
1659  double minFF = (V1>cbl::par::defaultDouble) ? V1 : Min(FF)*0.9999;
1660  double maxFF = (V2>cbl::par::defaultDouble) ? V2 : Max(FF)*1.0001;
1661 
1662 
1663  // using GSL to create the histogram
1664 
1665  gsl_histogram *histo = gsl_histogram_alloc(nbin);
1666 
1667  if (linear) gsl_histogram_set_ranges_uniform(histo, minFF, maxFF);
1668 
1669  else {
1670  vector<double> vv = logarithmic_bin_vector(nbin+1, minFF, maxFF);
1671  double *vvv = new double[nbin+1]; for (int i=0; i<nbin+1; i++) vvv[i] = vv[i];
1672  gsl_histogram_set_ranges(histo, vvv, nbin+1);
1673  }
1674 
1675  vector<double> Weight = WW;
1676  if (Weight.size()==0) Weight.resize(FF.size(), 1.);
1677  checkDim(Weight, FF.size(), "WW");
1678 
1679  for (size_t i=0; i<FF.size(); i++)
1680  gsl_histogram_accumulate(histo, FF[i], Weight[i]);
1681 
1682  double x1, x2;
1683 
1684  for (int i=0; i<nbin; i++) {
1685 
1686  gsl_histogram_get_range(histo, i, &x1, &x2);
1687  double val = gsl_histogram_get(histo, i);
1688 
1689  if (linear) xx.push_back(0.5*(x1+x2));
1690  else xx.push_back(pow(10., 0.5*(log10(x1)+log10(x2))));
1691 
1692  if (bin_type == "Linear") {
1693  fx.push_back(val/((x2-x1)*fact));
1694  err.push_back(sqrt(val)/((x2-x1)*fact));
1695  }
1696 
1697  else if (bin_type == "Log") {
1698  fx.push_back(val/((log(x2)-log(x1))*fact));
1699  err.push_back(sqrt(val)/((log(x2)-log(x1))*fact));
1700  }
1701 
1702  else if (bin_type == "Log10") {
1703  fx.push_back(val/((log10(x2)-log10(x1))*fact));
1704  err.push_back(sqrt(val)/((log10(x2)-log10(x1))*fact));
1705  }
1706 
1707  else
1708  ErrorCBL("the value of string 'bin_type' is not permitted, possible selections are 'Linear', 'Log', 'Log10'!", "distribution", "Func.cpp");
1709 
1710 
1711 
1712  }
1713 
1714 
1715  // Gaussian convolution
1716 
1717  if (conv) {
1718  coutCBL << "The distribution is smoothed with a Gaussian filter" << endl;
1719  double *func;
1720  fftw_complex *func_tr;
1721 
1722  if (!linear) ErrorCBL("", "distribution", "Func.cpp", ExitCode::_workInProgress_);
1723  int nbinN = 2*nbin;
1724  int i1 = nbin*0.5, i2 = 1.5*nbin;
1725 
1726  int nbinK = 0.5*nbinN+1;
1727 
1728  func = fftw_alloc_real(nbinN);
1729  func_tr = fftw_alloc_complex(nbinK);
1730 
1731  for (int i=0; i<nbinN; i++)
1732  func[i] = 0;
1733 
1734  for (int i=i1; i<i2; i++)
1735  func[i] = fx[i-i1];
1736 
1737  for (int i=0; i<nbinK; i++) {
1738  func_tr[i][0] = 0;
1739  func_tr[i][1] = 0;
1740  }
1741 
1742  fftw_plan real2complex;
1743  real2complex = fftw_plan_dft_r2c_1d(nbinN, func, func_tr, FFTW_ESTIMATE);
1744  fftw_execute(real2complex);
1745  fftw_destroy_plan(real2complex);
1746 
1747  double delta = (maxFF-minFF)/nbin;
1748  double SS = pow(sigma,2);
1749 
1750  double fact = 2*par::pi/(nbinN*delta);
1751  for (int i=0; i<nbinK; i++) {
1752  double kk = i*fact;
1753  func_tr[i][0] = func_tr[i][0]*exp(-0.5*kk*kk*SS);
1754  func_tr[i][1] = func_tr[i][1]*exp(-0.5*kk*kk*SS);
1755  }
1756 
1757  fftw_plan complex2real;
1758  complex2real = fftw_plan_dft_c2r_1d(nbinN, func_tr, func, FFTW_ESTIMATE);
1759  fftw_execute(complex2real);
1760  fftw_destroy_plan(complex2real);
1761 
1762  for (int i=i1; i<i2; i++)
1763  fx[i-i1] = func[i]/nbinN;
1764  }
1765 
1766 
1767  if (file_out!=par::defaultString && file_out!="") {
1768 
1769  ofstream fout(file_out.c_str()); checkIO(fout, file_out);
1770 
1771  for (size_t i=0; i<xx.size(); i++)
1772  fout << xx[i] << " " << fx[i] << " " << err[i] << endl;
1773 
1774  fout.clear(); fout.close(); coutCBL << "I wrote the file: " << file_out << endl;
1775  }
1776 
1777  gsl_histogram_free(histo);
1778  fftw_cleanup();
1779 
1780 }
1781 
1782 
1783 // ============================================================================
1784 
1785 
1786 double cbl::legendre_polynomial (const double mu, const int l)
1787 {
1788  return gsl_sf_legendre_Pl(l,mu);
1789 }
1790 
1791 
1792 // ============================================================================
1793 
1794 
1795 double cbl::legendre_polynomial_integral (double mu, void *params)
1796 {
1797  // cbl::glob::STR_jl_distance_average *par = (cbl::glob::STR_jl_distance_average *)(params);
1798  int *l = (int *)(params);
1799  return legendre_polynomial(mu, *l);
1800 }
1801 
1802 
1803 // ============================================================================
1804 
1805 
1806 double cbl::Legendre_polynomial_mu_average (const int ll, const double mu, const double delta_mu)
1807 {
1808  auto integrand = [&] (const double mu) { return cbl::legendre_polynomial(mu, ll); };
1809  return wrapper::gsl::GSL_integrate_qag(integrand, mu, mu+delta_mu, 1.e-3, 1.e-6, 1000, 6);
1810 }
1811 
1812 
1813 // ============================================================================
1814 
1815 
1816 double cbl::Legendre_polynomial_mu_average (const double mu_min, const double mu_max, const int ll)
1817 {
1818  double integral = (ll>0) ? (legendre_polynomial(mu_max, ll+1)-legendre_polynomial(mu_max, ll-1)+
1819  legendre_polynomial(mu_min, ll-1)-legendre_polynomial(mu_min, ll+1))/(mu_max-mu_min) : 1.;
1820  return integral/(2*ll+1);
1821 }
1822 
1823 
1824 // ============================================================================
1825 
1826 
1827 double cbl::Legendre_polynomial_theta_average (const double theta_min, const double theta_max, const int ll)
1828 {
1829  return Legendre_polynomial_mu_average(cos(theta_max), cos(theta_min), ll);
1830 }
1831 
1832 
1833 // ============================================================================
1834 
1835 
1836 double cbl::Legendre_polynomial_triangles_average (const double r12_min, const double r12_max, const double r13_min, const double r13_max, const double r23_min, const double r23_max, const int ll, const double rel_err, const double abs_err, const int nevals)
1837 {
1838  double norm = 2*(pow(r12_max, 3)-pow(r12_min,3))*(pow(r13_max, 3)-pow(r13_min, 3))/9;
1839 
1840  auto r12_integrand = [&] (const double r12) {
1841 
1842  auto r13_integrand = [&] (const double r13) {
1843  double mu_min = (r12*r12+r13*r13-r23_max*r23_max)/(2*r12*r13);
1844  double mu_max = (r12*r12+r13*r13-r23_min*r23_min)/(2*r12*r13);
1845 
1846  if ((mu_min<=1) & (mu_max>=-1)) {
1847  double low = max(mu_min, -1.);
1848  double up = min(1., mu_max);
1849  return r13*r13*Legendre_polynomial_mu_average (low, up, ll)*(up-low);
1850  }
1851  return 0.;
1852 
1853  };
1854 
1855  return r12*r12*cbl::wrapper::gsl::GSL_integrate_cquad(r13_integrand, r13_min, r13_max, rel_err, abs_err, nevals);
1856  };
1857 
1858  return cbl::wrapper::gsl::GSL_integrate_cquad(r12_integrand, r12_min, r12_max, rel_err, abs_err, nevals)/norm; //((r12_max-r12_min)*(r13_max-r13_min));
1859 }
1860 
1861 
1862 
1863 // ============================================================================
1864 
1865 
1866 vector<vector<double>> cbl::Legendre_polynomial_triangles_average (const double rMin, const double rMax, const double deltaR, const int lMax, const double rel_err, const double abs_err, const int nevals)
1867 {
1868  (void)abs_err;
1869  const int nBins = int((rMax-rMin)/deltaR);
1870 
1871  vector<double> r12, r13, r23;
1872 
1873 
1874  for (int i=0; i<nBins; i++)
1875  for (int j=i; j<nBins; j++) {
1876 
1877  double r12_min = rMin+i*deltaR;
1878  double r12_max = r12_min+deltaR;
1879 
1880  double r13_min = rMin+j*deltaR;
1881  double r13_max = r13_min+deltaR;
1882 
1883  double r23_min = max(0., r13_min-r12_max);
1884  double r23_max = r13_max+r12_max;
1885 
1886  int nBins_R23 = int(( r23_max-r23_min)/deltaR);
1887 
1888  for ( int k=0; k<nBins_R23; k++) {
1889  r12.push_back(0.5*(r12_min+r12_max));
1890  r13.push_back(0.5*(r13_min+r13_max));
1891  r23.push_back(r23_min+(k+0.5)*deltaR);
1892  }
1893 
1894  }
1895  int nTriangles = static_cast<int>(r12.size());
1896  int nOrders = lMax+1;
1897 
1898  vector<vector<double>> leg_pols(nTriangles, vector<double>(nOrders+3, 0.));
1899 
1900 #pragma omp parallel num_threads(omp_get_max_threads())
1901  {
1902 
1903  LegendrePolynomials legendre(lMax);
1904 
1905 #pragma omp for schedule(dynamic)
1906  for (int i=0; i<nTriangles; i++) {
1907 
1908  double r12_min = r12[i]-0.5*deltaR;
1909  double r12_max = r12[i]+0.5*deltaR;
1910 
1911  double r13_min = r13[i]-0.5*deltaR;
1912  double r13_max = r13[i]+0.5*deltaR;
1913 
1914  double r23_min = r23[i]-0.5*deltaR;
1915  double r23_max = r23[i]+0.5*deltaR;
1916 
1917  leg_pols[i][0] = r12[i];
1918  leg_pols[i][1] = r13[i];
1919  leg_pols[i][2] = r23[i];
1920 
1921  vector<double> integral = legendre.triangle_integral(r12_min, r12_max, r13_min, r13_max, r23_min, r23_max, rel_err, nevals);
1922 
1923  for (int ell=0; ell<nOrders; ell++)
1924  leg_pols[i][ell+3] = integral[ell];
1925 
1926  //for (int ell=0; ell<nOrders; ell++)
1927  // leg_pols[i][ell+3] = cbl::Legendre_polynomial_triangles_average(r12_min, r12_max, r13_min, r13_max, r23_min, r23_max, ell, rel_err, abs_err, nevals);
1928 
1929  }
1930  }
1931 
1932  return leg_pols;
1933 }
1934 
1935 
1936 // ============================================================================
1937 
1938 
1939 complex<double> cbl::spherical_harmonics (cbl::CoordinateType coordinate_type, const int l, const int m, const double coord1, const double coord2, const double coord3)
1940 {
1941 
1942  if(coordinate_type==cbl::CoordinateType::_comoving_){
1943  double xx=coord1, yy=coord2, zz=coord3;
1944  const double sintheta = sin(acos(zz));
1945  complex<double> exp_iphi(xx/(sintheta), yy/(sintheta));
1946 
1947  if(m<0) { //Y_l_-m=(-1)^m*conj(Y_lm)
1948  complex<double> pow_exp = pow(exp_iphi, -m);
1949  double fact = gsl_sf_legendre_sphPlm (l, -m, zz);
1950  return conj(fact*pow_exp);
1951  }
1952  else {
1953  complex<double> pow_exp = pow(exp_iphi, m);
1954  double fact = pow(-1.,m)*gsl_sf_legendre_sphPlm(l, m, zz);
1955  return fact*pow_exp;
1956  }
1957  }
1958 
1959  else {
1960  const double pi_2=cbl::par::pi*0.5;
1961  double colatitude=pi_2-coord1;
1962  double RA= coord2;
1963  return pow(-1.,m)*boost::math::spherical_harmonic(l, m, colatitude, RA);
1964 
1965  }
1966 
1967 }
1968 
1969 
1970 // ============================================================================
1971 
1972 
1973 std::vector<std::vector<complex<double>>> cbl::spherical_harmonics (const int lmax, const double xx, const double yy, const double zz)
1974 {
1975  const int nl = lmax+1;
1976 
1977  const double sintheta = sin(acos(zz));
1978  complex<double> exp_iphi(xx/(sintheta), yy/(sintheta));
1979 
1980  vector<complex<double>> pow_exp(nl+1);
1981  vector<double> norm(nl+1);
1982 
1983  for (int mm=0; mm<nl+1; mm++){
1984  norm[mm] = pow(-1., mm);
1985  pow_exp[mm] = pow(exp_iphi, mm);
1986  }
1987 
1988  vector<vector<complex<double>>> coeff(nl);
1989 
1990  for(int ll=0; ll< nl; ll++){
1991 
1992  vector<complex<double>> ylm(ll+1);
1993 
1994  for (int mm=0; mm<ll+1; mm++){
1995  double fact = norm[mm]*gsl_sf_legendre_sphPlm (ll, mm, zz);
1996  ylm[mm] = fact*pow_exp[mm];
1997  }
1998 
1999  coeff[ll] = ylm;
2000  }
2001 
2002  return coeff;
2003 }
2004 
2005 
2006 // ============================================================================
2007 
2008 
2009 std::vector<std::complex<double>> cbl::spherical_harmonics_array (const int lmax, const double xx, const double yy, const double zz)
2010 {
2011  const int n_sph = gsl_sf_legendre_array_n(lmax);
2012 
2013  vector<double> Plm(n_sph, 0);
2014  vector<complex<double>> sph(n_sph);
2015 
2016  double phi = atan2(yy, xx);
2017 
2018  vector<complex<double>> pow_exp(lmax+2, complex<double>(cos(phi), sin(phi)));
2019 
2020  for (int mm=0; mm<lmax+2; mm++)
2021  pow_exp[mm] = pow(pow_exp[mm], mm);
2022 
2023  gsl_sf_legendre_array_e(GSL_SF_LEGENDRE_SPHARM, lmax, zz, 1., Plm.data());
2024 
2025 
2026  int n=0;
2027  for(int l=0; l<lmax+1; l++)
2028  for (int m=0; m<l+1; m++){
2029  sph[n] = pow_exp[m]*Plm[n];
2030  n++;
2031  }
2032 
2033  return sph;
2034 }
2035 
2036 // ============================================================================
2037 
2038 
2039 double cbl::j0 (const double xx)
2040 {
2041  return gsl_sf_bessel_jl(0, xx);
2042 }
2043 
2044 
2045 // ============================================================================
2046 
2047 
2048 double cbl::j2 (const double xx)
2049 {
2050  return gsl_sf_bessel_jl(2, xx);
2051 }
2052 
2053 
2054 // ============================================================================
2055 
2056 
2057 double cbl::j4 (const double xx)
2058 {
2059  return gsl_sf_bessel_jl(4, xx);
2060 }
2061 
2062 
2063 // ============================================================================
2064 
2065 
2066 double cbl::jl (const double xx, const int order)
2067 {
2068  return gsl_sf_bessel_jl(order, xx);
2069 }
2070 
2071 
2072 // ============================================================================
2073 
2074 
2075 double cbl::j0_distance_average (const double kk, const double r_down, const double r_up)
2076 {
2077  double volume = (pow(r_up,3)-pow(r_down,3))/3;
2078  double up = (sin(kk*r_up)-kk*r_up*cos(kk*r_up))*pow(kk,-3);
2079  double down = (sin(kk*r_down)-kk*r_down*cos(kk*r_down))*pow(kk,-3);
2080  return (up-down)/volume;
2081 }
2082 
2083 
2084 // ============================================================================
2085 
2086 
2087 double cbl::j2_distance_average (const double kk, const double r_down, const double r_up)
2088 {
2089  double volume = (pow(r_up,3)-pow(r_down,3))/3;
2090  double up = (3*gsl_sf_Si(kk*r_up)-4*sin(kk*r_up)+kk*r_up*cos(kk*r_up))*pow(kk,-3);
2091  double down = (3*gsl_sf_Si(kk*r_down)-4*sin(kk*r_down)+kk*r_down*cos(kk*r_down))*pow(kk,-3);
2092  return (up-down)/volume;
2093 }
2094 
2095 
2096 // ============================================================================
2097 
2098 
2099 double cbl::jl_spherical_integrand (double rr, void *params)
2100 {
2101  cbl::glob::STR_jl_distance_average *par = (cbl::glob::STR_jl_distance_average *)(params);
2102  return rr*rr*gsl_sf_bessel_jl(par->order, par->k*rr);
2103 }
2104 
2105 
2106 // ============================================================================
2107 
2108 
2109 double cbl::jl_distance_average (const double kk, const int order, const double r_down, const double r_up)
2110 {
2111  double volume = (pow(r_up,3)-pow(r_down,3))/3;
2112 
2113  auto integrand = [&] (const double rr) {
2114  return rr * rr * gsl_sf_bessel_jl(order, kk*rr);
2115  };
2116 
2117  double Int = cbl::wrapper::gsl::GSL_integrate_qag(integrand, r_down, r_up);
2118 
2119  /*
2120  cbl::glob::STR_jl_distance_average str;
2121  str.order = order;
2122  str.k = kk;
2123 
2124  gsl_function Func;
2125 
2126  Func.function=&cbl::jl_spherical_integrand;
2127  Func.params=&str;
2128 
2129  double prec=1.e-2;
2130  int limit_size = 1000;
2131 
2132  double Int = cbl::wrapper::gsl::GSL_integrate_qag(Func, r_down, r_up, prec, limit_size, 6);
2133  */
2134 
2135  return Int/volume;
2136 }
2137 
2138 
2139 // ============================================================================
2140 
2141 
2142 std::vector<double> cbl::generate_correlated_data (const std::vector<double> mean, const std::vector<std::vector<double>> covariance, const int seed)
2143 {
2144  random::NormalRandomNumbers ran(0., 1., seed);
2145 
2146  size_t sample_size = mean.size();
2147  vector<double> sample;
2148  vector<double> std;
2149 
2150  gsl_matrix *correlation = gsl_matrix_alloc(sample_size, sample_size);
2151 
2152  for (size_t i=0; i<sample_size; i++) {
2153  std.push_back(sqrt(covariance[i][i]));
2154  sample.push_back(ran());
2155  for (size_t j=0; j<sample_size; j++) {
2156  double corr = covariance[i][j]/sqrt(covariance[i][i]*covariance[j][j]);
2157  if (corr!=corr)
2158  ErrorCBL("negative value on the covariance diagonal!", "generate_correlated_data", "Func.cpp");
2159  gsl_matrix_set(correlation,i,j, corr);
2160  }
2161  }
2162 
2163 
2164  // correlation matrix eigensystem
2165 
2166  gsl_vector *eigenvalues = gsl_vector_alloc(sample_size);
2167  gsl_matrix *VV = gsl_matrix_alloc(sample_size, sample_size);
2168  gsl_matrix_set_zero(VV);
2169 
2170  gsl_matrix *eigenvectors = gsl_matrix_alloc(sample_size, sample_size);
2171 
2172  gsl_eigen_symmv_workspace *ww = gsl_eigen_symmv_alloc(sample_size);
2173  gsl_eigen_symmv (correlation, eigenvalues, eigenvectors, ww);
2174  gsl_eigen_symmv_free(ww);
2175 
2176  for (size_t j = 0; j<sample_size; j++) {
2177  for (size_t i = 0; i<sample_size; i++) {
2178  if (gsl_vector_get(eigenvalues, j)<0)
2179  ErrorCBL("covariance matrix must be positive (semi-)definite but has at least one negative eigenvalue!", "generate_correlated_data", "Func.cpp");
2180  double v1 = gsl_matrix_get(eigenvectors, i, j);
2181  double v2 = sqrt(gsl_vector_get(eigenvalues, j));
2182  gsl_matrix_set(VV, i, j, v1*v2);
2183  }
2184  }
2185 
2186  vector<double> cov_sample;
2187  for (size_t i=0; i<sample_size; i++) {
2188  gsl_vector *row = gsl_vector_alloc(sample_size);
2189  gsl_matrix_get_row(row, VV, i);
2190  cov_sample.push_back(0);
2191  for (size_t j=0; j<sample_size; j++)
2192  cov_sample[i] += gsl_vector_get(row, j)*sample[j];
2193  cov_sample[i] = std[i]*cov_sample[i]+mean[i];
2194  }
2195 
2196  return cov_sample;
2197 }
2198 
2199 
2200 // ============================================================================
2201 
2202 
2203 double cbl::trapezoid_integration (const std::vector<double> xx, const std::vector<double> yy)
2204 {
2205  double Int = 0.;
2206 
2207  for (size_t i=0; i<xx.size()-1; i++)
2208  Int += 0.5*(yy[i+1]+yy[i])*(xx[i+1]-xx[i]);
2209 
2210  return Int;
2211 }
2212 
2213 
2214 // ============================================================================
2215 
2216 
2217 double cbl::binomial_coefficient(const int n, const int m)
2218 {
2219  return double(gsl_sf_fact(n))/double(gsl_sf_fact(m)*gsl_sf_fact(n-m));
2220 }
2221 
2222 
2223 // ============================================================================
2224 
2225 
2226 template <typename T> //template used in wigner_3j
2227 double cbl::sgn(T val)
2228 {
2229  int sgn = (T(0) < val) - (val < T(0));
2230  if (sgn == 0)
2231  return 1.0;
2232  else
2233  return (double)sgn;
2234 }
2235 
2236 
2237 // ============================================================================
2238 
2239 
2240 double cbl::wigner3j_auxA(double l1, double l2, double l3, double m1, double /*m2*/, double /*m3*/)
2241 {
2242  double T1 = l1*l1-pow(l2-l3,2.0);
2243  double T2 = pow(l2+l3+1.0,2.0)-l1*l1;
2244  double T3 = l1*l1-m1*m1;
2245 
2246  return sqrt(T1*T2*T3);
2247 }
2248 
2249 
2250 // ============================================================================
2251 
2252 
2253 double cbl::wigner3j_auxB(double l1, double l2, double l3, double m1, double m2, double m3)
2254 {
2255  double T1 = -(2.0*l1+1.0);
2256  double T2 = l2*(l2+1.0)*m1;
2257  double T3 = l3*(l3+1.0)*m1;
2258  double T4 = l1*(l1+1.0)*(m3-m2);
2259 
2260  return T1*(T2-T3-T4);
2261 }
2262 
2263 
2264 // ============================================================================
2265 
2266 
2267 std::vector<double> cbl::wigner3j(double l2, double l3, double m1, double m2, double m3)
2268 {
2269 
2270  // We compute the numeric limits of double precision.
2271  double huge = sqrt(std::numeric_limits<double>::max()/20.0);
2272  double srhuge = sqrt(huge);
2273  double tiny = std::numeric_limits<double>::min();
2274  double srtiny = sqrt(tiny);
2275  double eps = std::numeric_limits<double>::epsilon();
2276 
2277  // We enforce the selection rules.
2278  bool select(true);
2279  select = (
2280  std::fabs(m1+m2+m3)<eps
2281  && std::fabs(m2) <= l2+eps
2282  && std::fabs(m3) <= l3+eps
2283  );
2284 
2285  if (!select) return std::vector<double>(1,0.0);
2286 
2287  // We compute the limits of l1.
2288  double l1min = std::max(std::fabs(l2-l3),std::fabs(m1));
2289  double l1max = l2+l3;
2290 
2291  // We compute the size of the resulting array.
2292  int size = (int)std::floor(l1max-l1min+1.0+eps);
2293  std::vector<double> thrcof(size,0.0);
2294 
2295  // If l1min=l1max, we have an analytical formula.
2296  if (size==1)
2297  {
2298  thrcof[0] = pow(-1.0,std::floor(std::fabs(l2+m2-l3+m3)))/sqrt(l1min+l2+l3+1.0);
2299  }
2300 
2301  // Another special case where the recursion relation fails.
2302  else
2303  {
2304  // We start with an arbitrary value.
2305  thrcof[0] = srtiny;
2306 
2307  // From now on, we check the variation of |alpha(l1)|.
2308  double alphaNew, l1(l1min);
2309  if (l1min==0.0)
2310  alphaNew = -(m3-m2+2.0*wigner3j_auxB(l1,l2,l3,m1,m2,m3))/wigner3j_auxA(1.0,l2,l3,m1,m2,m3);
2311  else
2312  alphaNew = -wigner3j_auxB(l1min,l2,l3,m1,m2,m3)
2313  /(l1min*wigner3j_auxA(l1min+1.0,l2,l3,m1,m2,m3));
2314 
2315  // We compute the two-term recursion.
2316  thrcof[1] = alphaNew*thrcof[0];
2317 
2318  // If size > 2, we start the forward recursion.
2319  if (size>2)
2320  {
2321  // We start with an arbitrary value.
2322  thrcof[0] = srtiny;
2323 
2324  // From now on, we check the variation of |alpha(l1)|.
2325  double alphaOld, alphaNew, beta, l1(l1min);
2326  if (l1min==0.0)
2327  alphaNew = -(m3-m2+2.0*wigner3j_auxB(l1,l2,l3,m1,m2,m3))/wigner3j_auxA(1.0,l2,l3,m1,m2,m3);
2328  else
2329  alphaNew = -wigner3j_auxB(l1min,l2,l3,m1,m2,m3)
2330  /(l1min*wigner3j_auxA(l1min+1.0,l2,l3,m1,m2,m3));
2331 
2332  // We compute the two-term recursion.
2333  thrcof[1] = alphaNew*thrcof[0];
2334 
2335  // We compute the rest of the recursion.
2336  int i = 1;
2337  bool alphaVar = false;
2338  do
2339  {
2340  // Bookkeeping:
2341  i++; // Next term in recursion
2342  alphaOld = alphaNew; // Monitoring of |alpha(l1)|.
2343  l1 += 1.0; // l1 = l1+1
2344 
2345  // New coefficients in recursion.
2346  alphaNew = -wigner3j_auxB(l1,l2,l3,m1,m2,m3)
2347  /(l1*wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3));
2348 
2349  beta = -(l1+1.0)*wigner3j_auxA(l1,l2,l3,m1,m2,m3)
2350  /(l1*wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3));
2351 
2352  // Application of the recursion.
2353  thrcof[i] = alphaNew*thrcof[i-1]+beta*thrcof[i-2];
2354 
2355  // We check if we are overflowing.
2356  if (std::fabs(thrcof[i])>srhuge)
2357  {
2358  std::cout << "We renormalized the forward recursion." << std::endl;
2359  for (std::vector<double>::iterator it = thrcof.begin(); it != thrcof.begin()+i; ++it)
2360  {
2361  //if (std::fabs(*it) < srtiny) *it = 0;
2362  //else
2363  *it /= srhuge;
2364  }
2365  }
2366 
2367  // This piece of code checks whether we have reached
2368  // the classical region. If we have, the second if
2369  // sets alphaVar to true and we break this loop at the
2370  // next iteration because we need thrcof(l1mid+1) to
2371  // compute the scalar lambda.
2372  if (alphaVar) break;
2373 
2374  if (std::fabs(alphaNew)-std::fabs(alphaOld)>0.0)
2375  alphaVar=true;
2376 
2377  } while (i<(size-1)); // Loop stops when we have computed all values.
2378 
2379  // If this is the case, we have stumbled upon a classical region.
2380  // We start the backwards recursion.
2381  if (i!=size-1)
2382  {
2383  // We keep the two terms around l1mid to compute the factor later.
2384  double l1midm1(thrcof[i-2]),l1mid(thrcof[i-1]),l1midp1(thrcof[i]);
2385 
2386  // We compute the backward recursion by providing an arbitrary
2387  // startint value.
2388  thrcof[size-1] = srtiny;
2389 
2390  // We compute the two-term recursion.
2391  l1 = l1max;
2392  alphaNew = -wigner3j_auxB(l1,l2,l3,m1,m2,m3)
2393  /((l1+1.0)*wigner3j_auxA(l1,l2,l3,m1,m2,m3));
2394  thrcof[size-2] = alphaNew*thrcof[size-1];
2395 
2396  // We compute the rest of the backward recursion.
2397  int j = size-2;
2398  do
2399  {
2400  // Bookkeeping
2401  j--; // Previous term in recursion.
2402  l1 -= 1.0; // l1 = l1-1
2403 
2404  // New coefficients in recursion.
2405  alphaNew = -wigner3j_auxB(l1,l2,l3,m1,m2,m3)
2406  /((l1+1.0)*wigner3j_auxA(l1,l2,l3,m1,m2,m3));
2407  beta = -l1*wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3)
2408  /((l1+1.0)*wigner3j_auxA(l1,l2,l3,m1,m2,m3));
2409 
2410  // Application of the recursion.
2411  thrcof[j] = alphaNew*thrcof[j+1]+beta*thrcof[j+2];
2412 
2413  // We check if we are overflowing.
2414  if (std::fabs(thrcof[j]>srhuge))
2415  {
2416  std::cout << "We renormalized the backward recursion." << std::endl;
2417  for (std::vector<double>::iterator it = thrcof.begin()+j; it != thrcof.end(); ++it)
2418  {
2419  //if (std::fabs(*it) < srtiny) *it = 0;
2420  //else
2421  *it /= srhuge;
2422  }
2423  }
2424 
2425  } while (j>(i-2)); // Loop stops when we are at l1=l1mid-1.
2426 
2427  // We now compute the scaling factor for the forward recursion.
2428  double lambda = (l1midp1*thrcof[j+2]+l1mid*thrcof[j+1]+l1midm1*thrcof[j])
2429  /(l1midp1*l1midp1+l1mid*l1mid+l1midm1*l1midm1);
2430 
2431  // We scale the forward recursion.
2432  for (std::vector<double>::iterator it = thrcof.begin(); it != thrcof.begin()+j; ++it)
2433  {
2434  *it *= lambda;
2435  }
2436  }
2437  }
2438  }
2439 
2440  // We compute the overall factor.
2441  double sum = 0.0;
2442  for (int k=0;k<size;k++)
2443  {
2444  sum += (2.0*(l1min+k)+1.0)*thrcof[k]*thrcof[k];
2445  }
2446  //std::cout << sum << std::endl;
2447 
2448  //std::cout << "(-1)^(l2-l3-m1): " << pow(-1.0,l2-l3-m1) << " sgn:" << sgn(thrcof[size-1]) << std::endl;
2449  double c1 = pow(-1.0,l2-l3-m1)*sgn(thrcof[size-1]);
2450  //std::cout << "c1: " << c1 << std::endl;
2451  for (std::vector<double>::iterator it = thrcof.begin(); it != thrcof.end(); ++it)
2452  {
2453  //std::cout << *it << ", " << c1 << ", ";
2454  *it *= c1/sqrt(sum);
2455  //std::cout << *it << std::endl;
2456  }
2457  return thrcof;
2458 }
2459 
2460 
2461 // ============================================================================
2462 
2463 
2464 double cbl::wigner3j(double l1, double l2, double l3,double m1, double m2, double m3)
2465 {
2466  // We enforce the selection rules.
2467  bool select(true);
2468  select = (
2469  std::fabs(m1+m2+m3)<1.0e-10
2470  && std::floor(l1+l2+l3)==(l1+l2+l3)
2471  && l3 >= std::fabs(l1-l2)
2472  && l3 <= l1+l2
2473  && std::fabs(m1) <= l1
2474  && std::fabs(m2) <= l2
2475  && std::fabs(m3) <= l3
2476  );
2477 
2478  if (!select) return 0.0;
2479 
2480  // We compute l1min and the position of the array we will want.
2481  double l1min = std::max(std::fabs(l2-l3),std::fabs(m1));
2482 
2483  // We fetch the proper value in the array.
2484  int index = (int)(l1-l1min);
2485 
2486  return wigner3j(l2,l3,m1,m2,m3)[index];
2487 }
2488 
2489 
2490 // ============================================================================
2491 
2492 
2493 double cbl::wigner_3j(const int j1, const int j2, const int j3, const int m1, const int m2, const int m3)
2494 {
2495  return gsl_sf_coupling_3j(2*j1, 2*j2, 2*j3, 2*m1, 2*m2, 2*m3);
2496 }
2497 
2498 
2499 // ============================================================================
2500 
2501 
2502 double cbl::wigner_6j(const int j1, const int j2, const int j3, const int j4, const int j5, const int j6)
2503 {
2504  return gsl_sf_coupling_6j(2*j1, 2*j2, 2*j3, 2*j4, 2*j5, 2*j6);
2505 }
2506 
2507 
2508 // ============================================================================
2509 
2510 
2511 double cbl::clebsh_gordan(const int l1, const int l2, const int m1, const int m2, const int l3, const int m3)
2512 {
2513  return pow(-1, l1-l2+m3)*sqrt(2*l3+1)*gsl_sf_coupling_3j(2*l1, 2*l2, 2*l3, 2*m1, 2*m2, 2*m3);
2514 }
2515 
2516 
2517 // ============================================================================
2518 
2519 
2520 double cbl::coupling_3j(const int l, const int l_prime, const int l2)
2521 {
2522  return gsl_sf_coupling_3j(2*l, 2*l_prime, 2*l2, 0, 0, 0);
2523 }
2524 
2525 
2526 // ============================================================================
2527 
2528 
2529 double cbl::get_mu (const double r1, const double r2, const double r3)
2530 {
2531  return ( (r1*r1+r2*r2-r3*r3)/(2*r1*r2));
2532 }
2533 
2534 
2535 // ============================================================================
2536 
2537 
2538 double cbl::window_function (const double x, const double min, const double max)
2539 {
2540  if ((x>min) && (x<max))
2541  return 1.;
2542  else if ((x<min) or (x>max))
2543  return 0;
2544  else
2545  return 0.5;
2546 
2547  return 0.;
2548 }
2549 
2550 
2551 // ============================================================================
2552 
2553 
2554 double cbl::three_spherical_bessel_integral (const double r1, const double r2, const double r3, const int L1, const int L2, const int L3)
2555 {
2556  double fact = pow(-1, (L1+L2+L3)*0.5);
2557  double mu = get_mu(r1, r2, r3);
2558  double beta = window_function(mu);
2559 
2560  if ((fact!=fact) or (beta==0))
2561  return 0;
2562 
2563  double term1 = fact*beta*(2*L3+1)/(8*cbl::par::pi*r1*r2*r3)*pow(r1/r3, L3);
2564  double tt = 0;
2565 
2566  for (int L=0; L<L3+1; L++) {
2567 
2568  double term2 = 0;
2569  int min_ell = std::max(fabs(L1-(L3-L)), fabs(L2-L));
2570  int max_ell = std::min(L1+(L3-L), L2+L);
2571  for (int ell=min_ell; ell<max_ell+1; ell++){ //check
2572  term2 += clebsh_gordan(L1, L3-L, 0, 0, ell, 0)*clebsh_gordan(L2, L, 0, 0, ell, 0)*wigner_6j(L1, L2, L3, L, (L3-L), ell)*cbl::legendre_polynomial(mu, ell);
2573  }
2574  tt += sqrt(binomial_coefficient(2*L3, 2*L))*pow(r2/r1, L)*term2;
2575  }
2576 
2577 
2578  return term1*tt/clebsh_gordan(L1, L2, 0, 0, L3, 0);
2579 }
2580 
2581 
2582 // ============================================================================
2583 
2584 
2585 double cbl::average_three_spherical_bessel_integral (const double r1_min, const double r1_max, const double r2_min, const double r2_max, const double r3, const int L1, const int L2, const int L3)
2586 {
2587  // limits of the integral
2588  int ndim = 2;
2589  std::vector<std::vector<double>> integration_limits(ndim);
2590  integration_limits[0] = {pow(r1_min, 3), pow(r1_max, 3)};
2591  integration_limits[1] = {pow(r2_min, 3), pow(r2_max, 3)};
2592 
2593  double V1 = pow(r1_max, 3)-pow(r1_min, 3);
2594  double V2 = pow(r2_max, 3)-pow(r2_min, 3);
2595 
2596  // wrapper to CUBA libraries
2597 
2598  auto integrand = [&] (const vector<double> xx)
2599  {
2600  return three_spherical_bessel_integral(pow(xx[0], 1./3), pow(xx[1], 1./3), r3, L1, L2, L3);
2601  };
2602  cbl::wrapper::cuba::CUBAwrapper CW(integrand, ndim);
2603  CW.inputs().SPIN = make_shared<int>(-1);
2604  //CW.inputs().NVEC = 2;
2605 
2606  return CW.IntegrateCuhre(integration_limits)/(V1*V2);
2607 }
2608 
2609 
2610 // ============================================================================
2611 
2612 
2613 std::vector<std::vector<double>> cbl::generate_correlated_data (const int nExtractions, const std::vector<double> mean, const std::vector<std::vector<double>> covariance, const int seed)
2614 {
2615  random::NormalRandomNumbers ran(0., 1., seed);
2616 
2617  size_t sample_size = mean.size();
2618  vector<double> std;
2619 
2620  gsl_matrix *correlation = gsl_matrix_alloc(sample_size,sample_size);
2621 
2622  for (size_t i=0; i<sample_size; i++) {
2623  std.push_back(sqrt(covariance[i][i]));
2624  for (size_t j=0; j<sample_size; j++) {
2625  double corr = covariance[i][j]/sqrt(covariance[i][i]*covariance[j][j]);
2626  if (corr!=corr)
2627  ErrorCBL("negative value on the covariance diagonal!", "generate_correlated_data", "Func.cpp");
2628  gsl_matrix_set(correlation,i,j, corr);
2629  }
2630  }
2631 
2632  vector<vector<double>> sample;
2633  for (int j=0; j<nExtractions; j++) {
2634  vector<double> subS(sample_size, 0);
2635  for (size_t i=0; i<sample_size; i++)
2636  subS[i] = ran();
2637  sample.push_back(subS);
2638  }
2639 
2640 
2641  // correlation matrix eigensystem
2642 
2643  gsl_vector *eigenvalues = gsl_vector_alloc(sample_size);
2644  gsl_matrix *VV = gsl_matrix_alloc(sample_size,sample_size);
2645  gsl_matrix_set_zero(VV);
2646 
2647  gsl_matrix *eigenvectors = gsl_matrix_alloc(sample_size,sample_size);
2648 
2649  gsl_eigen_symmv_workspace *ww = gsl_eigen_symmv_alloc (sample_size);
2650  gsl_eigen_symmv (correlation, eigenvalues, eigenvectors, ww);
2651  gsl_eigen_symmv_free(ww);
2652 
2653  for (size_t j=0; j<sample_size; j++) {
2654  for (size_t i=0; i<sample_size; i++) {
2655  if (gsl_vector_get(eigenvalues, j)<0)
2656  ErrorCBL("covariance matrix must be positive (semi-)definite but has at least one negative eigenvalue!", "generate_correlated_data", "Func.cpp");
2657 
2658  double v1 = gsl_matrix_get(eigenvectors, i, j);
2659  double v2 = sqrt(gsl_vector_get(eigenvalues, j));
2660  gsl_matrix_set(VV, i, j, v1*v2);
2661  }
2662  }
2663 
2664  vector<vector<double>> cov_sample;
2665 
2666  for (int k=0; k<nExtractions; k++) {
2667  vector<double> cov_SSample(sample_size, 0);
2668  for (size_t i=0; i<sample_size; i++) {
2669 
2670  gsl_vector *row = gsl_vector_alloc(sample_size);
2671  gsl_matrix_get_row(row,VV,i);
2672 
2673  for (size_t j=0; j<sample_size; j++)
2674  cov_SSample[i] += gsl_vector_get(row, j)*sample[k][j];
2675 
2676  cov_SSample[i] = std[i]*cov_SSample[i]+mean[i];
2677  }
2678  cov_sample.push_back(cov_SSample);
2679  }
2680 
2681  return cov_sample;
2682 }
2683 
2684 
2685 
2686 // ============================================================================
2687 
2688 
2689 /* ======== Cosimo Fedeli ======== */
2690 
2692 
2693 void cbl::gauleg (const double x1, const double x2, double *x, double *w, const int n)
2694 {
2695  const double eps = 3.0e-11;
2696  int m = (n+1)/2;
2697  double xm = 0.5*(x2+x1);
2698  double xl = 0.5*(x2-x1);
2699  for (int i=1; i<=m; i++) {
2700  double z1, pp;
2701  double z = cos(par::pi*(i-0.25)/(n+0.5));
2702  do {
2703  double p1 = 1.0;
2704  double p2 = 0.0;
2705  for (int j=1; j<=n; j++) {
2706  double p3 = p2;
2707  p2 = p1;
2708  p1 = ((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
2709  }
2710  pp = n*(z*p1-p2)/(z*z-1.0);
2711  z1 = z;
2712  z = z1-p1/pp;
2713  }
2714  while (fabs(z-z1)>eps);
2715  x[i-1] = xm-xl*z;
2716  x[n-i] = xm+xl*z;
2717  w[i-1] = 2.0*xl/((1.0-z*z)*pp*pp);
2718  w[n-i] = w[i-1];
2719  }
2720 }
2721 
2722 
Useful generic functions.
#define coutCBL
CBL print message.
Definition: Kernel.h:734
Class to manage Legendre polymials computation.
The class ChainMesh.
Definition: ChainMesh.h:60
double interpolate(std::vector< double > xi, const int distNum)
N-dim interpolation of a set of N coordinates on a normalised grid (see normalize)
Definition: ChainMesh.cpp:387
ChainMesh()=default
default constructor
The class FuncGrid.
Definition: FuncGrid.h:55
double integrate_qag(const double a, const double b, const double rel_err=1.e-2, const double abs_err=1.e-6, const int limit_size=1000, const int rule=6)
compute the definite integral with GSL qag method
Definition: FuncGrid.cpp:187
The class LegendrePolynomials.
std::vector< double > triangle_integral(const double r12_min, const double r12_max, const double r13_min, const double r13_max, const double r23_min, const double r23_max, const double rel_err=1.e-4, const int nevals=10000)
evaluate the bin-averaged Legendre polynomials over a triangle. Triangle side can vary from a minimum...
The class NormalRandomNumbers.
The class UniformRandomNumbers.
The class CUBAwrapper.
Definition: CUBAwrapper.h:187
STR_CUBA_inputs & inputs()
return reference to integration parameters
Definition: CUBAwrapper.h:260
double IntegrateCuhre(std::vector< std::vector< double >> integration_limits, const bool parallelize=true)
integrate using the Cuhre routine
static const char fDP4[]
conversion symbol for: double -> std::string
Definition: Constants.h:139
static const char fDP3[]
conversion symbol for: double -> std::string
Definition: Constants.h:136
static const char fINT[]
conversion symbol for: int -> std::string
Definition: Constants.h:121
static const std::string defaultString
default std::string value
Definition: Constants.h:336
static const double defaultDouble
default double value
Definition: Constants.h:348
static const double pi
: the ratio of a circle's circumference to its diameter
Definition: Constants.h:199
static const double el
: the electrical charge of the electron [C]
Definition: Constants.h:230
Var
the catalogue variables
Definition: Catalogue.h:70
@ _workInProgress_
error due to work in progress
double bias(const double Mmin, const double sigmalgM, const double M0, const double M1, const double alpha, const std::shared_ptr< void > inputs)
the mean galaxy bias
Eigen::MatrixXd MatrixToEigen(const std::vector< std::vector< double >> mat)
convert a std::vector<std::vector<double>> to an Eigen::MatrixXd object
Eigen::MatrixXd VectorToEigen(const std::vector< double > vec)
convert a std::vector<double> to an Eigen::MatrixXd object
std::vector< std::vector< double > > EigenToMatrix(const Eigen::MatrixXd mat)
convert an Eigen::MatrixXd to a std::vector<std::vector<double>>
double GSL_integrate_cquad(gsl_function func, const double a, const double b, const double rel_err=1.e-3, const double abs_err=0, const int nevals=100)
integral, using the gsl cquad method
Definition: GSLwrapper.cpp:159
double GSL_integrate_qag(gsl_function Func, const double a, const double b, const double rel_err=1.e-3, const double abs_err=0, const int limit_size=1000, const int rule=6)
integral, computed using the GSL qag method
Definition: GSLwrapper.cpp:180
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
void sdss_atbound(double &angle, const double minval, const double maxval)
check if ra coordinate is inside the boundaries
Definition: Func.cpp:1347
double MC_Int(double func(const double), const double x1, const double x2, const int seed=3213)
simple Monte Carlo integration of f(x)
Definition: Func.cpp:295
T Min(const std::vector< T > vect)
minimum element of a std::vector
Definition: Kernel.h:1324
std::string conv(const T val, const char *fact)
convert a number to a std::string
Definition: Kernel.h:903
double legendre_polynomial_integral(double mu, void *params)
the order l Legendre polynomial integrand
Definition: Func.cpp:1795
double Euclidean_distance(const double x1, const double x2, const double y1, const double y2, const double z1, const double z2)
the Euclidean distance in 3D relative to the origin (0,0,0), i.e. the Euclidean norm
Definition: Func.cpp:250
void read_matrix(const std::string file_matrix, std::vector< double > &xx, std::vector< double > &yy, std::vector< std::vector< double >> &matrix, const std::vector< int > col={})
read a matrix from file
Definition: Func.cpp:612
double Legendre_polynomial_mu_average(const int ll, const double mu, const double delta_mu)
the average of the Legendre polynomial of the l-th order over the mu range
Definition: Func.cpp:1806
double multivariateGaussian(std::vector< double > xx, std::shared_ptr< void > pars)
the multivariate Gaussian function
Definition: Func.cpp:79
double Average(const std::vector< double > vect)
the average of a std::vector
Definition: Func.cpp:870
CoordinateType
the coordinate type
Definition: Kernel.h:624
@ _comoving_
comoving coordinates (x, y, z)
std::vector< T > different_elements(const std::vector< T > vect_input)
get the unique elements of a std::vector
Definition: Kernel.h:1349
T index_closest(T x, std::vector< T > vv)
given a number x, return the index of the closest element to x in vv
Definition: Kernel.h:965
double j2(const double xx)
the l=2 spherical Bessel function
Definition: Func.cpp:2048
double j2_distance_average(const double kk, const double r_down, const double r_up)
the distance average l=2 spherical Bessel function this function is used to obtain the analytic twop ...
Definition: Func.cpp:2087
double chainMeshInterpolate(std::vector< double > xx, std::shared_ptr< void > pars)
a multidimension interpolator
Definition: Func.cpp:68
std::vector< std::complex< double > > spherical_harmonics_array(const int lmax, const double xx, const double yy, const double zz)
the spherical harmonics up to
Definition: Func.cpp:2009
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
std::vector< T > linear_bin_vector(const size_t nn, const T min, const T max)
fill a std::vector with linearly spaced values
Definition: Kernel.h:1604
double haversine_distance(const double ra1, const double ra2, const double dec1, const double dec2)
the haversine angular separation
Definition: Func.cpp:286
double converted_angle(const double angle, const CoordinateUnits inputUnits=CoordinateUnits::_radians_, const CoordinateUnits outputUnits=CoordinateUnits::_degrees_)
conversion to angle units
Definition: Func.cpp:192
void checkDim(const std::vector< T > vect, const int val, const std::string vector, bool equal=true)
check if the dimension of a std::vector is equal/lower than an input value
Definition: Kernel.h:1532
void checkIO(const std::ifstream &fin, const std::string file="NULL")
check if an input file can be opened
Definition: Kernel.cpp:160
double Legendre_polynomial_triangles_average(const double r12_min, const double r12_max, const double r13_min, const double r13_max, const double r23_min, const double r23_max, const int ll, const double rel_err=1.e-5, const double abs_err=1.e-8, const int nevals=100)
the average of the Legendre polynomial of the l-th order over the
Definition: Func.cpp:1836
double jl_spherical_integrand(double rr, void *params)
the generic integrand to obtain the distance average spherical Bessel function of order l
Definition: Func.cpp:2099
double angular_distance(const double x1, const double x2, const double y1, const double y2, const double z1, const double z2)
the angular separation in 3D
Definition: Func.cpp:277
double interpolated_2D(const double _x1, const double _x2, const std::vector< double > x1, const std::vector< double > x2, const std::vector< std::vector< double >> yy, const std::string type)
2D interpolation
Definition: Func.cpp:502
double Legendre_polynomial_theta_average(const double theta_min, const double theta_max, const int ll)
the average of the Legendre polynomial of the l-th order over the range
Definition: Func.cpp:1827
double relative_error_beta(const double bias, const double Volume, const double density)
estimated relative error on
Definition: Func.cpp:1072
void cartesian_coord(const double ra, const double dec, const double dd, double &XX, double &YY, double &ZZ)
conversion from polar coordinates to Cartesian coordinates
Definition: Func.cpp:221
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
std::vector< double > colatitude(std::vector< double > latitude)
convert to colatitude
Definition: SubSample.cpp:484
void invert_matrix(const std::vector< std::vector< double >> mat, std::vector< std::vector< double >> &mat_inv, const double prec=1.e-10, const int Nres=-1)
function to invert a matrix
Definition: Func.cpp:673
double three_spherical_bessel_integral(const double r1, const double r2, const double r3, const int L1, const int L2, const int L3)
compute the integral of three spherical bessel function, from Mehrem (2011)
Definition: Func.cpp:2554
T Max(const std::vector< T > vect)
maximum element of a std::vector
Definition: Kernel.h:1336
double j0(const double xx)
the l=0 spherical Bessel function
Definition: Func.cpp:2039
double trapezoid_integration(const std::vector< double > xx, const std::vector< double > yy)
integral, computed with the trapezoid rule, using ordered data
Definition: Func.cpp:2203
std::vector< double > wigner3j(double l2, double l3, double m1, double m2, double m3)
Wigner symbol.
Definition: Func.cpp:2267
std::vector< double > linear_interpolation_3D(const std::vector< double > min, std::vector< double > max, std::vector< int > steps, std::vector< std::vector< std::vector< double >>> func, const std::vector< std::vector< double >> pos)
3D interpolation on a 3D regular grid
Definition: Func.cpp:546
std::vector< std::vector< T > > transpose(std::vector< std::vector< T >> matrix)
transpose a matrix
Definition: Kernel.h:1729
double coupling_3j(const int l, const int l_prime, const int l2)
compute the Wigner 3-j symbol
Definition: Func.cpp:2520
std::complex< double > spherical_harmonics(cbl::CoordinateType coordinate_type, const int l, const int m, const double coord1, const double coord2, const double coord3)
the order l, degree m spherical harmonics
Definition: Func.cpp:1939
double Filter(const double r, const double rc)
filter W(r/rc), used e.g. for filtering the correlation function
Definition: Func.cpp:94
double radians(const double angle, const CoordinateUnits inputUnits=CoordinateUnits::_degrees_)
conversion to radians
Definition: Func.cpp:126
double interpolated(const double _xx, const std::vector< double > xx, const std::vector< double > yy, const std::string type)
1D interpolation
Definition: Func.cpp:445
double clebsh_gordan(const int j1, const int j2, const int m1, const int m2, const int j3, const int m3)
get the Clebsh-Gordan coefficient in the notation
Definition: Func.cpp:2511
double average_three_spherical_bessel_integral(const double r1_min, const double r1_max, const double r2_min, const double r2_max, const double r3, const int L1, const int L2, const int L3)
compute the integral of three spherical bessel function, from Mehrem (2011), averaged on r1-r2 shells
Definition: Func.cpp:2585
double binomial_coefficient(const int n, const int m)
get the binomial coefficient
Definition: Func.cpp:2217
double Sigma(const std::vector< double > vect)
the standard deviation of a std::vector
Definition: Func.cpp:925
double j0_distance_average(const double kk, const double r_down, const double r_up)
the distance average l=0 spherical Bessel function this function is used to obtain the analytic twop ...
Definition: Func.cpp:2075
double wigner_3j(int j1, int j2, int j3, int m1, int m2, int m3)
Wigner symbol, use it for l<100.
Definition: Func.cpp:2493
std::vector< double > Quartile(const std::vector< double > Vect)
the first, second and third quartiles of a std::vector
Definition: Func.cpp:1002
void Moment(const std::vector< double > data, double &ave, double &adev, double &sdev, double &var, double &skew, double &curt)
compute the moments of a set of data
Definition: Func.cpp:1058
void sdss2eq(const std::vector< double > lambda, const std::vector< double > eta, std::vector< double > &ra, std::vector< double > &dec)
convert sdss coordinates to R.A., Dec.
Definition: Func.cpp:1397
double sgn(T val)
sgn the sign function
Definition: Func.cpp:2227
std::vector< double > generate_correlated_data(const std::vector< double > mean, const std::vector< std::vector< double >> covariance, const int idum=213123)
generate a covariant sample of n points using a covariance matrix
Definition: Func.cpp:2142
void sdss_stripe(const std::vector< double > eta, const std::vector< double > lambda, std::vector< int > &stripe, std::vector< int > &str_u)
compute the SDSS stripe given SDSS coordinates
Definition: Func.cpp:1420
double volume(const double boxSize, const int frac, const double Bord, const double mean_redshift, cosmology::Cosmology &real_cosm)
get the volume of a simulation box
Definition: Func.cpp:78
double closest_probability(double xx, std::shared_ptr< void > pp, std::vector< double > par)
probability of the closest element to x from a list with weights
Definition: Func.cpp:47
void covariance_matrix(const std::vector< std::vector< double >> mat, std::vector< std::vector< double >> &cov, const bool JK=false)
compute the covariance matrix from an input dataset
Definition: Func.cpp:761
void read_invert_covariance(const std::string filecov, std::vector< std::vector< double >> &cov, std::vector< std::vector< double >> &cov_inv, const size_t i1, const size_t i2, const double prec=1.e-10, const int Nres=-1)
read and invert the covariance matrix
Definition: Func.cpp:1522
double wigner3j_auxA(double l1, double l2, double l3, double m1, double m2, double m3)
Wigner auxiliar function A.
Definition: Func.cpp:2240
double degrees(const double angle, const CoordinateUnits inputUnits=CoordinateUnits::_radians_)
conversion to degrees
Definition: Func.cpp:104
double j4(const double xx)
the l=4 spherical Bessel function
Definition: Func.cpp:2057
void bin_function_2D(const std::string file_grid, double func(double *, size_t, void *), void *par, const int bin, const double x1_min, const double x1_max, const double x2_min, const double x2_max, const std::string binning, std::vector< double > &xx1, std::vector< double > &xx2, std::vector< std::vector< double >> &yy)
create a 2D grid given an input function
Definition: Func.cpp:1183
double jl_distance_average(const double kk, const int order, const double r_down, const double r_up)
the distance average for the order l-th spherical Bessel function
Definition: Func.cpp:2109
CoordinateUnits
the coordinate units
Definition: Kernel.h:562
std::vector< double > vector_from_distribution(const int nRan, const std::vector< double > xx, const std::vector< double > fx, const double xmin, const double xmax, const int seed)
return a std::vector of numbers sampled from a given distribution
Definition: Func.cpp:1455
void sdss_atbound2(double &theta, double &phi)
set the angular coordinates in the SDSS boundaries
Definition: Func.cpp:1356
void WarningMsgCBL(const std::string msg, const std::string functionCBL, const std::string fileCBL)
internal CBL warning message
Definition: Kernel.h:747
double perpendicular_distance(const double ra1, const double ra2, const double dec1, const double dec2, const double d1, const double d2)
the perpendicular separation, rp
Definition: Func.cpp:259
double get_mu(const double r1, const double r2, const double r3)
get the cosine of the angle between two sides of a triangle
Definition: Func.cpp:2529
double determinant_matrix(const std::vector< std::vector< double >> mat)
compute the determinant of a matrix
Definition: Func.cpp:648
double legendre_polynomial(const double mu, const int l)
the order l Legendre polynomial
Definition: Func.cpp:1786
void measure_var_function(const std::vector< double > var, const int bin, const double V_min, const double V_max, const double Volume, std::vector< double > &Var, std::vector< double > &Phi, std::vector< double > &err)
measure the var function (where "var" could be the mass, the luminosity, the radius,...
Definition: Func.cpp:1084
double jl(const double xx, const int order)
the order l spherical Bessel function
Definition: Func.cpp:2066
void convolution(const std::vector< double > f1, const std::vector< double > f2, std::vector< double > &res, const double deltaX)
convolution of two functions
Definition: Func.cpp:1580
void eq2sdss(const std::vector< double > ra, const std::vector< double > dec, std::vector< double > &lambda, std::vector< double > &eta)
convert from equatorial coordinates R.A., Dec to sdss coordinates
Definition: Func.cpp:1373
double arcseconds(const double angle, const CoordinateUnits inputUnits=CoordinateUnits::_radians_)
conversion to arcseconds
Definition: Func.cpp:148
void bin_function(const std::string file_grid, double func(double, void *), void *par, const int bin, const double x_min, const double x_max, const std::string binning, std::vector< double > &xx, std::vector< double > &yy)
create a 1D grid given an input function
Definition: Func.cpp:1118
double distribution_probability(double xx, std::shared_ptr< void > pp, std::vector< double > par)
probability of an interpolated distribution
Definition: Func.cpp:58
void read_vector(const std::string file_vector, std::vector< double > &xx, std::vector< double > &vector, const std::vector< int > col={})
read a vector from file
Definition: Func.cpp:582
double window_function(const double x, const double min=-1, const double max=1)
the unnormalized window function
Definition: Func.cpp:2538
double wigner3j_auxB(double l1, double l2, double l3, double m1, double m2, double m3)
Wigner auxiliar function B.
Definition: Func.cpp:2253
double number_from_distribution(const std::vector< double > xx, const std::vector< double > fx, const double xmin, const double xmax, const int seed)
return a number sampled from a given distribution
Definition: Func.cpp:1446
double wigner_6j(const int j1, const int j2, const int j3, const int j4, const int j5, const int j6)
Wigner symbol.
Definition: Func.cpp:2502
void polar_coord(const double XX, const double YY, const double ZZ, double &ra, double &dec, double &dd)
conversion from Cartesian coordinates to polar coordinates
Definition: Func.cpp:214
double arcminutes(const double angle, const CoordinateUnits inputUnits=CoordinateUnits::_radians_)
conversion to arcminutes
Definition: Func.cpp:170
std::vector< size_t > minimum_maximum_indexes(const std::vector< double > xx, const double x_min, const double x_max)
return the std::vector indexes corresponding to a given interval
Definition: Func.cpp:1503
std::shared_ptr< void > SPIN
CUBA SPIN parameter.
Definition: CUBAwrapper.h:107