Fast Methods for Cosmological Simulations
FastSim serves as a tool for quick N-body simulations in modified gravity.
ccl_utils.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 
5 #include <gsl/gsl_errno.h>
6 
7 #include "ccl.h"
8 
9 /* ------- ROUTINE: ccl_linear spacing ------
10 INPUTS: [xmin,xmax] of the interval to be divided in N bins
11 OUTPUT: bin edges in range [xmin,xmax]
12 */
13 
14 double * ccl_linear_spacing(double xmin, double xmax, int N)
15 {
16  double dx = (xmax-xmin)/(N -1.);
17 
18  double * x = malloc(sizeof(double)*N);
19  if (x==NULL) {
22  "ERROR: Could not allocate memory for linear-spaced array (N=%d)\n", N);
23  return x;
24  }
25 
26  for (int i=0; i<N; i++) {
27  x[i] = xmin + dx*i;
28  }
29  x[0]=xmin; //Make sure roundoff errors don't spoil edges
30  x[N-1]=xmax; //Make sure roundoff errors don't spoil edges
31 
32  return x;
33 }
34 
35 /* ------- ROUTINE: ccl_linlog spacing ------
36  * INPUTS: [xminlog,xmax] of the interval to be divided in bins
37  * xmin when linear spacing starts
38  * Nlog number of logarithmically spaced bins
39  * Nlin number of linearly spaced bins
40  * OUTPUT: bin edges in range [xminlog,xmax]
41  * */
42 
43 double * ccl_linlog_spacing(double xminlog, double xmin, double xmax, int Nlog, int Nlin)
44 {
45  if (Nlog<2) {
48  "ERROR: Cannot make log-spaced array with %d points - need at least 2\n", Nlog);
49  return NULL;
50  }
51 
52  if (!(xminlog>0 && xmin>0)) {
55  "ERROR: Cannot make log-spaced array xminlog or xmin non-positive (had %le, %le)\n", xminlog, xmin);
56  return NULL;
57  }
58 
59  if (xminlog>xmin){
60  ccl_raise_warning(CCL_ERROR_LINLOGSPACE, "ERROR: xminlog must be smaller as xmin");
61  return NULL;
62  }
63 
64  if (xmin>xmax){
65  ccl_raise_warning(CCL_ERROR_LINLOGSPACE, "ERROR: xmin must be smaller as xmax");
66  return NULL;
67  }
68 
69  double * x = malloc(sizeof(double)*(Nlin+Nlog-1));
70  if (x==NULL) {
73  "ERROR: Could not allocate memory for array of size (Nlin+Nlog-1)=%d)\n", (Nlin+Nlog-1));
74  return x;
75  }
76 
77  double dx = (xmax-xmin)/(Nlin -1.);
78  double log_xchange = log(xmin);
79  double log_xmin = log(xminlog);
80  double dlog_x = (log_xchange - log_xmin) / (Nlog-1.);
81 
82  for (int i=0; i<Nlin+Nlog-1; i++) {
83  if (i<Nlog)
84  x[i] = exp(log_xmin + dlog_x*i);
85  if (i>=Nlog)
86  x[i] = xmin + dx*(i-Nlog+1);
87  }
88 
89  x[0]=xminlog; //Make sure roundoff errors don't spoil edges
90  x[Nlog-1]=xmin; //Make sure roundoff errors don't spoil edges
91  x[Nlin+Nlog-2]=xmax; //Make sure roundoff errors don't spoil edges
92 
93  return x;
94 }
95 
96 /* ------- ROUTINE: ccl_log spacing ------
97 INPUTS: [xmin,xmax] of the interval to be divided logarithmically in N bins
98 TASK: divide an interval in N logarithmic bins
99 OUTPUT: bin edges in range [xmin,xmax]
100 */
101 
102 double * ccl_log_spacing(double xmin, double xmax, int N)
103 {
104  if (N<2) {
107  "ERROR: Cannot make log-spaced array with %d points - need at least 2\n", N);
108  return NULL;
109  }
110 
111  if (!(xmin>0 && xmax>0)) {
114  "ERROR: Cannot make log-spaced array xmax or xmax non-positive (had %le, %le)\n", xmin, xmax);
115  return NULL;
116  }
117 
118  double log_xmax = log(xmax);
119  double log_xmin = log(xmin);
120  double dlog_x = (log_xmax - log_xmin) / (N-1.);
121 
122  double * x = malloc(sizeof(double)*N);
123  if (x==NULL) {
126  "ERROR: Could not allocate memory for log-spaced array (N=%d)\n", N);
127  return x;
128  }
129 
130  double xratio = exp(dlog_x);
131  x[0] = xmin; //Make sure roundoff errors don't spoil edges
132  for (int i=1; i<N-1; i++) {
133  x[i] = x[i-1] * xratio;
134  }
135  x[N-1]=xmax; //Make sure roundoff errors don't spoil edges
136 
137  return x;
138 }
139 
140 
141 //Spline creator
142 //n -> number of points
143 //x -> x-axis
144 //y -> f(x)-axis
145 //y0,yf -> values of f(x) to use beyond the interpolation range
146 SplPar *ccl_spline_init(int n,double *x,double *y,double y0,double yf)
147 {
148  SplPar *spl=malloc(sizeof(SplPar));
149  if(spl==NULL)
150  return NULL;
151 
152  spl->intacc=gsl_interp_accel_alloc();
153  spl->spline=gsl_spline_alloc(gsl_interp_cspline,n);
154  int parstatus=gsl_spline_init(spl->spline,x,y,n);
155  if(parstatus) {
156  gsl_interp_accel_free(spl->intacc);
157  gsl_spline_free(spl->spline);
158  return NULL;
159  }
160 
161  spl->x0=x[0];
162  spl->xf=x[n-1];
163  spl->y0=y0;
164  spl->yf=yf;
165 
166  return spl;
167 }
168 
169 //Evaluates spline at x checking for bound errors
170 double ccl_spline_eval(double x,SplPar *spl)
171 {
172  if(x<=spl->x0)
173  return spl->y0;
174  else if(x>=spl->xf)
175  return spl->yf;
176  else {
177  double y;
178  int stat=gsl_spline_eval_e(spl->spline,x,spl->intacc,&y);
179  if (stat!=GSL_SUCCESS) {
180  ccl_raise_gsl_warning(stat, "ccl_utils.c: ccl_splin_eval():");
181  return NAN;
182  }
183  return y;
184  }
185 }
186 
187 #define CCL_GAMMA1 2.6789385347077476336556 //Gamma(1/3)
188 #define CCL_GAMMA2 1.3541179394264004169452 //Gamma(2/3)
189 #define CCL_ROOTPI12 21.269446210866192327578 //12*sqrt(pi)
190 double ccl_j_bessel(int l,double x)
191 {
192  double jl;
193  double ax=fabs(x);
194  double ax2=x*x;
195  if(l<0) {
196  fprintf(stderr,"CosmoMas: l>0 for Bessel function");
197  exit(1);
198  }
199 
200  if(l<7) {
201  if(l==0) {
202  if(ax<0.1) jl=1-ax2*(1-ax2/20.)/6.;
203  else jl=sin(x)/x;
204  }
205  else if(l==1) {
206  if(ax<0.2) jl=ax*(1-ax2*(1-ax2/28)/10)/3;
207  else jl=(sin(x)/ax-cos(x))/ax;
208  }
209  else if(l==2) {
210  if(ax<0.3) jl=ax2*(1-ax2*(1-ax2/36)/14)/15;
211  else jl=(-3*cos(x)/ax-sin(x)*(1-3/ax2))/ax;
212  }
213  else if(l==3) {
214  if(ax<0.4)
215  jl=ax*ax2*(1-ax2*(1-ax2/44)/18)/105;
216  else
217  jl=(cos(x)*(1-15/ax2)-sin(x)*(6-15/ax2)/ax)/ax;
218  }
219  else if(l==4) {
220  if(ax<0.6)
221  jl=ax2*ax2*(1-ax2*(1-ax2/52)/22)/945;
222  else
223  jl=(sin(x)*(1-(45-105/ax2)/ax2)+cos(x)*(10-105/ax2)/ax)/ax;
224  }
225  else if(l==5) {
226  if(ax<1.0)
227  jl=ax2*ax2*ax*(1-ax2*(1-ax2/60)/26)/10395;
228  else {
229  jl=(sin(x)*(15-(420-945/ax2)/ax2)/ax-
230  cos(x)*(1-(105-945/ax2)/ax2))/ax;
231  }
232  }
233  else {
234  if(ax<1.0)
235  jl=ax2*ax2*ax2*(1-ax2*(1-ax2/68)/30)/135135;
236  else {
237  jl=(sin(x)*(-1+(210-(4725-10395/ax2)/ax2)/ax2)+
238  cos(x)*(-21+(1260-10395/ax2)/ax2)/ax)/ax;
239  }
240  }
241  }
242  else {
243  double nu=l+0.5;
244  double nu2=nu*nu;
245 
246  if(ax<1.0E-40) jl=0;
247  else if((ax2/l)<0.5) {
248  jl=(exp(l*log(ax/nu)-M_LN2+nu*(1-M_LN2)-(1-(1-3.5/nu2)/(30*nu2))/(12*nu))/nu)*
249  (1-ax2/(4*nu+4)*(1-ax2/(8*nu+16)*(1-ax2/(12*nu+36))));
250  }
251  else if((l*l/ax)<0.5) {
252  double beta=ax-0.5*M_PI*(l+1);
253  jl=(cos(beta)*(1-(nu2-0.25)*(nu2-2.25)/(8*ax2)*(1-(nu2-6.25)*(nu2-12.25)/(48*ax2)))-
254  sin(beta)*(nu2-0.25)/(2*ax)*(1-(nu2-2.25)*(nu2-6.25)/(24*ax2)*
255  (1-(nu2-12.25)*(nu2-20.25)/(80*ax2))))/ax;
256  }
257  else {
258  double l3=pow(nu,0.325);
259  if(ax<nu-1.31*l3) {
260  double cosb=nu/ax;
261  double sx=sqrt(nu2-ax2);
262  double cotb=nu/sx;
263  double secb=ax/nu;
264  double beta=log(cosb+sx/ax);
265  double cot3b=cotb*cotb*cotb;
266  double cot6b=cot3b*cot3b;
267  double sec2b=secb*secb;
268  double expterm=((2+3*sec2b)*cot3b/24
269  -((4+sec2b)*sec2b*cot6b/16
270  +((16-(1512+(3654+375*sec2b)*sec2b)*sec2b)*cot3b/5760
271  +(32+(288+(232+13*sec2b)*sec2b)*sec2b)*sec2b*cot6b/(128*nu))*
272  cot6b/nu)/nu)/nu;
273  jl=sqrt(cotb*cosb)/(2*nu)*exp(-nu*beta+nu/cotb-expterm);
274  }
275  else if(ax>nu+1.48*l3) {
276  double cosb=nu/ax;
277  double sx=sqrt(ax2-nu2);
278  double cotb=nu/sx;
279  double secb=ax/nu;
280  double beta=acos(cosb);
281  double cot3b=cotb*cotb*cotb;
282  double cot6b=cot3b*cot3b;
283  double sec2b=secb*secb;
284  double trigarg=nu/cotb-nu*beta-0.25*M_PI-
285  ((2+3*sec2b)*cot3b/24+(16-(1512+(3654+375*sec2b)*sec2b)*sec2b)*
286  cot3b*cot6b/(5760*nu2))/nu;
287  double expterm=((4+sec2b)*sec2b*cot6b/16-
288  (32+(288+(232+13*sec2b)*sec2b)*sec2b)*
289  sec2b*cot6b*cot6b/(128*nu2))/nu2;
290  jl=sqrt(cotb*cosb)/nu*exp(-expterm)*cos(trigarg);
291  }
292  else {
293  double beta=ax-nu;
294  double beta2=beta*beta;
295  double sx=6/ax;
296  double sx2=sx*sx;
297  double secb=pow(sx,0.3333333333333333333333);
298  double sec2b=secb*secb;
299 
300  jl=(CCL_GAMMA1*secb+beta*CCL_GAMMA2*sec2b
301  -(beta2/18-1.0/45.0)*beta*sx*secb*CCL_GAMMA1
302  -((beta2-1)*beta2/36+1.0/420.0)*sx*sec2b*CCL_GAMMA2
303  +(((beta2/1620-7.0/3240.0)*beta2+1.0/648.0)*beta2-1.0/8100.0)*sx2*secb*CCL_GAMMA1
304  +(((beta2/4536-1.0/810.0)*beta2+19.0/11340.0)*beta2-13.0/28350.0)*beta*sx2*sec2b*CCL_GAMMA2
305  -((((beta2/349920-1.0/29160.0)*beta2+71.0/583200.0)*beta2-121.0/874800.0)*
306  beta2+7939.0/224532000.0)*beta*sx2*sx*secb*CCL_GAMMA1)*sqrt(sx)/CCL_ROOTPI12;
307  }
308  }
309  }
310  if((x<0)&&(l%2!=0)) jl=-jl;
311 
312  return jl;
313 }
314 
315 //Spline destructor
317 {
318  gsl_spline_free(spl->spline);
319  gsl_interp_accel_free(spl->intacc);
320  free(spl);
321 }
#define CCL_ROOTPI12
Definition: ccl_utils.c:189
#define CCL_ERROR_LINLOGSPACE
Definition: ccl_error.h:38
double yf
Definition: ccl_utils.h:53
void ccl_raise_gsl_warning(int gslstatus, const char *msg,...)
Definition: ccl_error.c:75
double x0
Definition: ccl_utils.h:52
#define CCL_GAMMA1
Definition: ccl_utils.c:187
gsl_spline * spline
Definition: ccl_utils.h:51
static double beta2[28][8]
#define M_PI
Definition: ccl_constants.h:22
double * ccl_linear_spacing(double xmin, double xmax, int N)
Definition: ccl_utils.c:14
double y0
Definition: ccl_utils.h:53
Grid< NDIM, T > sqrt(Grid< NDIM, T > lhs)
Definition: grid.h:231
static double beta[2][28][8]
Definition: ccl_emu17.c:32
static CCL_BEGIN_DECLS double x[111][8]
gsl_interp_accel * intacc
Definition: ccl_utils.h:50
SplPar * ccl_spline_init(int n, double *x, double *y, double y0, double yf)
Definition: ccl_utils.c:146
#define CCL_ERROR_MEMORY
Definition: ccl_error.h:10
void ccl_raise_warning(int err, const char *msg,...)
Definition: ccl_error.c:56
#define CCL_ERROR_LOGSPACE
Definition: ccl_error.h:37
double * ccl_log_spacing(double xmin, double xmax, int N)
Definition: ccl_utils.c:102
#define CCL_GAMMA2
Definition: ccl_utils.c:188
double ccl_spline_eval(double x, SplPar *spl)
Definition: ccl_utils.c:170
double * ccl_linlog_spacing(double xminlog, double xmin, double xmax, int Nlog, int Nlin)
Definition: ccl_utils.c:43
float pow(float base, unsigned long int exp)
Definition: precision.hpp:39
void ccl_spline_free(SplPar *spl)
Definition: ccl_utils.c:316
double xf
Definition: ccl_utils.h:52
static double xmax[8]
static double xmin[8]
double ccl_j_bessel(int l, double x)
Definition: ccl_utils.c:190