MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
petaio.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 #include <string.h>
7 #include <stdarg.h>
8 #include <omp.h>
9 
10 #include <bigfile-mpi.h>
11 
12 #include "sfr_eff.h"
13 #include "cooling.h"
14 #include "timestep.h"
15 
16 #include "petaio.h"
17 #include "slotsmanager.h"
18 #include "hydra.h"
19 #include "density.h"
20 #include "partmanager.h"
21 #include "config.h"
22 #include "neutrinos_lra.h"
23 
24 #include "utils.h"
25 /************
26  *
27  * The IO api , intented to replace io.c and read_ic.c
28  * currently we have a function to register the blocks and enumerate the blocks
29  *
30  */
31 static struct petaio_params {
32  size_t BytesPerFile; /* Number of bytes per physical file; this decides how many files bigfile creates each block */
33  int WritersPerFile; /* Number of concurrent writers per file; this decides number of writers */
34  int NumWriters; /* Number of concurrent writers, this caps number of writers */
35  int MinNumWriters; /* Min Number of concurrent writers, this caps number of writers */
36  int EnableAggregatedIO; /* Enable aggregated IO policy for small files.*/
37  size_t AggregatedIOThreshold; /* bytes per writer above which to use non-aggregated IO (avoid OOM)*/
38  /* Changes the comoving factors of the snapshot outputs. Set in the ICs.
39  * If UsePeculiarVelocity = 1 then snapshots save to the velocity field the physical peculiar velocity, v = a dx/dt (where x is comoving distance).
40  * If UsePeculiarVelocity = 0 then the velocity field is a * v = a^2 dx/dt in snapshots
41  * and v / sqrt(a) = sqrt(a) dx/dt in the ICs. Note that snapshots never match Gadget-2, which
42  * saves physical peculiar velocity / sqrt(a) in both ICs and snapshots. */
46  int OutputTimebins; /* Flag whether to save the timebins*/
47  char SnapshotFileBase[100]; /* Snapshots are written to OutputDir/SnapshotFileBase_$n*/
48  char InitCondFile[100]; /* Path to read ICs from is InitCondFile */
49 
50 } IO;
51 
52 /* Struct to store constant information written to each snapshot header*/
53 static struct header_data Header;
54 
55 /*Set the IO parameters*/
56 void
58 {
59  int ThisTask;
60  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
61  if(ThisTask == 0) {
62  IO.BytesPerFile = param_get_int(ps, "BytesPerFile");
63  IO.UsePeculiarVelocity = 0; /* Will be set by the Initial Condition File */
64  IO.NumWriters = param_get_int(ps, "NumWriters");
65  IO.MinNumWriters = param_get_int(ps, "MinNumWriters");
66  IO.WritersPerFile = param_get_int(ps, "WritersPerFile");
67  IO.AggregatedIOThreshold = param_get_int(ps, "AggregatedIOThreshold");
68  IO.EnableAggregatedIO = param_get_int(ps, "EnableAggregatedIO");
69  IO.OutputPotential = param_get_int(ps, "OutputPotential");
70  IO.OutputTimebins = param_get_int(ps, "OutputTimebins");
71  IO.OutputHeliumFractions = param_get_int(ps, "OutputHeliumFractions");
72  param_get_string2(ps, "SnapshotFileBase", IO.SnapshotFileBase, sizeof(IO.SnapshotFileBase));
73  param_get_string2(ps, "InitCondFile", IO.InitCondFile, sizeof(IO.InitCondFile));
74 
75  }
76  MPI_Bcast(&IO, sizeof(struct petaio_params), MPI_BYTE, 0, MPI_COMM_WORLD);
77 }
78 
80 {
81  return IO.UsePeculiarVelocity;
82 }
83 
84 static void petaio_write_header(BigFile * bf, const double atime, const int64_t * NTotal, const Cosmology * CP, const struct header_data * data);
85 static void petaio_read_header_internal(BigFile * bf, Cosmology * CP, struct header_data * data);
86 
87 /* these are only used in reading in */
88 void petaio_init(void) {
89  /* Smaller files will do aggregated IO.*/
91  message(0, "Aggregated IO is enabled\n");
92  big_file_mpi_set_aggregated_threshold(IO.AggregatedIOThreshold);
93  } else {
94  message(0, "Aggregated IO is disabled.\n");
95  big_file_mpi_set_aggregated_threshold(0);
96  }
97  if(IO.NumWriters == 0)
98  MPI_Comm_size(MPI_COMM_WORLD, &IO.NumWriters);
99 }
100 
101 /* Build a list of the first particle of each type on the current processor.
102  * This assumes that all particles are sorted!*/
112 void
113 petaio_build_selection(int * selection,
114  int * ptype_offset,
115  int * ptype_count,
116  const struct particle_data * Parts,
117  const int NumPart,
118  int (*select_func)(int i, const struct particle_data * Parts)
119  )
120 {
121  int i;
122  ptype_offset[0] = 0;
123  ptype_count[0] = 0;
124 
125  for(i = 0; i < NumPart; i ++) {
126  if(P[i].IsGarbage)
127  continue;
128  if((select_func == NULL) || (select_func(i, Parts) != 0)) {
129  int ptype = Parts[i].Type;
130  ptype_count[ptype] ++;
131  }
132  }
133  for(i = 1; i < 6; i ++) {
134  ptype_offset[i] = ptype_offset[i-1] + ptype_count[i-1];
135  ptype_count[i-1] = 0;
136  }
137 
138  ptype_count[5] = 0;
139  for(i = 0; i < NumPart; i ++) {
140  int ptype = Parts[i].Type;
141  if(P[i].IsGarbage)
142  continue;
143  if((select_func == NULL) || (select_func(i, Parts) != 0)) {
144  selection[ptype_offset[ptype] + ptype_count[ptype]] = i;
145  ptype_count[ptype]++;
146  }
147  }
148 }
149 
150 void
151 petaio_save_snapshot(const char * fname, struct IOTable * IOTable, int verbose, const double atime, const Cosmology * CP)
152 {
153  message(0, "saving snapshot into %s\n", fname);
154 
155  BigFile bf = {0};
156  if(0 != big_file_mpi_create(&bf, fname, MPI_COMM_WORLD)) {
157  endrun(0, "Failed to create snapshot at %s:%s\n", fname,
158  big_file_get_error_message());
159  }
160 
161  int ptype_offset[6]={0};
162  int ptype_count[6]={0};
163  int64_t NTotal[6]={0};
164 
165  int * selection = (int *) mymalloc("Selection", sizeof(int) * PartManager->NumPart);
166 
167  petaio_build_selection(selection, ptype_offset, ptype_count, P, PartManager->NumPart, NULL);
168 
169  sumup_large_ints(6, ptype_count, NTotal);
170 
171  struct conversions conv = {0};
172  conv.atime = atime;
173  conv.hubble = hubble_function(CP, atime);
174 
175  petaio_write_header(&bf, atime, NTotal, CP, &Header);
176 
177  int i;
178  for(i = 0; i < IOTable->used; i ++) {
179  /* only process the particle blocks */
180  char blockname[128];
181  int ptype = IOTable->ent[i].ptype;
182  BigArray array = {0};
183  /*This exclude FOF blocks*/
184  if(!(ptype < 6 && ptype >= 0)) {
185  continue;
186  }
187  sprintf(blockname, "%d/%s", ptype, IOTable->ent[i].name);
188  petaio_build_buffer(&array, &IOTable->ent[i], selection + ptype_offset[ptype], ptype_count[ptype], P, SlotsManager, &conv);
189  petaio_save_block(&bf, blockname, &array, verbose);
190  petaio_destroy_buffer(&array);
191  }
192 
193  if(CP->MassiveNuLinRespOn) {
194  int ThisTask;
195  MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
197  }
198  if(0 != big_file_mpi_close(&bf, MPI_COMM_WORLD)){
199  endrun(0, "Failed to close snapshot at %s:%s\n", fname,
200  big_file_get_error_message());
201  }
202 
203  myfree(selection);
204 }
205 
206 char *
207 petaio_get_snapshot_fname(int num, const char * OutputDir)
208 {
209  char * fname;
210  if(num == -1) {
211  fname = fastpm_strdup_printf("%s", IO.InitCondFile);
212  } else {
213  fname = fastpm_strdup_printf("%s/%s_%03d", OutputDir, IO.SnapshotFileBase, num);
214  }
215  return fname;
216 }
217 
218 struct header_data
219  petaio_read_header(int num, const char * OutputDir, Cosmology * CP)
220 {
221  BigFile bf = {0};
222 
223  char * fname = petaio_get_snapshot_fname(num, OutputDir);
224  message(0, "Probing Header of snapshot file: %s\n", fname);
225 
226  if(0 != big_file_mpi_open(&bf, fname, MPI_COMM_WORLD)) {
227  endrun(0, "Failed to open snapshot at %s:%s\n", fname,
228  big_file_get_error_message());
229  }
230 
231  struct header_data head;
232  petaio_read_header_internal(&bf, CP, &head);
233  head.neutrinonk = -1;
234  /* Try to read the neutrino header data from the snapshot.
235  * If this fails then neutrinonk will be zero.*/
236  if(num >= 0) {
237  BigBlock bn;
238  if(0 == big_file_mpi_open_block(&bf, &bn, "Neutrino", MPI_COMM_WORLD)) {
239  if(0 != big_block_get_attr(&bn, "Nkval", &head.neutrinonk, "u8", 1))
240  endrun(0, "Failed to read attr: %s\n", big_file_get_error_message());
241  big_block_mpi_close(&bn, MPI_COMM_WORLD);
242  }
243  }
244 
245  if(0 != big_file_mpi_close(&bf, MPI_COMM_WORLD)) {
246  endrun(0, "Failed to close snapshot at %s:%s\n", fname,
247  big_file_get_error_message());
248  }
249  myfree(fname);
250  Header = head;
251  return head;
252 }
253 
254 void
255 petaio_read_snapshot(int num, const char * OutputDir, Cosmology * CP, struct header_data * header, struct part_manager_type * PartManager, struct slots_manager_type * SlotsManager, MPI_Comm Comm)
256 {
257  char * fname = petaio_get_snapshot_fname(num, OutputDir);
258  int i;
259  const int ic = (num == -1);
260  BigFile bf = {0};
261  message(0, "Reading snapshot %s\n", fname);
262 
263  if(0 != big_file_mpi_open(&bf, fname, Comm)) {
264  endrun(0, "Failed to open snapshot at %s:%s\n", fname,
265  big_file_get_error_message());
266  }
267 
268  /*Read neutrinos from the snapshot if necessary*/
269  if(CP->MassiveNuLinRespOn) {
270  int ThisTask;
271  MPI_Comm_rank(Comm, &ThisTask);
272  /*Read the neutrino transfer function from the ICs: init_neutrinos_lra should have been called before this!*/
273  if(ic)
275  else
277  }
278 
279  struct conversions conv = {0};
280  conv.atime = header->TimeSnapshot;
281  conv.hubble = hubble_function(CP, header->TimeSnapshot);
282 
283  struct IOTable IOTable[1] = {0};
284  /* Always try to read the metal tables.
285  * This lets us turn it off for a short period and then re-enable it.
286  * Note the metal fields are non-fatal so this does not break resuming without metals.*/
288 
289  for(i = 0; i < IOTable->used; i ++) {
290  /* only process the particle blocks */
291  char blockname[128];
292  int ptype = IOTable->ent[i].ptype;
293  BigArray array = {0};
294  if(!(ptype < 6 && ptype >= 0)) {
295  continue;
296  }
297  if(header->NTotal[ptype] == 0) continue;
298  if(ic) {
299  /* for IC read in only three blocks */
300  int keep = 0;
301  keep |= (0 == strcmp(IOTable->ent[i].name, "Position"));
302  keep |= (0 == strcmp(IOTable->ent[i].name, "Velocity"));
303  keep |= (0 == strcmp(IOTable->ent[i].name, "ID"));
304  if (ptype == 5) {
305  keep |= (0 == strcmp(IOTable->ent[i].name, "Mass"));
306  keep |= (0 == strcmp(IOTable->ent[i].name, "BlackholeMass"));
307  keep |= (0 == strcmp(IOTable->ent[i].name, "MinPotPos"));
308  }
309  if(!keep) continue;
310  }
311  if(IOTable->ent[i].setter == NULL) {
312  /* FIXME: do not know how to read this block; assume the fucker is
313  * internally intialized; */
314  continue;
315  }
316  sprintf(blockname, "%d/%s", ptype, IOTable->ent[i].name);
317  petaio_alloc_buffer(&array, &IOTable->ent[i], header->NLocal[ptype]);
318  if(0 == petaio_read_block(&bf, blockname, &array, IOTable->ent[i].required))
320  petaio_destroy_buffer(&array);
321  }
323 
324  if(0 != big_file_mpi_close(&bf, Comm)) {
325  endrun(0, "Failed to close snapshot at %s:%s\n", fname,
326  big_file_get_error_message());
327  }
328  /* now we have IDs, set up the ID consistency between slots. */
330  myfree(fname);
331 
332  if(ic) {
333  /*
334  * IC doesn't have entropy or energy; always use the
335  * InitTemp in paramfile, then use init.c to convert to
336  * entropy.
337  * */
338  struct particle_data * parts = PartManager->Base;
339  int i;
340  /* touch up the mass -- IC files save mass in header */
341  #pragma omp parallel for
342  for(i = 0; i < PartManager->NumPart; i++)
343  {
344  parts[i].Mass = header->MassTable[parts[i].Type];
345  }
346 
347  if (!IO.UsePeculiarVelocity ) {
348  /* fixing the unit of velocity from Legacy GenIC IC */
349  #pragma omp parallel for
350  for(i = 0; i < PartManager->NumPart; i++) {
351  int k;
352  /* for GenIC's Gadget-1 snapshot Unit to Gadget-2 Internal velocity unit */
353  for(k = 0; k < 3; k++)
354  parts[i].Vel[k] *= sqrt(header->TimeSnapshot) * header->TimeSnapshot;
355  }
356  }
357  }
358 }
359 
360 /* write a header block */
361 static void petaio_write_header(BigFile * bf, const double atime, const int64_t * NTotal, const Cosmology * CP, const struct header_data * data) {
362  BigBlock bh;
363  if(0 != big_file_mpi_create_block(bf, &bh, "Header", NULL, 0, 0, 0, MPI_COMM_WORLD)) {
364  endrun(0, "Failed to create block at %s:%s\n", "Header",
365  big_file_get_error_message());
366  }
367 
368  /* conversion from peculiar velocity to RSD */
369  const double hubble = hubble_function(CP, atime);
370  double RSD = 1.0 / (atime * hubble);
371 
372  if(!IO.UsePeculiarVelocity) {
373  RSD /= atime; /* Conversion from internal velocity to RSD */
374  }
375 
376  int dk = GetDensityKernelType();
377  if(
378  (0 != big_block_set_attr(&bh, "TotNumPart", NTotal, "u8", 6)) ||
379  (0 != big_block_set_attr(&bh, "TotNumPartInit", &data->NTotalInit, "u8", 6)) ||
380  (0 != big_block_set_attr(&bh, "MassTable", &data->MassTable, "f8", 6)) ||
381  (0 != big_block_set_attr(&bh, "Time", &atime, "f8", 1)) ||
382  (0 != big_block_set_attr(&bh, "TimeIC", &data->TimeIC, "f8", 1)) ||
383  (0 != big_block_set_attr(&bh, "BoxSize", &data->BoxSize, "f8", 1)) ||
384  (0 != big_block_set_attr(&bh, "OmegaLambda", &CP->OmegaLambda, "f8", 1)) ||
385  (0 != big_block_set_attr(&bh, "RSDFactor", &RSD, "f8", 1)) ||
386  (0 != big_block_set_attr(&bh, "UsePeculiarVelocity", &IO.UsePeculiarVelocity, "i4", 1)) ||
387  (0 != big_block_set_attr(&bh, "Omega0", &CP->Omega0, "f8", 1)) ||
388  (0 != big_block_set_attr(&bh, "CMBTemperature", &CP->CMBTemperature, "f8", 1)) ||
389  (0 != big_block_set_attr(&bh, "OmegaBaryon", &CP->OmegaBaryon, "f8", 1)) ||
390  (0 != big_block_set_attr(&bh, "UnitLength_in_cm", &data->UnitLength_in_cm, "f8", 1)) ||
391  (0 != big_block_set_attr(&bh, "UnitMass_in_g", &data->UnitMass_in_g, "f8", 1)) ||
392  (0 != big_block_set_attr(&bh, "UnitVelocity_in_cm_per_s", &data->UnitVelocity_in_cm_per_s, "f8", 1)) ||
393  (0 != big_block_set_attr(&bh, "CodeVersion", GADGET_VERSION, "S1", strlen(GADGET_VERSION))) ||
394  (0 != big_block_set_attr(&bh, "CompilerSettings", GADGET_COMPILER_SETTINGS, "S1", strlen(GADGET_COMPILER_SETTINGS))) ||
395  (0 != big_block_set_attr(&bh, "DensityKernel", &dk, "i4", 1)) ||
396  (0 != big_block_set_attr(&bh, "HubbleParam", &CP->HubbleParam, "f8", 1)) ) {
397  endrun(0, "Failed to write attributes %s\n",
398  big_file_get_error_message());
399  }
400 
401  if(0 != big_block_mpi_close(&bh, MPI_COMM_WORLD)) {
402  endrun(0, "Failed to close block %s\n",
403  big_file_get_error_message());
404  }
405 }
406 static double
407 _get_attr_double(BigBlock * bh, const char * name, const double def)
408 {
409  double foo;
410  if(0 != big_block_get_attr(bh, name, &foo, "f8", 1)) {
411  foo = def;
412  }
413  return foo;
414 }
415 static int
416 _get_attr_int(BigBlock * bh, const char * name, const int def)
417 {
418  int foo;
419  if(0 != big_block_get_attr(bh, name, &foo, "i4", 1)) {
420  foo = def;
421  }
422  return foo;
423 }
424 
425 static void
427  BigBlock bh;
428  if(0 != big_file_mpi_open_block(bf, &bh, "Header", MPI_COMM_WORLD)) {
429  endrun(0, "Failed to create block at %s:%s\n", "Header",
430  big_file_get_error_message());
431  }
432  double Time = 0.;
433  if(
434  (0 != big_block_get_attr(&bh, "TotNumPart", Header->NTotal, "u8", 6)) ||
435  (0 != big_block_get_attr(&bh, "MassTable", Header->MassTable, "f8", 6)) ||
436  (0 != big_block_get_attr(&bh, "BoxSize", &Header->BoxSize, "f8", 1)) ||
437  (0 != big_block_get_attr(&bh, "Time", &Time, "f8", 1))
438  ) {
439  endrun(0, "Failed to read attr: %s\n",
440  big_file_get_error_message());
441  }
442 
443  Header->TimeSnapshot = Time;
444  if(0!= big_block_get_attr(&bh, "TimeIC", &Header->TimeIC, "f8", 1))
445  Header->TimeIC = Time;
446 
447  /* Set a reasonable MassTable entry for stars and BHs*/
448  if(Header->MassTable[4] == 0)
450  if(Header->MassTable[5] == 0)
451  Header->MassTable[5] = Header->MassTable[4];
452 
453  /* fall back to traditional MP-Gadget Units if not given in the snapshot file. */
454  Header->UnitVelocity_in_cm_per_s = _get_attr_double(&bh, "UnitVelocity_in_cm_per_s", 1e5); /* 1 km/sec */
455  Header->UnitLength_in_cm = _get_attr_double(&bh, "UnitLength_in_cm", 3.085678e21); /* 1.0 Kpc /h */
456  Header->UnitMass_in_g = _get_attr_double(&bh, "UnitMass_in_g", 1.989e43); /* 1e10 Msun/h */
457 
458  double OmegaBaryon = CP->OmegaBaryon;
459  double HubbleParam = CP->HubbleParam;
460  double OmegaLambda = CP->OmegaLambda;
461 
462  if(0 == big_block_get_attr(&bh, "OmegaBaryon", &CP->OmegaBaryon, "f8", 1) &&
463  OmegaBaryon > 0 && fabs(CP->OmegaBaryon - OmegaBaryon) > 1e-3)
464  message(0,"IC Header has Omega_b = %g but paramfile wants %g\n", CP->OmegaBaryon, OmegaBaryon);
465  if(0 == big_block_get_attr(&bh, "HubbleParam", &CP->HubbleParam, "f8", 1) &&
466  HubbleParam > 0 && fabs(CP->HubbleParam - HubbleParam) > 1e-3)
467  message(0,"IC Header has HubbleParam = %g but paramfile wants %g\n", CP->HubbleParam, HubbleParam);
468  if(0 == big_block_get_attr(&bh, "OmegaLambda", &CP->OmegaLambda, "f8", 1) &&
469  OmegaLambda > 0 && fabs(CP->OmegaLambda - OmegaLambda) > 1e-3)
470  message(0,"IC Header has Omega_L = %g but paramfile wants %g\n", CP->OmegaLambda, OmegaLambda);
471 
472  /* If UsePeculiarVelocity = 1 then snapshots save to the velocity field the physical peculiar velocity, v = a dx/dt (where x is comoving distance).
473  * If UsePeculiarVelocity = 0 then the velocity field is a * v = a^2 dx/dt in snapshots
474  * and v / sqrt(a) = sqrt(a) dx/dt in the ICs. Note that snapshots never match Gadget-2, which
475  * saves physical peculiar velocity / sqrt(a) in both ICs and snapshots. */
476  IO.UsePeculiarVelocity = _get_attr_int(&bh, "UsePeculiarVelocity", 0);
477 
478  if(0 != big_block_get_attr(&bh, "TotNumPartInit", Header->NTotalInit, "u8", 6)) {
479  int ptype;
480  for(ptype = 0; ptype < 6; ptype ++) {
482  }
483  }
484 
485  if(0 != big_block_mpi_close(&bh, MPI_COMM_WORLD)) {
486  endrun(0, "Failed to close block: %s\n",
487  big_file_get_error_message());
488  }
489 }
490 
491 void petaio_alloc_buffer(BigArray * array, IOTableEntry * ent, int64_t localsize) {
492  size_t dims[2];
493  ptrdiff_t strides[2];
494  int elsize = dtype_itemsize(ent->dtype);
495 
496  dims[0] = localsize;
497  dims[1] = ent->items;
498  strides[1] = elsize;
499  strides[0] = elsize * ent->items;
500  char * buffer = (char *) mymalloc("IOBUFFER", dims[0] * dims[1] * elsize);
501 
502  big_array_init(array, buffer, ent->dtype, 2, dims, strides);
503 }
504 
505 /* readout array into P struct with setters */
506 void petaio_readout_buffer(BigArray * array, IOTableEntry * ent, struct conversions * conv, struct part_manager_type * PartManager, struct slots_manager_type * SlotsManager) {
507  int i;
508  /* fill the buffer */
509  char * p = (char *) array->data;
510  for(i = 0; i < PartManager->NumPart; i ++) {
511  if(PartManager->Base[i].Type != ent->ptype) continue;
512  ent->setter(i, p, PartManager->Base, SlotsManager, conv);
513  p += array->strides[0];
514  }
515 }
516 /* build an IO buffer for block, based on selection
517  * only check P[ selection[i]]. If selection is NULL, just use P[i].
518  * NOTE: selected range should contain only one particle type!
519 */
520 void
521 petaio_build_buffer(BigArray * array, IOTableEntry * ent, const int * selection, const int NumSelection, struct particle_data * Parts, struct slots_manager_type * SlotsManager, struct conversions * conv)
522 {
523  if(selection == NULL) {
524  endrun(-1, "NULL selection is not supported\n");
525  }
526 
527  /* don't forget to free buffer after its done*/
528  petaio_alloc_buffer(array, ent, NumSelection);
529 
530  /* Fast code path if there are no such particles */
531  if(NumSelection == 0) {
532  return;
533  }
534 
535 #pragma omp parallel
536  {
537  int i;
538  const int tid = omp_get_thread_num();
539  const int NT = omp_get_num_threads();
540  const int start = NumSelection * (size_t) tid / NT;
541  const int end = NumSelection * ((size_t) tid + 1) / NT;
542  /* fill the buffer */
543  char * p = (char *) array->data;
544  p += array->strides[0] * start;
545  for(i = start; i < end; i ++) {
546  const int j = selection[i];
547  if(Parts[j].Type != ent->ptype) {
548  endrun(2, "Selection %d has type = %d != %d\n", j, Parts[j].Type, ent->ptype);
549  }
550  ent->getter(j, p, Parts, SlotsManager, conv);
551  p += array->strides[0];
552  }
553  }
554 }
555 
556 /* destroy a buffer, freeing its memory */
557 void petaio_destroy_buffer(BigArray * array) {
558  myfree(array->data);
559 }
560 
561 /* read a block from disk, spread the values to memory with setters */
562 int petaio_read_block(BigFile * bf, const char * blockname, BigArray * array, int required) {
563  BigBlock bb;
564  BigBlockPtr ptr;
565 
566  /* open the block */
567  if(0 != big_file_mpi_open_block(bf, &bb, blockname, MPI_COMM_WORLD)) {
568  if(required)
569  endrun(0, "Failed to open block at %s:%s\n", blockname, big_file_get_error_message());
570  else
571  return 1;
572  }
573  if(0 != big_block_seek(&bb, &ptr, 0)) {
574  endrun(1, "Failed to seek block %s: %s\n", blockname, big_file_get_error_message());
575  }
576  if(0 != big_block_mpi_read(&bb, &ptr, array, IO.NumWriters, MPI_COMM_WORLD)) {
577  endrun(1, "Failed to read from block %s: %s\n", blockname, big_file_get_error_message());
578  }
579  if(0 != big_block_mpi_close(&bb, MPI_COMM_WORLD)) {
580  endrun(0, "Failed to close block at %s:%s\n", blockname,
581  big_file_get_error_message());
582  }
583  return 0;
584 }
585 
586 /* save a block to disk */
587 void petaio_save_block(BigFile * bf, const char * blockname, BigArray * array, int verbose)
588 {
589 
590  BigBlock bb;
591  BigBlockPtr ptr;
592 
593  int elsize = big_file_dtype_itemsize(array->dtype);
594 
595  int NumWriters = IO.NumWriters;
596 
597  size_t size = count_sum(array->dims[0]);
598  int NumFiles;
599 
600  if(IO.EnableAggregatedIO) {
601  NumFiles = (size * elsize + IO.BytesPerFile - 1) / IO.BytesPerFile;
602  if(NumWriters > NumFiles * IO.WritersPerFile) {
603  NumWriters = NumFiles * IO.WritersPerFile;
604  message(0, "Throttling NumWriters to %d.\n", NumWriters);
605  }
606  if(NumWriters < IO.MinNumWriters) {
607  NumWriters = IO.MinNumWriters;
608  NumFiles = (NumWriters + IO.WritersPerFile - 1) / IO.WritersPerFile ;
609  message(0, "Throttling NumWriters to %d.\n", NumWriters);
610  }
611  } else {
612  NumFiles = NumWriters;
613  }
614  /*Do not write empty files*/
615  if(size == 0) {
616  NumFiles = 0;
617  }
618 
619  if(verbose && size > 0) {
620  message(0, "Will write %td particles to %d Files for %s\n", size, NumFiles, blockname);
621  }
622  /* create the block */
623  /* dims[1] is the number of members per item */
624  if(0 != big_file_mpi_create_block(bf, &bb, blockname, array->dtype, array->dims[1], NumFiles, size, MPI_COMM_WORLD)) {
625  endrun(0, "Failed to create block at %s:%s\n", blockname,
626  big_file_get_error_message());
627  }
628  if(0 != big_block_seek(&bb, &ptr, 0)) {
629  endrun(0, "Failed to seek:%s\n", big_file_get_error_message());
630  }
631  if(0 != big_block_mpi_write(&bb, &ptr, array, NumWriters, MPI_COMM_WORLD)) {
632  endrun(0, "Failed to write :%s\n", big_file_get_error_message());
633  }
634 
635  if(verbose && size > 0)
636  message(0, "Done writing %td particles to %d Files\n", size, NumFiles);
637 
638  if(0 != big_block_mpi_close(&bb, MPI_COMM_WORLD)) {
639  endrun(0, "Failed to close block at %s:%s\n", blockname,
640  big_file_get_error_message());
641  }
642 }
643 
644 /*
645  * register an IO block of name for particle type ptype.
646  *
647  * use IO_REG wrapper.
648  *
649  * with getter function getter
650  * getter(i, output)
651  * will fill the property of particle i to output.
652  *
653  * NOTE: dtype shall match the format of output of getter
654  *
655  * NOTE: currently there is a hard limit (4096 blocks ).
656  *
657  * */
658 void io_register_io_block(const char * name,
659  const char * dtype,
660  int items,
661  int ptype,
662  property_getter getter,
663  property_setter setter,
664  int required,
665  struct IOTable * IOTable
666  ) {
667  if (IOTable->used == IOTable->allocated) {
669  IOTable->allocated *= 2;
670  }
671  IOTableEntry * ent = &IOTable->ent[IOTable->used];
672  strncpy(ent->name, name, 63);
673  ent->name[63] = '\0';
674  ent->zorder = IOTable->used;
675  ent->ptype = ptype;
676  strncpy(ent->dtype, dtype, 7);
677  ent->dtype[7] = '\0';
678  ent->getter = getter;
679  ent->setter = setter;
680  ent->items = items;
681  ent->required = required;
682  IOTable->used ++;
683 }
684 
685 static void GTPosition(int i, double * out, void * baseptr, void * smanptr, const struct conversions * params) {
686  /* Remove the particle offset before saving*/
687  struct particle_data * part = (struct particle_data *) baseptr;
688  int d;
689  for(d = 0; d < 3; d ++) {
690  out[d] = part[i].Pos[d] - PartManager->CurrentParticleOffset[d];
691  while(out[d] > PartManager->BoxSize) out[d] -= PartManager->BoxSize;
692  while(out[d] <= 0) out[d] += PartManager->BoxSize;
693  }
694 }
695 
696 static void STPosition(int i, double * out, void * baseptr, void * smanptr, const struct conversions * params) {
697  int d;
698  struct particle_data * part = (struct particle_data *) baseptr;
699  for(d = 0; d < 3; d ++) {
700  part[i].Pos[d] = out[d];
701  }
702 }
703 
704 #define SIMPLE_PROPERTY(name, field, type, items) \
705  SIMPLE_GETTER(GT ## name , field, type, items, struct particle_data) \
706  SIMPLE_SETTER(ST ## name , field, type, items, struct particle_data)
707 /*A property with getters and setters that are type specific*/
708 #define SIMPLE_PROPERTY_TYPE(name, ptype, field, type, items) \
709  SIMPLE_GETTER(GT ## ptype ## name , field, type, items, struct particle_data) \
710  SIMPLE_SETTER(ST ## ptype ## name , field, type, items, struct particle_data)
711 
712 /* A property that uses getters and setters via the PI of a particle data array.*/
713 #define SIMPLE_GETTER_PI(name, field, dtype, items, slottype) \
714 static void name(int i, dtype * out, void * baseptr, void * smanptr, const struct conversions * params) { \
715  int PI = ((struct particle_data *) baseptr)[i].PI; \
716  int ptype = ((struct particle_data *) baseptr)[i].Type; \
717  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[ptype]); \
718  slottype * sl = (slottype *) info->ptr; \
719  int k; \
720  for(k = 0; k < items; k ++) { \
721  out[k] = *(&(sl[PI].field) + k); \
722  } \
723 }
724 
725 #define SIMPLE_SETTER_PI(name, field, dtype, items, slottype) \
726 static void name(int i, dtype * out, void * baseptr, void * smanptr, const struct conversions * params) { \
727  int PI = ((struct particle_data *) baseptr)[i].PI; \
728  int ptype = ((struct particle_data *) baseptr)[i].Type; \
729  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[ptype]); \
730  slottype * sl = (slottype *) info->ptr; \
731  int k; \
732  for(k = 0; k < items; k ++) { \
733  *(&(sl[PI].field) + k) = out[k]; \
734  } \
735 }
736 
737 #define SIMPLE_PROPERTY_PI(name, field, type, items, slottype) \
738  SIMPLE_GETTER_PI(GT ## name , field, type, items, slottype) \
739  SIMPLE_SETTER_PI(ST ## name , field, type, items, slottype)
740 #define SIMPLE_PROPERTY_TYPE_PI(name, ptype, field, type, items, slottype) \
741  SIMPLE_GETTER_PI(GT ## ptype ## name , field, type, items, slottype) \
742  SIMPLE_SETTER_PI(ST ## ptype ## name , field, type, items, slottype)
743 
744 static void GTVelocity(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
745  /* Convert to Peculiar Velocity if UsePeculiarVelocity is set */
746  double fac;
747  struct particle_data * part = (struct particle_data *) baseptr;
748  if (IO.UsePeculiarVelocity) {
749  fac = 1.0 / params->atime;
750  } else {
751  fac = 1.0;
752  }
753 
754  int d;
755  for(d = 0; d < 3; d ++) {
756  out[d] = fac * part[i].Vel[d];
757  }
758 }
759 static void STVelocity(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
760  double fac;
761  struct particle_data * part = (struct particle_data *) baseptr;
762  if (IO.UsePeculiarVelocity) {
763  fac = params->atime;
764  } else {
765  fac = 1.0;
766  }
767 
768  int d;
769  for(d = 0; d < 3; d ++) {
770  part[i].Vel[d] = out[d] * fac;
771  }
772 }
773 SIMPLE_PROPERTY(Mass, Mass, float, 1)
774 SIMPLE_PROPERTY(ID, ID, uint64_t, 1)
775 SIMPLE_PROPERTY(Generation, Generation, unsigned char, 1)
776 SIMPLE_GETTER(GTPotential, Potential, float, 1, struct particle_data)
777 SIMPLE_GETTER(GTTimeBin, TimeBin, int, 1, struct particle_data)
778 SIMPLE_PROPERTY(SmoothingLength, Hsml, float, 1)
779 SIMPLE_PROPERTY_PI(Density, Density, float, 1, struct sph_particle_data)
780 SIMPLE_PROPERTY_PI(EgyWtDensity, EgyWtDensity, float, 1, struct sph_particle_data)
781 SIMPLE_PROPERTY_PI(ElectronAbundance, Ne, float, 1, struct sph_particle_data)
782 SIMPLE_PROPERTY_PI(DelayTime, DelayTime, float, 1, struct sph_particle_data)
783 SIMPLE_PROPERTY_TYPE_PI(StarFormationTime, 4, FormationTime, float, 1, struct star_particle_data)
784 SIMPLE_PROPERTY_PI(BirthDensity, BirthDensity, float, 1, struct star_particle_data)
785 SIMPLE_PROPERTY_TYPE_PI(Metallicity, 4, Metallicity, float, 1, struct star_particle_data)
786 SIMPLE_PROPERTY_TYPE_PI(LastEnrichmentMyr, 4, LastEnrichmentMyr, float, 1, struct star_particle_data)
787 SIMPLE_PROPERTY_TYPE_PI(TotalMassReturned, 4, TotalMassReturned, float, 1, struct star_particle_data)
788 SIMPLE_PROPERTY_TYPE_PI(Metallicity, 0, Metallicity, float, 1, struct sph_particle_data)
789 SIMPLE_PROPERTY_TYPE_PI(Metals, 4, Metals[0], float, NMETALS, struct star_particle_data)
790 SIMPLE_PROPERTY_TYPE_PI(Metals, 0, Metals[0], float, NMETALS, struct sph_particle_data)
791 
792 SIMPLE_GETTER_PI(GTStarFormationRate, Sfr, float, 1, struct sph_particle_data)
793 SIMPLE_PROPERTY_TYPE_PI(StarFormationTime, 5, FormationTime, float, 1, struct bh_particle_data)
794 SIMPLE_PROPERTY_PI(BlackholeMass, Mass, float, 1, struct bh_particle_data)
795 SIMPLE_PROPERTY_PI(BlackholeDensity, Density, float, 1, struct bh_particle_data)
796 SIMPLE_PROPERTY_PI(BlackholeAccretionRate, Mdot, float, 1, struct bh_particle_data)
797 SIMPLE_PROPERTY_PI(BlackholeProgenitors, CountProgs, float, 1, struct bh_particle_data)
798 SIMPLE_PROPERTY_PI(BlackholeSwallowID, SwallowID, uint64_t, 1, struct bh_particle_data)
799 SIMPLE_PROPERTY_PI(BlackholeSwallowTime, SwallowTime, float, 1, struct bh_particle_data)
800 SIMPLE_PROPERTY_PI(BlackholeJumpToMinPot, JumpToMinPot, int, 1, struct bh_particle_data)
801 SIMPLE_PROPERTY_PI(BlackholeMtrack, Mtrack, float, 1, struct bh_particle_data)
802 SIMPLE_PROPERTY_PI(BlackholeMseed, Mseed, float, 1, struct bh_particle_data)
803 SIMPLE_PROPERTY_PI(BlackholeKineticFdbkEnergy, KineticFdbkEnergy, float, 1, struct bh_particle_data)
804 
805 SIMPLE_SETTER_PI(STBlackholeMinPotPos , MinPotPos[0], double, 3, struct bh_particle_data)
806 static void GTBlackholeMinPotPos(int i, double * out, void * baseptr, void * smanptr, const struct conversions * params) {
807  /* Remove the particle offset before saving*/
808  struct particle_data * part = (struct particle_data *) baseptr;
809  int PI = part[i].PI;
810  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[5]);
811  struct bh_particle_data * sl = (struct bh_particle_data *) info->ptr;
812  int d;
813  for(d = 0; d < 3; d ++) {
814  out[d] = sl[PI].MinPotPos[d] - PartManager->CurrentParticleOffset[d];
815  while(out[d] > PartManager->BoxSize) out[d] -= PartManager->BoxSize;
816  while(out[d] <= 0) out[d] += PartManager->BoxSize;
817  }
818 }
819 
820 /*This is only used if FoF is enabled*/
821 SIMPLE_GETTER(GTGroupID, GrNr, uint32_t, 1, struct particle_data)
822 static void GTNeutralHydrogenFraction(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
823  double redshift = 1./params->atime - 1;
824  struct particle_data * pl = ((struct particle_data *) baseptr)+i;
825  int PI = pl->PI;
826  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
827  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
828  *out = get_neutral_fraction_sfreff(redshift, params->hubble, pl, sl+PI);
829 }
830 
831 static void GTHeliumIFraction(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
832  double redshift = 1./params->atime - 1;
833  struct particle_data * pl = ((struct particle_data *) baseptr)+i;
834  int PI = pl->PI;
835  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
836  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
837  *out = get_helium_neutral_fraction_sfreff(0, redshift, params->hubble, pl, sl+PI);
838 }
839 static void GTHeliumIIFraction(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
840  double redshift = 1./params->atime - 1;
841  struct particle_data * pl = ((struct particle_data *) baseptr)+i;
842  int PI = pl->PI;
843  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
844  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
845  *out = get_helium_neutral_fraction_sfreff(1, redshift, params->hubble, pl, sl+PI);
846 }
847 static void GTHeliumIIIFraction(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
848  double redshift = 1./params->atime - 1;
849  struct particle_data * pl = ((struct particle_data *) baseptr)+i;
850  int PI = pl->PI;
851  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
852  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
853  *out = get_helium_neutral_fraction_sfreff(2, redshift, params->hubble, pl, sl+PI);
854 }
855 static void GTInternalEnergy(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
856  int PI = ((struct particle_data *) baseptr)[i].PI;
857  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
858  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
859  double a3inv = 1/(params->atime * params->atime * params->atime);
860  *out = sl[PI].Entropy / GAMMA_MINUS1 * pow(sl[PI].Density * a3inv, GAMMA_MINUS1);
861 }
862 
863 static void STInternalEnergy(int i, float * out, void * baseptr, void * smanptr, const struct conversions * params) {
864  float u = *out;
865  int PI = ((struct particle_data *) baseptr)[i].PI;
866  struct slot_info * info = &(((struct slots_manager_type *) smanptr)->info[0]);
867  struct sph_particle_data * sl = (struct sph_particle_data *) info->ptr;
868  double a3inv = 1/(params->atime * params->atime * params->atime);
869  sl[PI].Entropy = GAMMA_MINUS1 * u / pow(sl[PI].Density * a3inv, GAMMA_MINUS1);
870 }
871 
872 /* Can't use the macros because cannot take address of a bitfield*/
873 static void GTHeIIIIonized(int i, unsigned char * out, void * baseptr, void * smanptr, const struct conversions * params) {
874  struct particle_data * part = (struct particle_data *) baseptr;
875  *out = part[i].HeIIIionized;
876 }
877 
878 static void STHeIIIIonized(int i, unsigned char * out, void * baseptr, void * smanptr, const struct conversions * params) {
879  struct particle_data * part = (struct particle_data *) baseptr;
880  part[i].HeIIIionized = *out;
881 }
882 static void GTSwallowed(int i, unsigned char * out, void * baseptr, void * smanptr, const struct conversions * params) {
883  struct particle_data * part = (struct particle_data *) baseptr;
884  *out = part[i].Swallowed;
885 }
886 
887 static void STSwallowed(int i, unsigned char * out, void * baseptr, void * smanptr, const struct conversions * params) {
888  struct particle_data * part = (struct particle_data *) baseptr;
889  part[i].Swallowed = *out;
890 }
891 
892 static int order_by_type(const void *a, const void *b)
893 {
894  const struct IOTableEntry * pa = (const struct IOTableEntry *) a;
895  const struct IOTableEntry * pb = (const struct IOTableEntry *) b;
896 
897  if(pa->ptype < pb->ptype)
898  return -1;
899  if(pa->ptype > pb->ptype)
900  return +1;
901  if(pa->zorder < pb->zorder)
902  return -1;
903  if(pa->zorder > pb->zorder)
904  return 1;
905 
906  return 0;
907 }
908 
909 void register_io_blocks(struct IOTable * IOTable, int WriteGroupID, int MetalReturnOn)
910 {
911  int i;
912  IOTable->used = 0;
913  IOTable->allocated = 100;
914  IOTable->ent = (IOTableEntry *) mymalloc2("IOTable", IOTable->allocated * sizeof(IOTableEntry));
915  /* Bare Bone Gravity*/
916  for(i = 0; i < 6; i ++) {
917  /* We put Mass first because sometimes there is
918  * corruption in the first array and we can recover from Mass corruption*/
919  IO_REG(Mass, "f4", 1, i, IOTable);
920  IO_REG(Position, "f8", 3, i, IOTable);
921  IO_REG(Velocity, "f4", 3, i, IOTable);
922  IO_REG(ID, "u8", 1, i, IOTable);
923  if(IO.OutputPotential)
924  IO_REG_WRONLY(Potential, "f4", 1, i, IOTable);
925  if(WriteGroupID)
926  IO_REG_WRONLY(GroupID, "u4", 1, i, IOTable);
927  if(IO.OutputTimebins)
928  IO_REG_WRONLY(TimeBin, "u4", 1, i, IOTable);
929  }
930 
931  IO_REG(Generation, "u1", 1, 0, IOTable);
932  IO_REG(Generation, "u1", 1, 4, IOTable);
933  IO_REG(Generation, "u1", 1, 5, IOTable);
934  /* Bare Bone SPH*/
935  IO_REG(SmoothingLength, "f4", 1, 0, IOTable);
936  IO_REG(Density, "f4", 1, 0, IOTable);
937 
939  IO_REG(EgyWtDensity, "f4", 1, 0, IOTable);
940 
941  /* On reload this sets the Entropy variable, need the densities.
942  * Register this after Density and EgyWtDensity will ensure density is read
943  * before this. */
944  IO_REG(InternalEnergy, "f4", 1, 0, IOTable);
945 
946  /* Cooling */
947  IO_REG(ElectronAbundance, "f4", 1, 0, IOTable);
948  IO_REG_WRONLY(NeutralHydrogenFraction, "f4", 1, 0, IOTable);
949 
951  IO_REG_WRONLY(HeliumIFraction, "f4", 1, 0, IOTable);
952  IO_REG_WRONLY(HeliumIIFraction, "f4", 1, 0, IOTable);
953  IO_REG_WRONLY(HeliumIIIFraction, "f4", 1, 0, IOTable);
954  }
955  /* Marks whether a particle has been HeIII ionized yet*/
956  IO_REG_NONFATAL(HeIIIIonized, "u1", 1, 0, IOTable);
957 
958  /* SF */
959  IO_REG_WRONLY(StarFormationRate, "f4", 1, 0, IOTable);
960  /* Another new addition: save the DelayTime for wind particles*/
961  IO_REG_NONFATAL(DelayTime, "f4", 1, 0, IOTable);
962 
963  IO_REG_NONFATAL(BirthDensity, "f4", 1, 4, IOTable);
964  IO_REG_TYPE(StarFormationTime, "f4", 1, 4, IOTable);
965  IO_REG_TYPE(Metallicity, "f4", 1, 0, IOTable);
966  IO_REG_TYPE(Metallicity, "f4", 1, 4, IOTable);
967  if(MetalReturnOn) {
968  IO_REG_TYPE(Metals, "f4", NMETALS, 0, IOTable);
969  IO_REG_TYPE(Metals, "f4", NMETALS, 4, IOTable);
970  IO_REG_TYPE(LastEnrichmentMyr, "f4", 1, 4, IOTable);
971  IO_REG_TYPE(TotalMassReturned, "f4", 1, 4, IOTable);
972  IO_REG_NONFATAL(SmoothingLength, "f4", 1, 4, IOTable);
973  }
974  /* end SF */
975 
976  /* Black hole */
977  IO_REG_TYPE(StarFormationTime, "f4", 1, 5, IOTable);
978  IO_REG(BlackholeMass, "f4", 1, 5, IOTable);
979  IO_REG(BlackholeDensity, "f4", 1, 5, IOTable);
980  IO_REG(BlackholeAccretionRate, "f4", 1, 5, IOTable);
981  IO_REG(BlackholeProgenitors, "i4", 1, 5, IOTable);
982  IO_REG(BlackholeMinPotPos, "f8", 3, 5, IOTable);
983  IO_REG(BlackholeJumpToMinPot, "i4", 1, 5, IOTable);
984  IO_REG(BlackholeMtrack, "f4", 1, 5, IOTable);
985  IO_REG_NONFATAL(BlackholeMseed, "f4", 1, 5, IOTable);
986  IO_REG_NONFATAL(BlackholeKineticFdbkEnergy, "f4", 1, 5, IOTable);
987 
988  /* Smoothing lengths for black hole: this is a new addition*/
989  IO_REG_NONFATAL(SmoothingLength, "f4", 1, 5, IOTable);
990  /* Marks whether a BH particle has been swallowed*/
991  IO_REG_NONFATAL(Swallowed, "u1", 1, 5, IOTable);
992  /* ID of the swallowing black hole particle. If == -1, then particle is live*/
993  IO_REG_NONFATAL(BlackholeSwallowID, "u8", 1, 5, IOTable);
994  /* Time the BH was swallowed*/
995  IO_REG_NONFATAL(BlackholeSwallowTime, "f4", 1, 5, IOTable);
996 
997  /*Sort IO blocks so similar types are together; then ordered by the sequence they are declared. */
999 }
1000 
1001 /* Add extra debug blocks to the output*/
1002 /* Write (but don't read) them, only useful for debugging the particle structures.
1003  * Warning: future code versions may change the units!*/
1004 SIMPLE_GETTER(GTGravAccel, GravAccel[0], float, 3, struct particle_data)
1005 SIMPLE_GETTER(GTGravPM, GravPM[0], float, 3, struct particle_data)
1006 SIMPLE_GETTER_PI(GTHydroAccel, HydroAccel[0], float, 3, struct sph_particle_data)
1007 SIMPLE_GETTER_PI(GTMaxSignalVel, MaxSignalVel, float, 1, struct sph_particle_data)
1008 SIMPLE_GETTER_PI(GTEntropy, Entropy, float, 1, struct sph_particle_data)
1009 SIMPLE_GETTER_PI(GTDtEntropy, DtEntropy, float, 1, struct sph_particle_data)
1010 SIMPLE_GETTER_PI(GTDhsmlEgyDensityFactor, DhsmlEgyDensityFactor, float, 1, struct sph_particle_data)
1011 SIMPLE_GETTER_PI(GTDivVel, DivVel, float, 1, struct sph_particle_data)
1012 SIMPLE_GETTER_PI(GTCurlVel, CurlVel, float, 1, struct sph_particle_data)
1013 
1015 {
1016  int ptype;
1017  for(ptype = 0; ptype < 6; ptype++) {
1018  IO_REG_WRONLY(GravAccel, "f4", 3, ptype, IOTable);
1019  IO_REG_WRONLY(GravPM, "f4", 3, ptype, IOTable);
1020  if(!IO.OutputTimebins) /* Otherwise it is output in the regular blocks*/
1021  IO_REG_WRONLY(TimeBin, "u4", 1, ptype, IOTable);
1022  }
1023  IO_REG_WRONLY(HydroAccel, "f4", 3, 0, IOTable);
1024  IO_REG_WRONLY(MaxSignalVel, "f4", 1, 0, IOTable);
1025  IO_REG_WRONLY(Entropy, "f4", 1, 0, IOTable);
1026  IO_REG_WRONLY(DtEntropy, "f4", 1, 0, IOTable);
1027  IO_REG_WRONLY(DhsmlEgyDensityFactor, "f4", 1, 0, IOTable);
1028  IO_REG_WRONLY(DivVel, "f4", 1, 0, IOTable);
1029  IO_REG_WRONLY(CurlVel, "f4", 1, 0, IOTable);
1030  /*Sort IO blocks so similar types are together; then ordered by the sequence they are declared. */
1032 }
1033 
1035  myfree(IOTable->ent);
1036  IOTable->allocated = 0;
1037 }
const char * GADGET_VERSION
Definition: config.c:7
const char * GADGET_COMPILER_SETTINGS
Definition: config.c:1
double hubble_function(const Cosmology *CP, double a)
Definition: cosmology.c:58
enum DensityKernelType GetDensityKernelType(void)
Definition: density.c:63
const char * name
Definition: densitykernel.c:93
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
static struct gravpm_params GravPM
int DensityIndependentSphOn(void)
Definition: hydra.c:49
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myrealloc(ptr, size)
Definition: mymalloc.h:18
#define mymalloc2(name, size)
Definition: mymalloc.h:16
#define myfree(x)
Definition: mymalloc.h:19
void petaio_save_neutrinos(BigFile *bf, int ThisTask)
void petaio_read_neutrinos(BigFile *bf, int ThisTask)
void petaio_read_icnutransfer(BigFile *bf, int ThisTask)
void param_get_string2(ParameterSet *ps, const char *name, char *dst, size_t len)
Definition: paramset.c:355
int param_get_int(ParameterSet *ps, const char *name)
Definition: paramset.c:368
struct part_manager_type PartManager[1]
Definition: partmanager.c:11
#define P
Definition: partmanager.h:88
void petaio_destroy_buffer(BigArray *array)
Definition: petaio.c:557
#define SIMPLE_GETTER_PI(name, field, dtype, items, slottype)
Definition: petaio.c:713
static void GTHeliumIIFraction(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:839
static void GTBlackholeMinPotPos(int i, double *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:806
static int _get_attr_int(BigBlock *bh, const char *name, const int def)
Definition: petaio.c:416
static void petaio_read_header_internal(BigFile *bf, Cosmology *CP, struct header_data *data)
Definition: petaio.c:426
void petaio_read_snapshot(int num, const char *OutputDir, Cosmology *CP, struct header_data *header, struct part_manager_type *PartManager, struct slots_manager_type *SlotsManager, MPI_Comm Comm)
Definition: petaio.c:255
#define SIMPLE_PROPERTY(name, field, type, items)
Definition: petaio.c:704
static void GTSwallowed(int i, unsigned char *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:882
static struct petaio_params IO
void io_register_io_block(const char *name, const char *dtype, int items, int ptype, property_getter getter, property_setter setter, int required, struct IOTable *IOTable)
Definition: petaio.c:658
static void STVelocity(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:759
static void STPosition(int i, double *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:696
struct header_data petaio_read_header(int num, const char *OutputDir, Cosmology *CP)
Definition: petaio.c:219
static void GTVelocity(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:744
void destroy_io_blocks(struct IOTable *IOTable)
Definition: petaio.c:1034
static void GTHeIIIIonized(int i, unsigned char *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:873
static void GTNeutralHydrogenFraction(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:822
static int order_by_type(const void *a, const void *b)
Definition: petaio.c:892
void register_io_blocks(struct IOTable *IOTable, int WriteGroupID, int MetalReturnOn)
Definition: petaio.c:909
static struct header_data Header
Definition: petaio.c:53
static void petaio_write_header(BigFile *bf, const double atime, const int64_t *NTotal, const Cosmology *CP, const struct header_data *data)
Definition: petaio.c:361
int petaio_read_block(BigFile *bf, const char *blockname, BigArray *array, int required)
Definition: petaio.c:562
static void GTHeliumIFraction(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:831
static void STInternalEnergy(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:863
#define SIMPLE_SETTER_PI(name, field, dtype, items, slottype)
Definition: petaio.c:725
void petaio_init(void)
Definition: petaio.c:88
void petaio_save_snapshot(const char *fname, struct IOTable *IOTable, int verbose, const double atime, const Cosmology *CP)
Definition: petaio.c:151
void register_debug_io_blocks(struct IOTable *IOTable)
Definition: petaio.c:1014
char * petaio_get_snapshot_fname(int num, const char *OutputDir)
Definition: petaio.c:207
void petaio_build_selection(int *selection, int *ptype_offset, int *ptype_count, const struct particle_data *Parts, const int NumPart, int(*select_func)(int i, const struct particle_data *Parts))
Definition: petaio.c:113
void petaio_alloc_buffer(BigArray *array, IOTableEntry *ent, int64_t localsize)
Definition: petaio.c:491
int GetUsePeculiarVelocity(void)
Definition: petaio.c:79
static void GTHeliumIIIFraction(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:847
static void STSwallowed(int i, unsigned char *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:887
void set_petaio_params(ParameterSet *ps)
Definition: petaio.c:57
static void GTInternalEnergy(int i, float *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:855
#define SIMPLE_PROPERTY_TYPE_PI(name, ptype, field, type, items, slottype)
Definition: petaio.c:740
static void STHeIIIIonized(int i, unsigned char *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:878
static void GTPosition(int i, double *out, void *baseptr, void *smanptr, const struct conversions *params)
Definition: petaio.c:685
void petaio_build_buffer(BigArray *array, IOTableEntry *ent, const int *selection, const int NumSelection, struct particle_data *Parts, struct slots_manager_type *SlotsManager, struct conversions *conv)
Definition: petaio.c:521
void petaio_readout_buffer(BigArray *array, IOTableEntry *ent, struct conversions *conv, struct part_manager_type *PartManager, struct slots_manager_type *SlotsManager)
Definition: petaio.c:506
#define SIMPLE_PROPERTY_PI(name, field, type, items, slottype)
Definition: petaio.c:737
void petaio_save_block(BigFile *bf, const char *blockname, BigArray *array, int verbose)
Definition: petaio.c:587
static double _get_attr_double(BigBlock *bh, const char *name, const double def)
Definition: petaio.c:407
void(* property_setter)(int i, void *target, void *baseptr, void *slotptr, const struct conversions *params)
Definition: petaio.h:46
#define SIMPLE_GETTER(name, field, type, items, stype)
Definition: petaio.h:145
#define IO_REG_WRONLY(name, dtype, items, ptype, IOTable)
Definition: petaio.h:117
void(* property_getter)(int i, void *result, void *baseptr, void *slotptr, const struct conversions *params)
Definition: petaio.h:45
#define IO_REG(name, dtype, items, ptype, IOTable)
Definition: petaio.h:113
#define IO_REG_NONFATAL(name, dtype, items, ptype, IOTable)
Definition: petaio.h:119
#define IO_REG_TYPE(name, dtype, items, ptype, IOTable)
Definition: petaio.h:115
#define GAMMA_MINUS1
Definition: physconst.h:35
static Cosmology * CP
Definition: power.c:27
double get_helium_neutral_fraction_sfreff(int ion, double redshift, double hubble, struct particle_data *partdata, struct sph_particle_data *sphdata)
Definition: sfr_eff.c:548
double get_neutral_fraction_sfreff(double redshift, double hubble, struct particle_data *partdata, struct sph_particle_data *sphdata)
Definition: sfr_eff.c:520
int get_generations(void)
Definition: sfr_eff.c:87
void slots_setup_id(const struct part_manager_type *pman, struct slots_manager_type *sman)
Definition: slotsmanager.c:653
struct slots_manager_type SlotsManager[1]
Definition: slotsmanager.c:7
#define NMETALS
Definition: slotsmanager.h:60
char * fastpm_strdup_printf(const char *fmt,...)
Definition: string.c:41
double Omega0
Definition: cosmology.h:10
double HubbleParam
Definition: cosmology.h:20
double CMBTemperature
Definition: cosmology.h:9
double OmegaLambda
Definition: cosmology.h:14
double OmegaBaryon
Definition: cosmology.h:19
int MassiveNuLinRespOn
Definition: cosmology.h:26
int items
Definition: petaio.h:54
char dtype[8]
Definition: petaio.h:53
int zorder
Definition: petaio.h:50
int ptype
Definition: petaio.h:52
int required
Definition: petaio.h:55
property_getter getter
Definition: petaio.h:56
property_setter setter
Definition: petaio.h:57
char name[64]
Definition: petaio.h:51
Definition: petaio.h:60
int used
Definition: petaio.h:62
int allocated
Definition: petaio.h:63
IOTableEntry * ent
Definition: petaio.h:61
double MinPotPos[3]
Definition: slotsmanager.h:41
double atime
Definition: petaio.h:41
double hubble
Definition: petaio.h:42
double TimeIC
Definition: petaio.h:24
int64_t NTotalInit[6]
Definition: petaio.h:20
double TimeSnapshot
Definition: petaio.h:26
double UnitMass_in_g
Definition: petaio.h:31
int64_t NLocal[6]
Definition: petaio.h:16
double MassTable[6]
Definition: petaio.h:22
double UnitVelocity_in_cm_per_s
Definition: petaio.h:32
double UnitLength_in_cm
Definition: petaio.h:30
double BoxSize
Definition: petaio.h:28
int64_t NTotal[6]
Definition: petaio.h:18
struct particle_data * Base
Definition: partmanager.h:74
double CurrentParticleOffset[3]
Definition: partmanager.h:82
unsigned char TimeBin
Definition: partmanager.h:26
MyFloat Potential
Definition: partmanager.h:45
unsigned char HeIIIionized
Definition: partmanager.h:28
MyFloat Hsml
Definition: partmanager.h:59
MyIDType ID
Definition: partmanager.h:38
unsigned int Swallowed
Definition: partmanager.h:20
MyFloat Vel[3]
Definition: partmanager.h:40
double Pos[3]
Definition: partmanager.h:12
unsigned int Type
Definition: partmanager.h:17
unsigned char Generation
Definition: partmanager.h:23
size_t AggregatedIOThreshold
Definition: petaio.c:37
int UsePeculiarVelocity
Definition: petaio.c:43
int EnableAggregatedIO
Definition: petaio.c:36
int OutputPotential
Definition: petaio.c:44
int OutputHeliumFractions
Definition: petaio.c:45
char InitCondFile[100]
Definition: petaio.c:48
char SnapshotFileBase[100]
Definition: petaio.c:47
int WritersPerFile
Definition: petaio.c:33
int NumWriters
Definition: petaio.c:34
int OutputTimebins
Definition: petaio.c:46
int MinNumWriters
Definition: petaio.c:35
size_t BytesPerFile
Definition: petaio.c:32
char * ptr
Definition: slotsmanager.h:10
int64_t count_sum(int64_t countLocal)
Definition: system.c:264
void sumup_large_ints(int n, int *src, int64_t *res)
Definition: system.c:192
int ThisTask
Definition: test_exchange.c:23
#define qsort_openmp
Definition: test_exchange.c:14
static enum TransferType ptype
Definition: zeldovich.c:146