MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
zeldovich.c
Go to the documentation of this file.
1 #include <mpi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 /* do NOT use complex.h it breaks the code */
7 #include <pfft.h>
8 #include "allvars.h"
9 #include "proto.h"
10 #include "power.h"
11 /* Using fastpm's gaussian_fill for ngenic agreement. */
12 #include "pmesh.h"
13 
14 #include <libgadget/petapm.h>
15 #include <libgadget/walltime.h>
16 #include <libgadget/utils.h>
17 
18 #define MESH2K(i) petapm_mesh_to_k(i)
19 static void density_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
20 static void vel_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
21 static void vel_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
22 static void vel_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
23 static void disp_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
24 static void disp_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
25 static void disp_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value);
26 static void readout_density(PetaPM * pm, int i, double * mesh, double weight);
27 static void readout_vel_x(PetaPM * pm, int i, double * mesh, double weight);
28 static void readout_vel_y(PetaPM * pm, int i, double * mesh, double weight);
29 static void readout_vel_z(PetaPM * pm, int i, double * mesh, double weight);
30 static void readout_disp_x(PetaPM * pm, int i, double * mesh, double weight);
31 static void readout_disp_y(PetaPM * pm, int i, double * mesh, double weight);
32 static void readout_disp_z(PetaPM * pm, int i, double * mesh, double weight);
33 static void gaussian_fill(int Nmesh, PetaPMRegion * region, pfft_complex * rho_k, int UnitaryAmplitude, int InvertPhase, const int Seed);
34 
35 static inline double periodic_wrap(double x, const double BoxSize)
36 {
37  while(x >= BoxSize)
38  x -= BoxSize;
39 
40  while(x < 0)
41  x += BoxSize;
42 
43  return x;
44 }
45 
46 /* Watch out: only works for pencils along-z !*/
47 void
48 idgen_init(IDGenerator * idgen, PetaPM * pm, int Ngrid, double BoxSize)
49 {
50 
51  int * ThisTask2d = petapm_get_thistask2d(pm);
52  int * NTask2d = petapm_get_ntask2d(pm);
53  idgen->NumPart = 1;
54  int k;
55  for(k = 0; k < 2; k ++) {
56  idgen->offset[k] = (ThisTask2d[k]) * Ngrid / NTask2d[k];
57  idgen->size[k] = (ThisTask2d[k] + 1) * Ngrid / NTask2d[k];
58  idgen->size[k] -= idgen->offset[k];
59  idgen->NumPart *= idgen->size[k];
60  }
61  idgen->offset[2] = 0;
62  idgen->size[2] = Ngrid;
63  idgen->NumPart *= idgen->size[2];
64  idgen->Ngrid = Ngrid;
65  idgen->BoxSize = BoxSize;
66 }
67 
68 uint64_t
70 {
71  int i = index / (idgen->size[2] * idgen->size[1]) + idgen->offset[0];
72  int j = (index % (idgen->size[1] * idgen->size[2])) / idgen->size[2] + idgen->offset[1];
73  int k = (index % idgen->size[2]) + idgen->offset[2];
74  uint64_t id = ((uint64_t) i) * idgen->Ngrid * idgen->Ngrid + ((uint64_t)j) * idgen->Ngrid + k + 1;
75  return id;
76 }
77 
78 void
79 idgen_create_pos_from_index(IDGenerator * idgen, int index, double pos[3])
80 {
81  int x = index / (idgen->size[2] * idgen->size[1]) + idgen->offset[0];
82  int y = (index % (idgen->size[1] * idgen->size[2])) / idgen->size[2] + idgen->offset[1];
83  int z = (index % idgen->size[2]) + idgen->offset[2];
84 
85  pos[0] = x * idgen->BoxSize / idgen->Ngrid;
86  pos[1] = y * idgen->BoxSize / idgen->Ngrid;
87  pos[2] = z * idgen->BoxSize / idgen->Ngrid;
88 }
89 
90 int
91 setup_grid(IDGenerator * idgen, double shift, double mass, struct ic_part_data * ICP)
92 {
93  memset(ICP, 0, idgen->NumPart*sizeof(struct ic_part_data));
94 
95  int i;
96  #pragma omp parallel for
97  for(i = 0; i < idgen->NumPart; i ++) {
98  idgen_create_pos_from_index(idgen, i, &ICP[i].Pos[0]);
99  ICP[i].Pos[0] += shift;
100  ICP[i].Pos[1] += shift;
101  ICP[i].Pos[2] += shift;
102  ICP[i].Mass = mass;
103  }
104  return idgen->NumPart;
105 }
106 
107 struct ic_prep_data
108 {
109  struct ic_part_data * curICP;
110  int NumPart;
111 };
112 
113 static PetaPMRegion * makeregion(PetaPM * pm, PetaPMParticleStruct * pstruct, void * userdata, int * Nregions) {
114  PetaPMRegion * regions = (PetaPMRegion *) mymalloc2("Regions", sizeof(PetaPMRegion));
115  struct ic_prep_data * icprep = (struct ic_prep_data *) userdata;
116  int NumPart = icprep->NumPart;
117  struct ic_part_data * ICP = icprep->curICP;
118  int k;
119  int r = 0;
120  int i;
121  double min[3] = {pm->BoxSize, pm->BoxSize, pm->BoxSize};
122  double max[3] = {0, 0, 0.};
123 
124  for(i = 0; i < NumPart; i ++) {
125  for(k = 0; k < 3; k ++) {
126  if(min[k] > ICP[i].Pos[k])
127  min[k] = ICP[i].Pos[k];
128  if(max[k] < ICP[i].Pos[k])
129  max[k] = ICP[i].Pos[k];
130  }
131  }
132 
133  for(k = 0; k < 3; k ++) {
134  regions[r].offset[k] = floor(min[k] / pm->BoxSize * pm->Nmesh - 1);
135  regions[r].size[k] = ceil(max[k] / pm->BoxSize * pm->Nmesh + 2);
136  regions[r].size[k] -= regions[r].offset[k];
137  }
138 
139  /* setup the internal data structure of the region */
140  petapm_region_init_strides(&regions[r]);
141  *Nregions = 1;
142  return regions;
143 }
144 
145 /*Global to pass type to *_transfer functions*/
146 static enum TransferType ptype;
147 /*Global to pass the particle data to the readout functions*/
148 static struct ic_part_data * curICP;
149 
150 void displacement_fields(PetaPM * pm, enum TransferType Type, struct ic_part_data * dispICP, const int NumPart, Cosmology * CP, const struct genic_config GenicConfig) {
151 
152  /*MUST set this before doing force.*/
153  ptype = Type;
154  curICP = dispICP;
155  PetaPMParticleStruct pstruct = {
156  curICP,
157  sizeof(curICP[0]),
158  ((char*) &curICP[0].Pos[0]) - (char*) curICP,
159  ((char*) &curICP[0].Mass) - (char*) curICP,
160  NULL,
161  NULL,
162  NumPart,
163  };
164 
165  int i;
166  #pragma omp parallel for
167  for(i = 0; i < NumPart; i++)
168  {
169  memset(&curICP[i].Disp[0], 0, sizeof(curICP[i].Disp));
170  memset(&curICP[i].Vel[0], 0, sizeof(curICP[i].Vel));
171  curICP[i].Density = 0;
172  }
173 
174 
175  /* This reads out the displacements into P.Disp and the velocities into P.Vel.
176  * Disp is used to avoid changing the particle positions mid-way through.
177  * Note that for the velocities we do NOT just use the velocity transfer functions.
178  * The reason is because of the gauge: velocity transfer is in synchronous gauge for CLASS,
179  * newtonian gauge for CAMB. But we want N-body gauge, which we get by taking the time derivative
180  * of the synchronous gauge density perturbations. See arxiv:1505.04756*/
182  {"Density", density_transfer, readout_density},
183  {"DispX", disp_x_transfer, readout_disp_x},
184  {"DispY", disp_y_transfer, readout_disp_y},
185  {"DispZ", disp_z_transfer, readout_disp_z},
186  {"VelX", vel_x_transfer, readout_vel_x},
187  {"VelY", vel_y_transfer, readout_vel_y},
188  {"VelZ", vel_z_transfer, readout_vel_z},
189  {NULL, NULL, NULL },
190  };
191 
192  /*Set up the velocity pre-factors*/
193  const double hubble_a = hubble_function(CP, GenicConfig.TimeIC);
194 
195  double vel_prefac = GenicConfig.TimeIC * hubble_a;
196 
197  if(GenicConfig.UsePeculiarVelocity) {
198  /* already for peculiar velocity */
199  message(0, "Producing Peculiar Velocity in the output.\n");
200  } else {
201  vel_prefac /= sqrt(GenicConfig.TimeIC); /* converts to Gadget velocity */
202  }
203 
204  if(!GenicConfig.PowerP.ScaleDepVelocity) {
205  vel_prefac *= F_Omega(CP, GenicConfig.TimeIC);
206  /* If different transfer functions are disabled, we can copy displacements to velocities
207  * and we don't need the extra transfers.*/
208  functions[4].name = NULL;
209  }
210 
211  int Nregions;
212  struct ic_prep_data icprep = {dispICP, NumPart};
213  PetaPMRegion * regions = petapm_force_init(pm,
214  makeregion,
215  &pstruct,
216  &Nregions,
217  &icprep);
218 
219  /*This allocates the memory*/
220  pfft_complex * rho_k = petapm_alloc_rhok(pm);
221 
223  rho_k, GenicConfig.UnitaryAmplitude, GenicConfig.InvertPhase, GenicConfig.Seed);
224 
225  petapm_force_c2r(pm, rho_k, regions, Nregions, functions);
226 
227  myfree(rho_k);
228  myfree(regions);
230 
231  double maxdisp = 0, maxvel = 0;
232 
233  #pragma omp parallel for reduction(max:maxdisp, maxvel)
234  for(i = 0; i < NumPart; i++)
235  {
236  int k;
237  double absv = 0;
238  for(k = 0; k < 3; k++)
239  {
240  double dis = curICP[i].Disp[k];
241  if(dis > maxdisp)
242  maxdisp = dis;
243  /*Copy displacements to positions.*/
244  curICP[i].Pos[k] += curICP[i].Disp[k];
245  /*Copy displacements to velocities if not done already*/
246  if(!GenicConfig.PowerP.ScaleDepVelocity)
247  curICP[i].Vel[k] = curICP[i].Disp[k];
248  curICP[i].Vel[k] *= vel_prefac;
249  absv += curICP[i].Vel[k] * curICP[i].Vel[k];
250  curICP[i].Pos[k] = periodic_wrap(curICP[i].Pos[k], pm->BoxSize);
251  }
252  if(absv > maxvel)
253  maxvel = absv;
254  }
255  MPI_Allreduce(MPI_IN_PLACE, &maxdisp, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
256  message(0, "Type = %d max disp = %g in units of cell sep %g \n", ptype, maxdisp, maxdisp / (pm->BoxSize / pm->Nmesh) );
257 
258  MPI_Allreduce(MPI_IN_PLACE, &maxvel, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
259  message(0, "Max vel=%g km/s, vel_prefac= %g hubble_a=%g fom=%g \n", sqrt(maxvel), vel_prefac, hubble_a, F_Omega(CP, GenicConfig.TimeIC));
260 
261  walltime_measure("/Disp/Finalize");
262  MPIU_Barrier(MPI_COMM_WORLD);
263 }
264 
265 /********************
266  * transfer functions for
267  *
268  * potential from mass in cell
269  *
270  * and
271  *
272  * force from potential
273  *
274  *********************/
275 
276 static void density_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
277  if(k2) {
278  /* density is smoothed in k space by a gaussian kernel of 1 mesh grid */
279  double r2 = 1.0 / pm->Nmesh;
280  r2 *= r2;
281  double fac = exp(- k2 * r2);
282 
283  double kmag = sqrt(k2) * 2 * M_PI / pm->BoxSize;
284  fac *= DeltaSpec(kmag, ptype) / sqrt(pm->BoxSize * pm->BoxSize * pm->BoxSize);
285 
286  value[0][0] *= fac;
287  value[0][1] *= fac;
288  }
289 }
290 
291 static void disp_transfer(PetaPM * pm, int64_t k2, int kaxis, pfft_complex * value, int include_growth) {
292  if(k2) {
293  double fac = 1./ (2 * M_PI) / sqrt(pm->BoxSize) * kaxis / k2;
294  /*
295  We avoid high precision kernels to maintain compatibility with N-GenIC.
296  The following formular shall cross check with fac in the limit of
297  native diff_kernel (disp_y, disp_z shall match too!)
298 
299  double fac1 = (2 * M_PI) / pm->BoxSize;
300  double fac = diff_kernel(kaxis * (2 * M_PI / pm->Nmesh)) * (pm->Nmesh / pm->BoxSize) / (
301  k2 * fac1 * fac1);
302  */
303  double kmag = sqrt(k2) * 2 * M_PI / pm->BoxSize;
304  /*Multiply by derivative of scale-dependent growth function*/
305  if(include_growth)
306  fac *= dlogGrowth(kmag, ptype);
307  else
308  fac *= DeltaSpec(kmag, ptype);
309  double tmp = value[0][0];
310  value[0][0] = - value[0][1] * fac;
311  value[0][1] = tmp * fac;
312  }
313 }
314 
315 static void vel_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
316  disp_transfer(pm, k2, kpos[0], value, 1);
317 }
318 static void vel_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
319  disp_transfer(pm, k2, kpos[1], value, 1);
320 }
321 static void vel_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
322  disp_transfer(pm, k2, kpos[2], value, 1);
323 }
324 
325 static void disp_x_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
326  disp_transfer(pm, k2, kpos[0], value, 0);
327 }
328 static void disp_y_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
329  disp_transfer(pm, k2, kpos[1], value, 0);
330 }
331 static void disp_z_transfer(PetaPM * pm, int64_t k2, int kpos[3], pfft_complex * value) {
332  disp_transfer(pm, k2, kpos[2], value, 0);
333 }
334 
335 /**************
336  * functions iterating over particle / mesh pairs
337  ***************/
338 static void readout_density(PetaPM * pm, int i, double * mesh, double weight) {
339  curICP[i].Density += weight * mesh[0];
340 }
341 static void readout_vel_x(PetaPM * pm, int i, double * mesh, double weight) {
342  curICP[i].Vel[0] += weight * mesh[0];
343 }
344 static void readout_vel_y(PetaPM * pm, int i, double * mesh, double weight) {
345  curICP[i].Vel[1] += weight * mesh[0];
346 }
347 static void readout_vel_z(PetaPM * pm, int i, double * mesh, double weight) {
348  curICP[i].Vel[2] += weight * mesh[0];
349 }
350 
351 static void readout_disp_x(PetaPM * pm, int i, double * mesh, double weight) {
352  curICP[i].Disp[0] += weight * mesh[0];
353 }
354 static void readout_disp_y(PetaPM * pm, int i, double * mesh, double weight) {
355  curICP[i].Disp[1] += weight * mesh[0];
356 }
357 static void readout_disp_z(PetaPM * pm, int i, double * mesh, double weight) {
358  curICP[i].Disp[2] += weight * mesh[0];
359 }
360 
361 static void
362 gaussian_fill(int Nmesh, PetaPMRegion * region, pfft_complex * rho_k, int setUnitaryAmplitude, int setInvertPhase, const int Seed)
363 {
364  /* fastpm deals with strides properly; petapm not. So we translate it here. */
365  PMDesc pm[1];
366  int d;
367  for (d = 0; d < 3; d ++) {
368  pm->Nmesh[d] = Nmesh;
369  }
370 
371  pm->ORegion.start[0] = region->offset[2];
372  pm->ORegion.size[0] = region->size[2];
373  pm->ORegion.strides[0] = region->strides[2];
374  pm->ORegion.start[1] = region->offset[0];
375  pm->ORegion.size[1] = region->size[0];
376  pm->ORegion.strides[1] = region->strides[0];
377  pm->ORegion.start[2] = region->offset[1];
378  pm->ORegion.size[2] = region->size[1];
379  pm->ORegion.strides[2] = region->strides[1];
380 
381  pm->ORegion.total = region->totalsize;
382  pmic_fill_gaussian_gadget(pm, (double*) rho_k, Seed, setUnitaryAmplitude, setInvertPhase);
383 
384 #if 0
385  /* dump the gaussian field for debugging
386  *
387  * the z directioin is in axis 1.
388  *
389  * */
390  FILE * rhokf = fopen("rhok", "w");
391  printf("strides %td %td %td\n",
392  pm->ORegion.strides[0],
393  pm->ORegion.strides[1],
394  pm->ORegion.strides[2]);
395  printf("size %td %td %td\n",
396  pm->ORegion.size[0],
397  pm->ORegion.size[1],
398  pm->ORegion.size[2]);
399  printf("offset %td %td %td\n",
400  pm->ORegion.start[0],
401  pm->ORegion.start[1],
402  pm->ORegion.start[2]);
403  fwrite(rho_k, sizeof(double) * region->totalsize, 1, rhokf);
404  fclose(rhokf);
405 #endif
406 }
double hubble_function(const Cosmology *CP, double a)
Definition: cosmology.c:58
double F_Omega(Cosmology *CP, double a)
Definition: cosmology.c:148
void message(int where, const char *fmt,...)
Definition: endrun.c:175
static PetaPMFunctions functions[]
Definition: gravpm.c:32
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
void petapm_force_finish(PetaPM *pm)
Definition: petapm.c:348
int * petapm_get_ntask2d(PetaPM *pm)
Definition: petapm.c:77
void petapm_region_init_strides(PetaPMRegion *region)
Definition: petapm.c:813
void petapm_force_c2r(PetaPM *pm, pfft_complex *rho_k, PetaPMRegion *regions, const int Nregions, PetaPMFunctions *functions)
Definition: petapm.c:317
pfft_complex * petapm_alloc_rhok(PetaPM *pm)
Definition: petapm.c:50
PetaPMRegion * petapm_get_fourier_region(PetaPM *pm)
Definition: petapm.c:64
PetaPMRegion * petapm_force_init(PetaPM *pm, petapm_prepare_func prepare, PetaPMParticleStruct *pstruct, int *Nregions, void *userdata)
Definition: petapm.c:251
int * petapm_get_thistask2d(PetaPM *pm)
Definition: petapm.c:74
static void pmic_fill_gaussian_gadget(PMDesc *pm, double *delta_k, int seed, int setUnitaryAmplitude, int setInvertPhase)
Definition: pmesh.h:65
double DeltaSpec(double k, enum TransferType Type)
Definition: power.c:52
double dlogGrowth(double kmag, enum TransferType Type)
Definition: power.c:101
static Cosmology * CP
Definition: power.c:27
TransferType
Definition: power.h:41
int Ngrid
Definition: proto.h:12
double BoxSize
Definition: proto.h:13
int size[3]
Definition: proto.h:10
int NumPart
Definition: proto.h:14
int offset[3]
Definition: proto.h:11
Definition: pmesh.h:11
struct PMDesc::@16 ORegion
ptrdiff_t start[3]
Definition: pmesh.h:13
ptrdiff_t size[3]
Definition: pmesh.h:14
int Nmesh[3]
Definition: pmesh.h:18
ptrdiff_t total
Definition: pmesh.h:16
ptrdiff_t strides[3]
Definition: pmesh.h:15
const char * name
Definition: petapm.h:94
Definition: petapm.h:62
int Nmesh
Definition: petapm.h:68
double BoxSize
Definition: petapm.h:70
Definition: petapm.h:7
size_t totalsize
Definition: petapm.h:12
ptrdiff_t size[3]
Definition: petapm.h:10
ptrdiff_t offset[3]
Definition: petapm.h:9
ptrdiff_t strides[3]
Definition: petapm.h:11
int UnitaryAmplitude
Definition: allvars.h:23
struct power_params PowerP
Definition: allvars.h:34
int Seed
Definition: allvars.h:22
int InvertPhase
Definition: allvars.h:24
int UsePeculiarVelocity
Definition: allvars.h:39
double TimeIC
Definition: allvars.h:38
float Mass
Definition: allvars.h:14
float Vel[3]
Definition: allvars.h:11
double Pos[3]
Definition: allvars.h:10
float Density
Definition: allvars.h:13
float Disp[3]
Definition: allvars.h:12
struct ic_part_data * curICP
Definition: glass.c:173
int NumPart
Definition: glass.c:174
int ScaleDepVelocity
Definition: power.h:11
#define MPIU_Barrier(comm)
Definition: system.h:103
#define walltime_measure(name)
Definition: walltime.h:8
static double periodic_wrap(double x, const double BoxSize)
Definition: zeldovich.c:35
static PetaPMRegion * makeregion(PetaPM *pm, PetaPMParticleStruct *pstruct, void *userdata, int *Nregions)
Definition: zeldovich.c:113
static void readout_density(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:338
static void readout_vel_z(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:347
void idgen_create_pos_from_index(IDGenerator *idgen, int index, double pos[3])
Definition: zeldovich.c:79
static void readout_disp_y(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:354
static void gaussian_fill(int Nmesh, PetaPMRegion *region, pfft_complex *rho_k, int UnitaryAmplitude, int InvertPhase, const int Seed)
Definition: zeldovich.c:362
static void vel_y_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:318
static void readout_vel_y(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:344
static enum TransferType ptype
Definition: zeldovich.c:146
int setup_grid(IDGenerator *idgen, double shift, double mass, struct ic_part_data *ICP)
Definition: zeldovich.c:91
static void readout_vel_x(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:341
static void disp_x_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:325
static void vel_x_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:315
static void readout_disp_z(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:357
void idgen_init(IDGenerator *idgen, PetaPM *pm, int Ngrid, double BoxSize)
Definition: zeldovich.c:48
static void density_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:276
void displacement_fields(PetaPM *pm, enum TransferType Type, struct ic_part_data *dispICP, const int NumPart, Cosmology *CP, const struct genic_config GenicConfig)
Definition: zeldovich.c:150
static void disp_transfer(PetaPM *pm, int64_t k2, int kaxis, pfft_complex *value, int include_growth)
Definition: zeldovich.c:291
static void disp_y_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:328
static void vel_z_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:321
static void readout_disp_x(PetaPM *pm, int i, double *mesh, double weight)
Definition: zeldovich.c:351
static struct ic_part_data * curICP
Definition: zeldovich.c:148
uint64_t idgen_create_id_from_index(IDGenerator *idgen, int index)
Definition: zeldovich.c:69
static void disp_z_transfer(PetaPM *pm, int64_t k2, int kpos[3], pfft_complex *value)
Definition: zeldovich.c:331