MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
gravpm.c
Go to the documentation of this file.
1 #include <mpi.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <string.h>
5 #include <omp.h>
6 
7 #include "utils.h"
8 
9 #include "partmanager.h"
10 #include "forcetree.h"
11 #include "petapm.h"
12 #include "domain.h"
13 #include "walltime.h"
14 #include "gravity.h"
15 
16 #include "cosmology.h"
17 #include "neutrinos_lra.h"
18 
19 static int pm_mark_region_for_node(int startno, int rid, int * RegionInd, const ForceTree * tt);
20 static void convert_node_to_region(PetaPM * pm, PetaPMRegion * r, struct NODE * Nodes);
21 
22 static int hybrid_nu_gravpm_is_active(int i);
23 static void potential_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
24 static void compute_neutrino_power(PetaPM * pm);
25 static void force_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
26 static void force_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
27 static void force_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
28 static void readout_potential(PetaPM * pm, int i, double * mesh, double weight);
29 static void readout_force_x(PetaPM * pm, int i, double * mesh, double weight);
30 static void readout_force_y(PetaPM * pm, int i, double * mesh, double weight);
31 static void readout_force_z(PetaPM * pm, int i, double * mesh, double weight);
33 {
34  {"Potential", NULL, readout_potential},
35  {"ForceX", force_x_transfer, readout_force_x},
36  {"ForceY", force_y_transfer, readout_force_y},
37  {"ForceZ", force_z_transfer, readout_force_z},
38  {NULL, NULL, NULL},
39 };
40 
41 static PetaPMRegion * _prepare(PetaPM * pm, PetaPMParticleStruct * pstruct, void * userdata, int * Nregions);
42 
43 static struct gravpm_params
44 {
45  double Time;
46  double TimeIC;
51 
52 void
53 gravpm_init_periodic(PetaPM * pm, double BoxSize, double Asmth, int Nmesh, double G) {
54  petapm_init(pm, BoxSize, Asmth, Nmesh, G, MPI_COMM_WORLD);
55 }
56 
57 /* Computes the gravitational force on the PM grid
58  * and saves the total matter power spectrum.
59  * Parameters: Cosmology, Time, UnitLength_in_cm and PowerOutputDir are used by the power spectrum output code.
60  * TimeIC and FastParticleType are used by the massive neutrino code. FastParticleType denotes possibly inactive particles.*/
61 void
62 gravpm_force(PetaPM * pm, ForceTree * tree, Cosmology * CP, double Time, double UnitLength_in_cm, const char * PowerOutputDir, double TimeIC, int FastParticleType) {
63  PetaPMParticleStruct pstruct = {
64  P,
65  sizeof(P[0]),
66  (char*) &P[0].Pos[0] - (char*) P,
67  (char*) &P[0].Mass - (char*) P,
68  /* Regions allocated inside _prepare*/
69  NULL,
70  /* By default all particles are active. For hybrid neutrinos set below.*/
71  NULL,
73  };
74 
76 
77  /*Initialise the kspace neutrino code if it is enabled.
78  * Mpc units are used to match power spectrum code.*/
79  if(CP->MassiveNuLinRespOn) {
82  }
83 
84  if(CP->HybridNeutrinosOn && particle_nu_fraction(&(CP->ONu.hybnu), Time, 0) == 0.)
86 
87  int i;
88  #pragma omp parallel for
89  for(i = 0; i < PartManager->NumPart; i++)
90  {
91  P[i].GravPM[0] = P[i].GravPM[1] = P[i].GravPM[2] = 0;
92  }
93 
94  /* Set up parameters*/
95  GravPM.Time = Time;
96  GravPM.TimeIC = TimeIC;
97  GravPM.CP = CP;
98  GravPM.FastParticleType = FastParticleType;
100  /*
101  * we apply potential transfer immediately after the R2C transform,
102  * Therefore the force transfer functions are based on the potential,
103  * not the density.
104  * */
105  petapm_force(pm, _prepare, &global_functions, functions, &pstruct, tree);
106  powerspectrum_sum(pm->ps);
107  /*Now save the power spectrum*/
108  powerspectrum_save(pm->ps, PowerOutputDir, "powerspectrum", Time, GrowthFactor(CP, Time, 1.0));
109  /* Save the neutrino power if it is allocated*/
110  if(pm->ps->logknu)
111  powerspectrum_nu_save(pm->ps, PowerOutputDir, "powerspectrum-nu", Time);
112  /*We are done with the power spectrum, free it*/
113  powerspectrum_free(pm->ps);
114  walltime_measure("/LongRange");
115 }
116 
117 static PetaPMRegion * _prepare(PetaPM * pm, PetaPMParticleStruct * pstruct, void * userdata, int * Nregions) {
118  /*
119  *
120  * walks down the tree, identify nodes that contains local mass and
121  * are sufficiently large in volume.
122  *
123  * for each nodes, a mesh region is created.
124  * the particles in a node are linked to their hosting region
125  * (each particle belongs
126  * to exactly one region even though it may be covered by two)
127  *
128  * */
129  ForceTree * tree = (ForceTree *) userdata;
130  /* In worst case, each topleave becomes a region: thus
131  * NTopLeaves is sufficient */
132  PetaPMRegion * regions = (PetaPMRegion *) mymalloc2("Regions", sizeof(PetaPMRegion) * tree->NTopLeaves);
133  pstruct->RegionInd = (int *) mymalloc2("RegionInd", PartManager->NumPart * sizeof(int));
134  int r = 0;
135 
136  int no = tree->firstnode; /* start with the root */
137  while(no >= 0) {
138 
139  if(!(tree->Nodes[no].f.DependsOnLocalMass)) {
140  /* node doesn't contain particles on this process, do not open */
141  no = tree->Nodes[no].sibling;
142  continue;
143  }
144  if(
145  /* node is large */
146  (tree->Nodes[no].len <= pm->BoxSize / pm->Nmesh * 24)
147  ||
148  /* node is a top leaf */
149  ( !tree->Nodes[no].f.InternalTopLevel && (tree->Nodes[no].f.TopLevel) )
150  ) {
151  regions[r].no = no;
152  r ++;
153  /* do not open */
154  no = tree->Nodes[no].sibling;
155  continue;
156  }
157  /* open */
158  no = tree->Nodes[no].s.suns[0];
159  }
160 
161  *Nregions = r;
162  int maxNregions;
163  MPI_Reduce(&r, &maxNregions, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
164  message(0, "max number of regions is %d\n", maxNregions);
165 
166  int64_t i;
167  int numswallowed = 0;
168  #pragma omp parallel for reduction(+: numswallowed)
169  for(i =0; i < PartManager->NumPart; i ++) {
170  /* Swallowed black hole particles stick around but should not gravitate.
171  * Short-range is handled by not adding them to the tree. */
172  if(P[i].Swallowed){
173  pstruct->RegionInd[i] = -2;
174  numswallowed++;
175  }
176  else
177  pstruct->RegionInd[i] = -1;
178  }
179 
180  /* now lets mark particles to their hosting region */
181  int64_t numpart = 0;
182 #pragma omp parallel for reduction(+: numpart)
183  for(r = 0; r < *Nregions; r++) {
184  regions[r].numpart = pm_mark_region_for_node(regions[r].no, r, pstruct->RegionInd, tree);
185  numpart += regions[r].numpart;
186  }
187  for(i = 0; i < PartManager->NumPart; i ++) {
188  if(pstruct->RegionInd[i] == -1) {
189  message(1, "i = %d father %d not assigned to a region\n", i, force_get_father(i, tree));
190  }
191  }
192  /* All particles shall have been processed just once. Otherwise we die */
193  if((numpart+numswallowed) != PartManager->NumPart) {
194  endrun(1, "Processed only %ld particles out of %ld\n", numpart, PartManager->NumPart);
195  }
196  for(r =0; r < *Nregions; r++) {
197  convert_node_to_region(pm, &regions[r], tree->Nodes);
198  }
199  /*This is done to conserve memory during the PM step*/
200  if(force_tree_allocated(tree)) force_tree_free(tree);
201 
202  /*Allocate memory for a power spectrum*/
203  powerspectrum_alloc(pm->ps, pm->Nmesh, omp_get_max_threads(), GravPM.CP->MassiveNuLinRespOn, pm->BoxSize*GravPM.UnitLength_in_cm);
204 
205  walltime_measure("/PMgrav/Regions");
206  return regions;
207 }
208 
209 static int pm_mark_region_for_node(int startno, int rid, int * RegionInd, const ForceTree * tree) {
210  int numpart = 0;
211  int no = startno;
212  int endno = tree->Nodes[startno].sibling;
213  while(no >= 0 && no != endno)
214  {
215  struct NODE * nop = &tree->Nodes[no];
216  if(nop->f.ChildType == PARTICLE_NODE_TYPE) {
217  int i;
218  for(i = 0; i < nop->s.noccupied; i++) {
219  int p = nop->s.suns[i];
220  RegionInd[p] = rid;
221 #ifdef DEBUG
222  /* Check for particles outside of the node. This should never happen,
223  * unless there is a bug in tree build, or the particles are being moved.*/
224  int k;
225  for(k = 0; k < 3; k ++) {
226  double l = P[p].Pos[k] - tree->Nodes[startno].center[k];
227  l = fabs(l * 2);
228  if (l > tree->Nodes[startno].len) {
229  if(l > tree->Nodes[startno].len * (1+ 1e-7))
230  endrun(1, "enlarging node size from %g to %g, due to particle of type %d at %g %g %g id=%ld\n",
231  tree->Nodes[startno].len, l, P[p].Type, P[p].Pos[0], P[p].Pos[1], P[p].Pos[2], P[p].ID);
232  tree->Nodes[startno].len = l;
233  }
234  }
235 #endif
236  }
237  numpart += nop->s.noccupied;
238  /* Move to sibling*/
239  no = nop->sibling;
240  }
241  /* Generally this function should be handed top leaves which do not contain pseudo particles.
242  * However, sometimes it will receive an internal top node which can, if that top node is small enough.
243  * In this case, just move to the sibling: no particles to mark here.*/
244  else if(nop->f.ChildType == PSEUDO_NODE_TYPE)
245  no = nop->sibling;
246  else if(nop->f.ChildType == NODE_NODE_TYPE)
247  no = nop->s.suns[0];
248  else
249  endrun(122, "Unrecognised Node type %d, memory corruption!\n", nop->f.ChildType);
250  }
251  return numpart;
252 }
253 
254 
255 static void convert_node_to_region(PetaPM * pm, PetaPMRegion * r, struct NODE * Nodes) {
256  int k;
257  double cellsize = pm->BoxSize / pm->Nmesh;
258  int no = r->no;
259 #if 0
260  printf("task = %d no = %d len = %g hmax = %g center = %g %g %g\n",
261  ThisTask, no, Nodes[no].len, Nodes[no].hmax,
262  Nodes[no].center[0],
263  Nodes[no].center[1],
264  Nodes[no].center[2]);
265 #endif
266  for(k = 0; k < 3; k ++) {
267  r->offset[k] = floor((Nodes[no].center[k] - Nodes[no].len * 0.5) / cellsize);
268  int end = (int) ceil((Nodes[no].center[k] + Nodes[no].len * 0.5) / cellsize) + 1;
269  r->size[k] = end - r->offset[k] + 1;
270  r->center[k] = Nodes[no].center[k];
271  }
272 
273  /* setup the internal data structure of the region */
275 
276  r->len = Nodes[no].len;
277 }
278 
279 /********************
280  * transfer functions for
281  *
282  * potential from mass in cell
283  *
284  * and
285  *
286  * force from potential
287  *
288  *********************/
289 
290 /* unnormalized sinc function sin(x) / x */
291 static double sinc_unnormed(double x) {
292  if(x < 1e-5 && x > -1e-5) {
293  double x2 = x * x;
294  return 1.0 - x2 / 6. + x2 * x2 / 120.;
295  } else {
296  return sin(x) / x;
297  }
298 }
299 
300 /* Update the model prediction of LinResp neutrino power spectrum.
301  * This should happen after the CFT is computed,
302  * and after powerspectrum_add_mode() has been called,
303  * but before potential_transfer is called.*/
304 static void compute_neutrino_power(PetaPM * pm) {
305  Power * ps = pm->ps;
306  /*Note the power spectrum is now in Mpc units*/
307  powerspectrum_sum(ps);
308  int i;
309  /*Get delta_cdm_curr , which is P(k)^1/2.*/
310  for(i=0; i<ps->nonzero; i++) {
311  ps->Power[i] = sqrt(ps->Power[i]);
312  }
313  /*Get the neutrino power.*/
315 
316  /*Initialize the interpolation for the neutrinos*/
317  ps->nu_spline = gsl_interp_alloc(gsl_interp_linear,ps->nonzero);
318  ps->nu_acc = gsl_interp_accel_alloc();
319  gsl_interp_init(ps->nu_spline,ps->logknu,ps->delta_nu_ratio,ps->nonzero);
320  /*Zero power spectrum, which is stored with the neutrinos*/
321  powerspectrum_zero(ps);
322 }
323 
324 /* Compute the power spectrum of the fourier transformed grid in value.
325  * Store it in the PowerSpectrum structure */
326 void
327 powerspectrum_add_mode(Power * PowerSpectrum, const int64_t k2, const int kpos[3], pfft_complex * const value, const double invwindow, double Nmesh)
328 {
329  if(k2 == 0) {
330  /* Save zero mode corresponding to the mean as the normalisation factor.*/
331  PowerSpectrum->Norm = (value[0][0] * value[0][0] + value[0][1] * value[0][1]);
332  return;
333  }
334  /* Measure power spectrum: we don't want the zero mode.
335  * Some modes with k_z = 0 or N/2 have weight 1, the rest have weight 2.
336  * This is because of the symmetry of the real fft. */
337  if(k2 > 0) {
338  /*How many bins per unit (log) interval in k?*/
339  const double binsperunit=(PowerSpectrum->size-1)/log(sqrt(3) * Nmesh/2.0);
340  int kint=floor(binsperunit*log(k2)/2.);
341  int w;
342  const double keff = sqrt(kpos[0]*kpos[0]+kpos[1]*kpos[1]+kpos[2]*kpos[2]);
343  const double m = (value[0][0] * value[0][0] + value[0][1] * value[0][1]);
344  /*Make sure we do not overflow (although this should never happen)*/
345  if(kint >= PowerSpectrum->size)
346  return;
347  if(kpos[2] == 0 || kpos[2] == Nmesh/2) w = 1;
348  else w = 2;
349  /*Make sure we use thread-local memory to avoid racing.*/
350  const int index = kint + omp_get_thread_num() * PowerSpectrum->size;
351  /*Multiply P(k) by inverse window function*/
352  PowerSpectrum->Power[index] += w * m * invwindow * invwindow;
353  PowerSpectrum->Nmodes[index] += w;
354  PowerSpectrum->kk[index] += w * keff;
355  }
356 
357 }
358 
359 /*Just read the power spectrum, without changing the input value.*/
360 void
361 measure_power_spectrum(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex *value) {
362  double f = 1.0;
363  /* the CIC deconvolution kernel is
364  *
365  * sinc_unnormed(k_x L / 2 Nmesh) ** 2
366  *
367  * k_x = kpos * 2pi / L
368  *
369  * */
370  int k;
371  for(k = 0; k < 3; k ++) {
372  double tmp = (kpos[k] * M_PI) / pm->Nmesh;
373  tmp = sinc_unnormed(tmp);
374  f *= 1. / (tmp * tmp);
375  }
376  powerspectrum_add_mode(pm->ps, k2, kpos, value, f, pm->Nmesh);
377 }
378 
379 static void
380 potential_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex *value)
381 {
382  const double asmth2 = pow((2 * M_PI) * pm->Asmth / pm->Nmesh,2);
383  double f = 1.0;
384  const double smth = exp(-k2 * asmth2) / k2;
385  /* fac is - 4pi G (L / 2pi) **2 / L ** 3
386  * Gravity k2 DFT (dk **3, but )
387  * */
388  const double pot_factor = - pm->G / (M_PI * pm->BoxSize); /* to get potential */
389 
390 
391  /* the CIC deconvolution kernel is
392  *
393  * sinc_unnormed(k_x L / 2 Nmesh) ** 2
394  *
395  * k_x = kpos * 2pi / L
396  *
397  * */
398  int k;
399  for(k = 0; k < 3; k ++) {
400  double tmp = (kpos[k] * M_PI) / pm->Nmesh;
401  tmp = sinc_unnormed(tmp);
402  f *= 1. / (tmp * tmp);
403  }
404  /*
405  * first decovolution is CIC in par->mesh
406  * second decovolution is correcting readout
407  * I don't understand the second yet!
408  * */
409  const double fac = pot_factor * smth * f * f;
410  Power * ps = pm->ps;
411 
412  /*Add neutrino power if desired*/
413  if(GravPM.CP->MassiveNuLinRespOn && k2 > 0) {
414  /* Change the units of k to match those of logkk*/
415  double logk2 = log(sqrt(k2) * 2 * M_PI / ps->BoxSize_in_MPC);
416  /* Floating point roundoff and the binning means there may be a mode just beyond the box size.*/
417  if(logk2 < ps->logknu[0] && logk2 > ps->logknu[0]-log(2) )
418  logk2 = ps->logknu[0];
419  else if( logk2 > ps->logknu[ps->nonzero-1])
420  logk2 = ps->logknu[ps->nonzero-1];
421  /* Note get_neutrino_powerspec returns Omega_nu / (Omega0 -OmegaNu) * delta_nu / P_cdm^1/2, which is dimensionless.
422  * So below is: M_cdm * delta_cdm (1 + Omega_nu/(Omega0-OmegaNu) (delta_nu / delta_cdm))
423  * = M_cdm * (delta_cdm (Omega0 - OmegaNu)/Omega0 + Omega_nu/Omega0 delta_nu) * Omega0 / (Omega0-OmegaNu)
424  * = M_cdm * Omega0 / (Omega0-OmegaNu) * (delta_cdm (1 - f_nu) + f_nu delta_nu) )
425  * = M_cdm * Omega0 / (Omega0-OmegaNu) * delta_t
426  * = (M_cdm + M_nu) * delta_t
427  * This is correct for the forces, and gives the right power spectrum,
428  * once we multiply PowerSpectrum.Norm by (Omega0 / (Omega0 - OmegaNu))**2 */
429  const double nufac = 1 + ps->nu_prefac * gsl_interp_eval(ps->nu_spline,ps->logknu,
430  ps->delta_nu_ratio,logk2,ps->nu_acc);
431  value[0][0] *= nufac;
432  value[0][1] *= nufac;
433  }
434 
435  /*Compute the power spectrum*/
436  powerspectrum_add_mode(ps, k2, kpos, value, f, pm->Nmesh);
437  if(k2 == 0) {
439  const double MtotbyMcdm = GravPM.CP->Omega0/(GravPM.CP->Omega0 - pow(GravPM.Time,3)*get_omega_nu_nopart(&(GravPM.CP->ONu), GravPM.Time));
440  ps->Norm *= MtotbyMcdm*MtotbyMcdm;
441  }
442  /* Remove zero mode corresponding to the mean.*/
443  value[0][0] = 0.0;
444  value[0][1] = 0.0;
445  return;
446  }
447 
448  value[0][0] *= fac;
449  value[0][1] *= fac;
450 }
451 
452 /* the transfer functions for force in fourier space applied to potential */
453 /* super lanzcos in CH6 P 122 Digital Filters by Richard W. Hamming */
454 static double diff_kernel(double w) {
455 /* order N = 1 */
456 /*
457  * This is the same as GADGET-2 but in fourier space:
458  * see gadget-2 paper and Hamming's book.
459  * c1 = 2 / 3, c2 = 1 / 12
460  * */
461  return 1 / 6.0 * (8 * sin (w) - sin (2 * w));
462 }
463 
464 /*This function decides if a particle is actively gravitating; tracers are not.*/
465 static int hybrid_nu_gravpm_is_active(int i) {
466  if (P[i].Type == GravPM.FastParticleType)
467  return 0;
468  else
469  return 1;
470 }
471 
472 static void force_transfer(PetaPM * pm, int k, pfft_complex * value) {
473  double tmp0;
474  double tmp1;
475  /*
476  * negative sign is from force_x = - Del_x pot
477  *
478  * filter is i K(w)
479  * */
480  double fac = -1 * diff_kernel (k * (2 * M_PI / pm->Nmesh)) * (pm->Nmesh / pm->BoxSize);
481  tmp0 = - value[0][1] * fac;
482  tmp1 = value[0][0] * fac;
483  value[0][0] = tmp0;
484  value[0][1] = tmp1;
485 }
486 static void force_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
487  force_transfer(pm, kpos[0], value);
488 }
489 static void force_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
490  force_transfer(pm, kpos[1], value);
491 }
492 static void force_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
493  force_transfer(pm, kpos[2], value);
494 }
495 static void readout_potential(PetaPM * pm, int i, double * mesh, double weight) {
496  P[i].Potential += weight * mesh[0];
497 }
498 static void readout_force_x(PetaPM * pm, int i, double * mesh, double weight) {
499  P[i].GravPM[0] += weight * mesh[0];
500 }
501 static void readout_force_y(PetaPM * pm, int i, double * mesh, double weight) {
502  P[i].GravPM[1] += weight * mesh[0];
503 }
504 static void readout_force_z(PetaPM * pm, int i, double * mesh, double weight) {
505  P[i].GravPM[2] += weight * mesh[0];
506 }
double GrowthFactor(Cosmology *CP, double astart, double aend)
Definition: cosmology.c:82
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
int force_tree_allocated(const ForceTree *tree)
Definition: forcetree.c:134
void force_tree_free(ForceTree *tree)
Definition: forcetree.c:1409
int force_get_father(int no, const ForceTree *tree)
Definition: forcetree.c:905
#define NODE_NODE_TYPE
Definition: forcetree.h:16
#define PARTICLE_NODE_TYPE
Definition: forcetree.h:15
#define PSEUDO_NODE_TYPE
Definition: forcetree.h:17
static double pot_factor
Definition: glass.c:215
static PetaPMGlobalFunctions global_functions
Definition: glass.c:33
static double diff_kernel(double w)
Definition: gravpm.c:454
static void readout_potential(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:495
static void compute_neutrino_power(PetaPM *pm)
Definition: gravpm.c:304
static void force_x_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:486
static void readout_force_z(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:504
static void readout_force_x(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:498
void powerspectrum_add_mode(Power *PowerSpectrum, const int64_t k2, const int kpos[3], pfft_complex *const value, const double invwindow, double Nmesh)
Definition: gravpm.c:327
static int pm_mark_region_for_node(int startno, int rid, int *RegionInd, const ForceTree *tt)
Definition: gravpm.c:209
static void force_z_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:492
static void force_y_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:489
static int hybrid_nu_gravpm_is_active(int i)
Definition: gravpm.c:465
static void readout_force_y(PetaPM *pm, int i, double *mesh, double weight)
Definition: gravpm.c:501
static PetaPMRegion * _prepare(PetaPM *pm, PetaPMParticleStruct *pstruct, void *userdata, int *Nregions)
Definition: gravpm.c:117
static double sinc_unnormed(double x)
Definition: gravpm.c:291
static void potential_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:380
static struct gravpm_params GravPM
void gravpm_force(PetaPM *pm, ForceTree *tree, Cosmology *CP, double Time, double UnitLength_in_cm, const char *PowerOutputDir, double TimeIC, int FastParticleType)
Definition: gravpm.c:62
void measure_power_spectrum(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: gravpm.c:361
static PetaPMFunctions functions[]
Definition: gravpm.c:32
static void force_transfer(PetaPM *pm, int k, pfft_complex *value)
Definition: gravpm.c:472
static void convert_node_to_region(PetaPM *pm, PetaPMRegion *r, struct NODE *Nodes)
Definition: gravpm.c:255
void gravpm_init_periodic(PetaPM *pm, double BoxSize, double Asmth, int Nmesh, double G)
Definition: gravpm.c:53
#define mymalloc2(name, size)
Definition: mymalloc.h:16
void delta_nu_from_power(struct _powerspectrum *PowerSpectrum, Cosmology *CP, const double Time, const double TimeIC)
void powerspectrum_nu_save(struct _powerspectrum *PowerSpectrum, const char *OutputDir, const char *filename, const double Time)
double particle_nu_fraction(const _hybrid_nu *const hybnu, const double a, const int i)
double get_omega_nu_nopart(const _omega_nu *const omnu, const double a)
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
void petapm_init(PetaPM *pm, double BoxSize, double Asmth, int Nmesh, double G, MPI_Comm comm)
Definition: petapm.c:94
void petapm_region_init_strides(PetaPMRegion *region)
Definition: petapm.c:813
void petapm_force(PetaPM *pm, petapm_prepare_func prepare, PetaPMGlobalFunctions *global_functions, PetaPMFunctions *functions, PetaPMParticleStruct *pstruct, void *userdata)
Definition: petapm.c:353
static Cosmology * CP
Definition: power.c:27
static double UnitLength_in_cm
Definition: power.c:26
void powerspectrum_save(Power *ps, const char *OutputDir, const char *filename, const double Time, const double D1)
Definition: powerspectrum.c:92
void powerspectrum_free(Power *ps)
Definition: powerspectrum.c:44
void powerspectrum_sum(Power *ps)
Definition: powerspectrum.c:54
void powerspectrum_zero(Power *ps)
Definition: powerspectrum.c:35
void powerspectrum_alloc(Power *ps, const int nbins, const int nthreads, const int MassiveNuLinResp, const double BoxSize_in_cm)
Definition: powerspectrum.c:16
int HybridNeutrinosOn
Definition: cosmology.h:28
double Omega0
Definition: cosmology.h:10
int MassiveNuLinRespOn
Definition: cosmology.h:26
_omega_nu ONu
Definition: cosmology.h:24
int NTopLeaves
Definition: forcetree.h:94
struct NODE * Nodes
Definition: forcetree.h:97
int firstnode
Definition: forcetree.h:84
Definition: forcetree.h:39
int sibling
Definition: forcetree.h:40
unsigned int DependsOnLocalMass
Definition: forcetree.h:48
MyFloat center[3]
Definition: forcetree.h:43
unsigned int ChildType
Definition: forcetree.h:49
MyFloat hmax
Definition: forcetree.h:57
unsigned int TopLevel
Definition: forcetree.h:47
struct NodeChild s
Definition: forcetree.h:66
unsigned int InternalTopLevel
Definition: forcetree.h:46
struct NODE::@8 f
MyFloat len
Definition: forcetree.h:42
int noccupied
Definition: forcetree.h:35
int suns[NMAXCHILD]
Definition: forcetree.h:32
void(* global_analysis)(PetaPM *pm)
Definition: petapm.h:103
petapm_transfer_func global_readout
Definition: petapm.h:102
int(* active)(int i)
Definition: petapm.h:85
Definition: petapm.h:62
int Nmesh
Definition: petapm.h:68
double G
Definition: petapm.h:71
double BoxSize
Definition: petapm.h:70
double Asmth
Definition: petapm.h:69
Power ps[1]
Definition: petapm.h:76
Definition: petapm.h:7
double center[3]
Definition: petapm.h:15
int numpart
Definition: petapm.h:17
ptrdiff_t size[3]
Definition: petapm.h:10
ptrdiff_t offset[3]
Definition: petapm.h:9
double len
Definition: petapm.h:16
int no
Definition: petapm.h:18
_hybrid_nu hybnu
gsl_interp_accel * nu_acc
Definition: powerspectrum.h:24
double * logknu
Definition: powerspectrum.h:20
double * delta_nu_ratio
Definition: powerspectrum.h:21
double * Power
Definition: powerspectrum.h:10
double BoxSize_in_MPC
Definition: powerspectrum.h:17
gsl_interp * nu_spline
Definition: powerspectrum.h:23
int64_t * Nmodes
Definition: powerspectrum.h:11
double TimeIC
Definition: gravpm.c:46
double UnitLength_in_cm
Definition: gravpm.c:49
int FastParticleType
Definition: gravpm.c:48
Cosmology * CP
Definition: gravpm.c:47
double Time
Definition: gravpm.c:45
static const double tt[NEXACT]
int ThisTask
Definition: test_exchange.c:23
static const double G
Definition: test_gravity.c:35
#define walltime_measure(name)
Definition: walltime.h:8