Fast Methods for Cosmological Simulations
FastSim serves as a tool for quick N-body simulations in modified gravity.
ccl_emu17.c
Go to the documentation of this file.
1 //
2 // emu.c
3 // Created by Earl Lawrence on 11/10/16.
4 // Modified E Chisari 05/10/17 for CCL
5 // For details on the license, see ../LICENSE_COSMICEMU
6 // in this repository.
7 //
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <string.h>
13 
14 #include <gsl/gsl_matrix.h>
15 #include <gsl/gsl_linalg.h>
16 #include <gsl/gsl_spline.h>
17 #include <gsl/gsl_errno.h>
18 
19 #include "ccl.h"
20 
21 #include "ccl_emu17_params.h"
22 #include "ccl_emu17.h"
23 
24 // Sizes of stuff
25 static int m[2] = {111, 36}, neta=2808, peta[2]={7, 28}, rs=8, p=8;
26 
27 // Kriging basis computed by emuInit
28 // Sizes of each basis will be peta[ee] and m[ee]
29 static double KrigBasis[2][28][111];
30 
31 // Need to combine some things into a big thing.
32 static double beta[2][28][8];
33 static double w[2][28][111];
34 static double lamws[2][28];
35 static double lamz[2][28];
36 
37 // Initialization to compute the kriging basis for the two parts
38 static void emuInit() {
39 
40  int ee, i, j, k, l;
41  double cov;
42  gsl_matrix *SigmaSim;
43  gsl_vector *b;
44 
45  // Because of the structure of this emu, I need to do this horrible part first.
46  // Fill in the correlation lenghths
47  for(i=0; i<7; i++) {
48  for(j=0; j<8; j++) {
49  beta[0][i][j] = beta1[i][j];
50  }
51  }
52 
53  for(i=0; i<28; i++) {
54  for(j=0; j<8; j++) {
55  beta[1][i][j] = beta2[i][j];
56  }
57  }
58 
59  // Fill in the PC weights
60  for(i=0; i<7; i++) {
61  for(j=0; j<111; j++) {
62  w[0][i][j] = w1[i][j];
63  }
64  }
65 
66  for(i=0; i<28; i++) {
67  for(j=0; j<36; j++) {
68  w[1][i][j] = w2[i][j];
69  }
70  }
71 
72  // Fill in the precisions
73  for(i=0; i<7; i++) {
74  lamws[0][i] = lamws1[i];
75  lamz[0][i] = lamz1[i];
76  }
77 
78  for(i=0; i<28; i++) {
79  lamws[1][i] = lamws2[i];
80  lamz[1][i] = lamz2[i];
81  }
82 
83  // This emu has two parts: one that uses all m[0] of the data for the the first peta[0] components
84  // and another that uses only the m[1] complete data for the next peta[1] components.
85  for(ee=0; ee<2; ee++) {
86 
87  // Allocate some stuff
88  SigmaSim = gsl_matrix_alloc(m[ee], m[ee]);
89  b = gsl_vector_alloc(m[ee]);
90 
91  // Loop over the basis
92  for(i=0; i<peta[ee]; i++) {
93 
94  // Loop over the number of simulations
95  for(j=0; j<m[ee]; j++) {
96 
97  // Diagonal term
98  gsl_matrix_set(SigmaSim, j, j, (1.0/lamz[ee][i]) + (1.0/lamws[ee][i]));
99 
100  // Off-diagonals
101  for(k=0; k<j; k++) {
102 
103  // compute the covariance
104  cov = 0.0;
105  for(l=0; l<p; l++) {
106  cov -= beta[ee][i][l]*pow(x[j][l] - x[k][l], 2.0);
107  } // for(l=0; l<p; l++)
108  cov = exp(cov) / lamz[ee][i];
109 
110  // put the covariance where it belongs
111  gsl_matrix_set(SigmaSim, j, k, cov);
112  gsl_matrix_set(SigmaSim, k, j, cov);
113 
114  } // for(k=0; k<j; k++)
115 
116  // Vector for the PC weights
117  gsl_vector_set(b, j, w[ee][i][j]);
118 
119  } // for(j=0; j<m[ee]; j++)
120 
121  // Cholesky and solve
122  gsl_linalg_cholesky_decomp(SigmaSim);
123  gsl_linalg_cholesky_svx(SigmaSim, b);
124 
125  // Put b where it belongs in the Kriging basis
126  for(j=0; j<m[ee]; j++) {
127  KrigBasis[ee][i][j] = gsl_vector_get(b, j);
128  }
129 
130  } // for(i=0; i<peta[ee]; i++)
131 
132  // Clean this up
133  gsl_matrix_free(SigmaSim);
134  gsl_vector_free(b);
135 
136  } // for(ee=0; ee<2; ee+)
137 
138 } // emuInit()
139 
140 // Actual emulation
141 void ccl_pkemu(double *xstar, double **ystar, int* status, ccl_cosmology* cosmo) {
142 
143  static double inited=0;
144  int ee, i, j, k;
145  double wstar[peta[0]+peta[1]];
146  double Sigmastar[2][peta[1]][m[0]];
147  double ystaremu[neta];
148  *ystar=(double *)malloc(sizeof(double)*NK_EMU);
149  double ybyz[rs];
150  double logc;
151  double xstarstd[p];
152  int zmatch;
153  gsl_spline *zinterp = gsl_spline_alloc(gsl_interp_cspline, rs);
154  gsl_interp_accel *accel = gsl_interp_accel_alloc();
155 
156 
157  // Initialize if necessary
158  if(inited==0) {
159  emuInit();
160  inited = 1;
161  }
162 
163  // Transform w_a into (-w_0-w_a)^(1/4)
164  xstar[6] = pow(-xstar[5]-xstar[6], 0.25);
165  // Check the inputs to make sure we're interpolating.
166  for(i=0; i<p; i++) {
167  if((xstar[i] < xmin[i]) || (xstar[i] > xmax[i])) {
168  switch(i) {
169  case 0:
171  "ccl_pkemu(): omega_m must be between %f and %f.\n",
172  xmin[i], xmax[i]);
173  break;
174  case 1:
176  "ccl_pkemu(): omega_b must be between %f and %f.\n",
177  xmin[i], xmax[i]);
178  break;
179  case 2:
181  "ccl_pkemu(): sigma8 must be between %f and %f.\n",
182  xmin[i], xmax[i]);
183  break;
184  case 3:
186  "ccl_pkemu(): h must be between %f and %f.\n",
187  xmin[i], xmax[i]);
188  break;
189  case 4:
191  "ccl_pkemu(): n_s must be between %f and %f.\n",
192  xmin[i], xmax[i]);
193  break;
194  case 5:
196  "ccl_pkemu(): w_0 must be between %f and %f.\n",
197  xmin[i], xmax[i]);
198  break;
199  case 6:
201  "ccl_pkemu(): (-w_0-w_a)^(1/4) must be between %f and %f.\n",
202  xmin[i], xmax[i]);
203  break;
204  case 7:
206  "ccl_pkemu(): omega_nu must be between %f and %f.\n",
207  xmin[i], xmax[i]);
208  break;
209  }
210  *status = CCL_ERROR_EMULATOR_BOUND;
211  ccl_raise_exception(*status, cosmo->status_message);
212  gsl_spline_free(zinterp);
213  gsl_interp_accel_free(accel);
214  return;
215  }
216  } // for(i=0; i<p; i++)
217  if((xstar[p] < z[0]) || (xstar[p] > z[rs-1])) {
219  "ccl_pkemu(): z must be between %f and %f.\n",
220  z[0], z[rs-1]);
221  *status = CCL_ERROR_EMULATOR_BOUND;
222  ccl_raise_exception(*status, cosmo->status_message);
223  gsl_spline_free(zinterp);
224  gsl_interp_accel_free(accel);
225  return;
226  }
227 
228  // Standardize the inputs
229  for(i=0; i<p; i++) {
230  xstarstd[i] = (xstar[i] - xmin[i]) / xrange[i];
231  }
232 
233  // compute the covariances between the new input and sims for all the PCs.
234  for(ee=0; ee<2; ee++) {
235  for(i=0; i<peta[ee]; i++) {
236  for(j=0; j<m[ee]; j++) {
237  logc = 0.0;
238  for(k=0; k<p; k++) {
239  logc -= beta[ee][i][k]*pow(x[j][k] - xstarstd[k], 2.0);
240  }
241  Sigmastar[ee][i][j] = exp(logc) / lamz[ee][i];
242  }
243  }
244  }
245 
246  // Compute wstar for the first chunk.
247  for(i=0; i<peta[0]; i++) {
248  wstar[i]=0.0;
249  for(j=0; j<m[0]; j++) {
250  wstar[i] += Sigmastar[0][i][j] * KrigBasis[0][i][j];
251  }
252  }
253  // Compute wstar for the second chunk.
254  for(i=0; i<peta[1]; i++) {
255  wstar[peta[0]+i]=0.0;
256  for(j=0; j<m[1]; j++) {
257  wstar[peta[0]+i] += Sigmastar[1][i][j] * KrigBasis[1][i][j];
258  }
259  }
260 
261  /*
262  for(i=0; i<peta[0]+peta[1]; i++) {
263  printf("%f\n", wstar[i]);
264  }
265  */
266 
267  // Compute ystar, the new output
268  for(i=0; i<neta; i++) {
269  ystaremu[i] = 0.0;
270  for(j=0; j<peta[0]+peta[1]; j++) {
271  ystaremu[i] += K[i][j]*wstar[j];
272  }
273  ystaremu[i] = ystaremu[i]*sd + mean[i];
274 
275  // Convert to P(k)
276  //ystaremu[i] = ystaremu[i] - 1.5*log10(mode[i % NK_EMU]);
277  //ystaremu[i] = 2*M_PI*M_PI*pow(10, ystaremu[i]);
278  }
279 
280 
281 
282  // Interpolate to the desired redshift
283  // Natural cubic spline interpolation over z.
284 
285  // First check to see if the requested z is one of the training z.
286  zmatch = -1;
287  for(i=0; i<rs; i++) {
288  if(xstar[p] == z[i]) {
289  zmatch = rs-i-1;
290  }
291  }
292 
293  // z doesn't match a training z, interpolate
294  if(zmatch == -1) {
295  for(i=0; i<NK_EMU; i++) {
296  for(j=0; j<rs; j++) {
297  ybyz[rs-j-1] = ystaremu[j*NK_EMU+i];
298  }
299  gsl_spline_init(zinterp, z, ybyz, rs);
300  (*ystar)[i] = gsl_spline_eval(zinterp, xstar[p], accel);
301  gsl_interp_accel_reset(accel);
302  }
303 
304  } else { //otherwise, copy in the emulated z without interpolating
305  for(i=0; i<NK_EMU; i++) {
306  (*ystar)[i] = ystaremu[zmatch*NK_EMU + i];
307  }
308  }
309 
310  gsl_spline_free(zinterp);
311  gsl_interp_accel_free(accel);
312 
313  // Convert to P(k)
314  for(i=0; i<NK_EMU; i++) {
315  (*ystar)[i] = (*ystar)[i] - 1.5*log10(mode[i]) + log10(2) + 2*log10(M_PI);
316  (*ystar)[i] = pow(10, (*ystar)[i]);
317  }
318 }
319 
static double sd
static int rs
Definition: ccl_emu17.c:25
#define NK_EMU
Definition: ccl_emu17.h:7
static double w2[28][36]
static double lamz2[28]
static double KrigBasis[2][28][111]
Definition: ccl_emu17.c:29
static double lamz[2][28]
Definition: ccl_emu17.c:35
static double beta2[28][8]
static double beta1[7][8]
#define M_PI
Definition: ccl_constants.h:22
void ccl_cosmology_set_status_message(ccl_cosmology *cosmo, const char *status_message,...)
Definition: ccl_core.c:792
static double lamws1[7]
static double lamws[2][28]
Definition: ccl_emu17.c:34
static double beta[2][28][8]
Definition: ccl_emu17.c:32
static double lamz1[7]
static CCL_BEGIN_DECLS double x[111][8]
static int peta[2]
Definition: ccl_emu17.c:25
void ccl_pkemu(double *xstar, double **ystar, int *status, ccl_cosmology *cosmo)
Definition: ccl_emu17.c:141
#define CCL_ERROR_EMULATOR_BOUND
Definition: ccl_error.h:23
static int neta
Definition: ccl_emu17.c:25
static double z[8]
static void emuInit()
Definition: ccl_emu17.c:38
static double w1[7][111]
static int p
Definition: ccl_emu17.c:25
float pow(float base, unsigned long int exp)
Definition: precision.hpp:39
static int m[2]
Definition: ccl_emu17.c:25
static double mode[351]
void ccl_raise_exception(int err, const char *msg,...)
Definition: ccl_error.c:35
static double K[2808][35]
static double w[2][28][111]
Definition: ccl_emu17.c:33
static double mean[2808]
static double xrange[8]
static double xmax[8]
static double lamws2[28]
char status_message[500]
Definition: ccl_core.h:136
static double xmin[8]