GADGET-4
io_halotrees.cc
Go to the documentation of this file.
1/*******************************************************************************
2 * \copyright This file is part of the GADGET4 N-body/SPH code developed
3 * \copyright by Volker Springel. Copyright (C) 2014-2020 by Volker Springel
4 * \copyright (vspringel@mpa-garching.mpg.de) and all contributing authors.
5 *******************************************************************************/
6
12#include "gadgetconfig.h"
13
14#ifdef MERGERTREE
15
16#include <gsl/gsl_rng.h>
17#include <hdf5.h>
18#include <math.h>
19#include <mpi.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26
27#include "../data/allvars.h"
28#include "../data/dtypes.h"
29#include "../data/mymalloc.h"
30#include "../fof/fof.h"
31#include "../io/hdf5_util.h"
32#include "../io/io.h"
33#include "../logs/timer.h"
34#include "../main/simulation.h"
35#include "../mergertree/io_halotrees.h"
36#include "../mergertree/mergertree.h"
37#include "../mpi_utils/mpi_utils.h"
38#include "../sort/parallel_sort.h"
39#include "../subfind/subfind.h"
40#include "../system/system.h"
41
42halotrees_io::halotrees_io(mergertree *MergerTree_ptr, MPI_Comm comm, int format) : IO_Def(comm, format)
43{
44 MergerTree = MergerTree_ptr;
45
46 this->N_IO_Fields = 0;
47 this->N_DataGroups = 3;
48 this->header_size = sizeof(header);
49 this->header_buf = &header;
50 this->type_of_file = FILE_IS_TREECAT;
51 sprintf(this->info, "MERGERTREE: writing mergertrees");
52
53 /* overview table for trees in the file */
54
55 init_field("MTRL", "Length", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_TT, &MergerTree->TreeTable[0].HaloCount, NULL, TREELENGTH, 0, 0,
56 0, 0, 0, 0, 0);
57 init_field("MTRS", "StartOffset", MEM_INT64, FILE_INT64, SKIP_ON_READ, 1, A_TT, &MergerTree->TreeTable[0].FirstHalo, NULL,
58 TREELENGTH, 0, 0, 0, 0, 0, 0, 0);
59 init_field("MTRI", "TreeID", MEM_INT64, FILE_INT64, SKIP_ON_READ, 1, A_TT, &MergerTree->TreeTable[0].TreeID, NULL, TREELENGTH, 0, 0,
60 0, 0, 0, 0, 0);
61
62 /* link pointers of each subhalo in the trees */
63
64 init_field("TMPR", "TreeMainProgenitor", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeMainProgenitor, NULL,
65 TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
66 init_field("TDES", "TreeDescendant", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeDescendant, NULL, TREEHALOS,
67 0, 0, 0, 0, 0, 0, 0, true);
68 init_field("TFPR", "TreeFirstProgenitor", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeFirstProgenitor, NULL,
69 TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
70 init_field("TNPR", "TreeNextProgenitor", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeNextProgenitor, NULL,
71 TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
72 init_field("TFHF", "TreeFirstHaloInFOFgroup", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeFirstHaloInFOFgroup,
73 NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
74 init_field("TNHF", "TreeNextHaloInFOFgroup", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeNextHaloInFOFgroup,
75 NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
76 init_field("TPRO", "TreeProgenitor", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeProgenitor, NULL, TREEHALOS,
77 0, 0, 0, 0, 0, 0, 0, true);
78 init_field("TFDE", "TreeFirstDescendant", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeFirstDescendant, NULL,
79 TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
80 init_field("TNDE", "TreeNextDescendant", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeNextDescendant, NULL,
81 TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
82
83 /* properties of each subhalo in the trees */
84
85 init_field("SLEN", "SubhaloLen", mem_len_type, file_len_type, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.Len, NULL,
86 SUBGROUPS, 0, 0, 0, 0, 0, 0, 0, true);
87 init_field("MASS", "SubhaloMass", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.Mass, NULL,
88 TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
89 init_field("FMC2", "Group_M_Crit200", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.M_Crit200,
90 NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
91 init_field("SPOS", "SubhaloPos", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 3, A_H, &MergerTree->Halos[0].SubProp.Pos[0], NULL,
92 TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
93 init_field("SVEL", "SubhaloVel", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 3, A_H, &MergerTree->Halos[0].SubProp.Vel[0], NULL,
94 TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
95 init_field("SSPI", "SubhaloVelDisp", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.SubVelDisp,
96 NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
97 init_field("SVMX", "SubhaloVmax", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.SubVmax, NULL,
98 TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
99 init_field("SVRX", "SubhaloVmaxRad", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubProp.SubVmaxRad,
100 NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
101 init_field("SHMR", "SubhaloHalfmassRad", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 1, A_H,
102 &MergerTree->Halos[0].SubProp.SubHalfMassRad, NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
103 init_field("SSPI", "SubhaloSpin", MEM_MY_FLOAT, FILE_MY_IO_FLOAT, SKIP_ON_READ, 3, A_H, &MergerTree->Halos[0].SubProp.Spin[0], NULL,
104 TREEHALOS, 0, 0, 0, 0, 0, 0, 0);
105 init_field("SIDM", "SubhaloIDMostbound", MEM_MY_ID_TYPE, FILE_MY_ID_TYPE, READ_IF_PRESENT, 1, A_H,
106 &MergerTree->Halos[0].SubProp.SubMostBoundID, NULL, TREEHALOS, 0, 0, 0, 0, 0, 0, 0, true);
107
108 /* where this subhalo came from */
109
110 init_field("TSNP", "SnapNum", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SnapNum, NULL, TREEHALOS, 0, 0, 0, 0, 0,
111 0, 0, true);
112 init_field("TSNR", "SubhaloNr", MEM_INT64, FILE_INT64, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].SubhaloNr, NULL, TREEHALOS, 0, 0,
113 0, 0, 0, 0, 0, true);
114 init_field("GRNR", "GroupNr", MEM_INT64, FILE_INT64, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].GroupNr, NULL, TREEHALOS, 0, 0, 0,
115 0, 0, 0, 0, true);
116
117 /* the fields TreeID and TreeIndex are in principle redundant but kept for convenience */
118
119 init_field("TRID", "TreeID", MEM_INT64, FILE_INT64, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeID, NULL, TREEHALOS, 0, 0, 0, 0,
120 0, 0, 0, true);
121 init_field("TRIX", "TreeIndex", MEM_INT, FILE_INT, SKIP_ON_READ, 1, A_H, &MergerTree->Halos[0].TreeIndex, NULL, TREEHALOS, 0, 0, 0,
122 0, 0, 0, 0, true);
123
124 /**** output times */
125
126 init_field("REDS", "Redshift", MEM_DOUBLE, FILE_DOUBLE, SKIP_ON_READ, 1, A_CT, &MergerTree->CatTimes[0].Redshift, NULL, TREETIMES, 0,
127 0, 0, 0, 0, 0, 0);
128
129 init_field("OUTT", "Time", MEM_DOUBLE, FILE_DOUBLE, SKIP_ON_READ, 1, A_CT, &MergerTree->CatTimes[0].Time, NULL, TREETIMES, 0, 0, 0,
130 0, 0, 0, 0);
131}
132
133void halotrees_io::halotrees_save_trees(void)
134{
135 char buf[MAXLEN_PATH_EXTRA];
136
137 /* write trees */
139 {
140 if(ThisTask == 0)
141 {
142 sprintf(buf, "%s/treedata", All.OutputDir);
143 mkdir(buf, 02755);
144 }
145 MPI_Barrier(Communicator);
146 }
147
149 sprintf(buf, "%s/treedata/%s", All.OutputDir, "trees");
150 else
151 sprintf(buf, "%s%s", All.OutputDir, "trees");
152
153 write_multiple_files(buf, All.NumFilesPerSnapshot);
154}
155
156void halotrees_io::fill_file_header(int writeTask, int lastTask, long long *n_type, long long *ntot_type)
157{
158 /* determine group/id numbers of each type in file */
159
160 n_type[0] = MergerTree->Ntrees;
161 n_type[1] = MergerTree->Nhalos;
162 if(ThisTask == writeTask)
163 n_type[2] = MergerTree->LastSnapShotNr + 1;
164 else
165 n_type[2] = 0;
166
167 if(ThisTask == writeTask)
168 {
169 for(int n = 0; n < N_DataGroups; n++)
170 ntot_type[n] = n_type[n];
171
172 for(int task = writeTask + 1; task <= lastTask; task++)
173 {
174 long long nn[N_DataGroups];
175 MPI_Recv(&nn[0], N_DataGroups, MPI_LONG_LONG, task, TAG_LOCALN, Communicator, MPI_STATUS_IGNORE);
176 for(int n = 0; n < N_DataGroups; n++)
177 ntot_type[n] += nn[n];
178 }
179
180 for(int task = writeTask + 1; task <= lastTask; task++)
181 MPI_Send(&ntot_type[0], N_DataGroups, MPI_LONG_LONG, task, TAG_N, Communicator);
182 }
183 else
184 {
185 MPI_Send(&n_type[0], N_DataGroups, MPI_LONG_LONG, writeTask, TAG_LOCALN, Communicator);
186 MPI_Recv(&ntot_type[0], N_DataGroups, MPI_LONG_LONG, writeTask, TAG_N, Communicator, MPI_STATUS_IGNORE);
187 }
188
189 /* fill file header */
190 header.Ntrees = ntot_type[0];
191 header.Nhalos = ntot_type[1];
192
193 header.TotNtrees = MergerTree->TotNtrees;
194 header.TotNhalos = MergerTree->TotNhalos;
195
196 header.lastsnapshotnr = MergerTree->LastSnapShotNr;
197
198 header.num_files = All.NumFilesPerSnapshot;
199}
200
201void halotrees_io::write_header_fields(hid_t handle)
202{
203 write_scalar_attribute(handle, "Ntrees_ThisFile", &header.Ntrees, H5T_NATIVE_UINT64);
204 write_scalar_attribute(handle, "Ntrees_Total", &header.TotNtrees, H5T_NATIVE_UINT64);
205
206 write_scalar_attribute(handle, "Nhalos_ThisFile", &header.Nhalos, H5T_NATIVE_UINT64);
207 write_scalar_attribute(handle, "Nhalos_Total", &header.TotNhalos, H5T_NATIVE_UINT64);
208
209 write_scalar_attribute(handle, "NumFiles", &header.num_files, H5T_NATIVE_INT);
210
211 write_scalar_attribute(handle, "LastSnapShotNr", &header.lastsnapshotnr, H5T_NATIVE_INT);
212}
213
214int halotrees_io::get_filenr_from_header(void) { return header.num_files; }
215
216void halotrees_io::set_filenr_in_header(int numfiles) { header.num_files = numfiles; }
217
218void halotrees_io::read_increase_numbers(int type, int n_for_this_task)
219{
220 switch(type)
221 {
222 case 0:
223 MergerTree->Ntrees += n_for_this_task;
224 break;
225 case 1:
226 MergerTree->Nhalos += n_for_this_task;
227 break;
228 case 2:
229 MergerTree->CatTimes += n_for_this_task;
230 break;
231
232 default:
233 Terminate("wrong group");
234 break;
235 }
236}
237
238void halotrees_io::read_file_header(const char *fname, int filenr, int readTask, int lastTask, long long *n_type, long long *ntot_type,
239 int *nstart)
240{
241 if(ThisTask == readTask)
242 {
243 if(filenr == 0 && nstart == NULL)
244 {
245 mpi_printf(
246 "\nREAD-TREES: filenr=%d, '%s' contains %lld trees out of a total of %lld, and %lld halos out of a total of %lld\n",
247 filenr, fname, header.Ntrees, header.TotNtrees, header.Nhalos, header.TotNhalos);
248 }
249 }
250
251 if(MergerTree->TotNtrees == 0)
252 {
253 MergerTree->TotNtrees = header.TotNtrees;
254 MergerTree->TotNhalos = header.TotNhalos;
255 }
256
257 for(int k = 0; k < 2; k++)
258 n_type[k] = ntot_type[k] = 0;
259
260 {
261 ntot_type[0] = header.Ntrees;
262 long long n_in_file = header.Ntrees;
263 int ntask = lastTask - readTask + 1;
264 int n_for_this_task = n_in_file / ntask;
265 if((ThisTask - readTask) < (n_in_file % ntask))
266 n_for_this_task++;
267 n_type[0] = n_for_this_task;
268
269 if(nstart)
270 memmove(&MergerTree->TreeTable[n_for_this_task], &MergerTree->TreeTable[0], MergerTree->Ntrees * sizeof(halotrees_table));
271 }
272
273 {
274 ntot_type[1] = header.Nhalos;
275 long long n_in_file = header.Nhalos;
276 int ntask = lastTask - readTask + 1;
277 int n_for_this_task = n_in_file / ntask;
278 if((ThisTask - readTask) < (n_in_file % ntask))
279 n_for_this_task++;
280 n_type[1] = n_for_this_task;
281
282 if(nstart)
283 memmove(&MergerTree->Halos[n_for_this_task], &MergerTree->Halos[0], MergerTree->Nhalos * sizeof(treehalo_type));
284 }
285
286 if(nstart)
287 *nstart = 0;
288}
289
290void halotrees_io::read_header_fields(const char *fname)
291{
292 memset(&header, 0, sizeof(header));
293
294 hid_t hdf5_file = my_H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
295 hid_t handle = my_H5Gopen(hdf5_file, "/Header");
296
297 read_scalar_attribute(handle, "Ntrees_ThisFile", &header.Ntrees, H5T_NATIVE_UINT64);
298 read_scalar_attribute(handle, "Ntrees_Total", &header.TotNtrees, H5T_NATIVE_UINT64);
299
300 read_scalar_attribute(handle, "Nhalos_ThisFile", &header.Nhalos, H5T_NATIVE_UINT64);
301 read_scalar_attribute(handle, "Nhalos_Total", &header.TotNhalos, H5T_NATIVE_UINT64);
302
303 read_scalar_attribute(handle, "NumFiles", &header.num_files, H5T_NATIVE_INT);
304
305 read_scalar_attribute(handle, "LastSnapShotNr", &header.lastsnapshotnr, H5T_NATIVE_INT);
306
307 my_H5Gclose(handle, "/Header");
308 my_H5Fclose(hdf5_file, fname);
309}
310
311void halotrees_io::get_datagroup_name(int type, char *buf)
312{
313 switch(type)
314 {
315 case 0:
316 sprintf(buf, "/TreeTable");
317 break;
318 case 1:
319 sprintf(buf, "/TreeHalos");
320 break;
321 case 2:
322 sprintf(buf, "/TreeTimes");
323 break;
324 default:
325 Terminate("wrong group");
326 break;
327 }
328}
329
330int halotrees_io::get_type_of_element(int index)
331{
332 /* empty */
333 return 0;
334}
335
336void halotrees_io::set_type_of_element(int index, int type)
337{ /* empty */
338}
339
340void *halotrees_io::get_base_address_of_structure(enum arrays array, int index)
341{
342 switch(array)
343 {
344 case A_TT:
345 return (void *)(MergerTree->TreeTable + index);
346 case A_H:
347 return (void *)(MergerTree->Halos + index);
348 case A_CT:
349 return (void *)(MergerTree->CatTimes + index);
350 default:
351 Terminate("strange, we don't expect to get here");
352 }
353}
354
355#endif
global_data_all_processes All
Definition: main.cc:40
Definition: io.h:129
#define MAXLEN_PATH_EXTRA
Definition: constants.h:301
hid_t my_H5Gopen(hid_t loc_id, const char *groupname)
Definition: hdf5_util.cc:311
hid_t my_H5Fopen(const char *fname, unsigned int flags, hid_t fapl_id)
Definition: hdf5_util.cc:297
herr_t my_H5Gclose(hid_t group_id, const char *groupname)
Definition: hdf5_util.cc:457
herr_t my_H5Fclose(hid_t file_id, const char *fname)
Definition: hdf5_util.cc:482
void write_scalar_attribute(hid_t handle, const char *attr_name, const void *buf, hid_t mem_type_id)
Definition: hdf5_util.cc:621
void read_scalar_attribute(hid_t handle, const char *attr_name, void *buf, hid_t mem_type_id)
Definition: hdf5_util.cc:589
const types_in_memory mem_len_type
Definition: io.h:94
@ READ_IF_PRESENT
Definition: io.h:124
@ SKIP_ON_READ
Definition: io.h:125
@ TREELENGTH
Definition: io.h:112
@ TREETIMES
Definition: io.h:117
@ SUBGROUPS
Definition: io.h:108
@ TREEHALOS
Definition: io.h:113
arrays
Definition: io.h:30
@ A_H
Definition: io.h:41
@ A_TT
Definition: io.h:42
@ A_CT
Definition: io.h:43
@ FILE_DOUBLE
Definition: io.h:73
@ FILE_MY_IO_FLOAT
Definition: io.h:69
@ FILE_INT64
Definition: io.h:68
@ FILE_MY_ID_TYPE
Definition: io.h:71
@ FILE_INT
Definition: io.h:67
const types_in_file file_len_type
Definition: io.h:95
@ MEM_INT
Definition: io.h:79
@ MEM_DOUBLE
Definition: io.h:84
@ MEM_MY_FLOAT
Definition: io.h:85
@ MEM_MY_ID_TYPE
Definition: io.h:81
@ MEM_INT64
Definition: io.h:80
@ FILE_IS_TREECAT
Definition: io.h:57
#define Terminate(...)
Definition: macros.h:15
#define TAG_LOCALN
Definition: mpi_utils.h:52
#define TAG_N
Definition: mpi_utils.h:25
char OutputDir[MAXLEN_PATH]
Definition: allvars.h:272