GADGET-4
mergertree.h
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#ifndef MERGERTREE_H
13#define MERGERTREE_H
14
15#ifdef MERGERTREE
16
17#include <hdf5.h>
18
19#include "../data/simparticles.h"
20#include "../fof/fof.h"
21#include "../subfind/subfind.h"
22
23#define NUM_MOST_BOUND_PARTICLES_USED_FOR_TRACKING 16 // may not be larger than 255 due to storage limits
24
25class mergertree : public setcomm
26{
27 private:
28 simparticles *Sp;
29
30 public:
31 mergertree(MPI_Comm comm, simparticles *Sp_ptr) : setcomm(comm)
32 {
33 Sp = Sp_ptr;
34 PrevTotNsubhalos = 0;
35 PrevNsubhalos = 0;
36 MtrP_NumPart = 0;
37 }
38
39 void mergertree_determine_descendants_on_the_fly(int num);
40 void descendants_in_postprocessing(int num);
41 void halotrees_construct(int lastsnapnr);
42 void get_previous_size_of_subhalo_for_each_particle(int num);
43
44 unsigned long long CurrTotNsubhalos;
45 unsigned long long PrevTotNsubhalos;
46
47 int CurrNsubhalos;
48 int PrevNsubhalos;
49
50 int MtrP_NumPart;
51 int PrevMtrP_NumPart;
52
53 int Nhalos;
54 long long TotNhalos;
55
56 int Ntrees;
57 long long TotNtrees;
58
59 int LargestHaloCount;
60 int LastSnapShotNr; // we will construct trees composed of dumps 0 to LastSnapShotNr
61
62 typedef fof<simparticles>::treehalo_t treehalo_type;
63 treehalo_type *Halos; /* This will contain the subhalos making up the merger tree information */
64
65 struct treehalo_ids_type
66 {
67 MyIDType SubMostBoundID;
68 long long TreeID;
69 };
70 treehalo_ids_type *HaloIDdata;
71
72 static bool compare_HaloIDdata_ID(const treehalo_ids_type &a, const treehalo_ids_type &b)
73 {
74 return a.SubMostBoundID < b.SubMostBoundID;
75 }
76
77 struct desc_list
78 {
79 double MaxScore;
80 long long PrevSubhaloNr;
81 long long DescSubhaloNr;
82
83 long long FirstDescSubhaloNr;
84 long long NextProgSubhaloNr;
85
86 long long FileOffset;
87 char FirstProgFlag;
88 };
89 desc_list *Descendants;
90
91 struct prog_list
92 {
93 double MaxScore;
94 long long SubhaloNr;
95
96 long long ProgSubhaloNr;
97
98 long long FirstProgSubhaloNr;
99 long long NextDescSubhaloNr;
100
101 long long MainProgSubhaloNr;
102
103 long long FileOffset;
104
105 char FirstDescFlag;
106 };
107 prog_list *Progenitors;
108
109 struct mergertree_particle_data
110 {
111 int Type;
112 MyIDType ID;
113 long long FileOffset;
114
115 long long PrevGroupNr;
116 long long PrevSubhaloNr;
117
118 long long GroupNr;
119 long long SubhaloNr;
120
121 MyLenType SubhaloLen;
122 MyLenType PrevSubhaloLen;
123
124 unsigned short RankInSubhalo;
125 unsigned short PrevRankInSubhalo;
126 };
127 mergertree_particle_data *MtrP, *PrevMtrP;
128
129 halotrees_table *TreeTable;
130
131 struct treelink_data
132 {
133 long long TreeID;
134 int TreeIndex;
135 };
136 treelink_data *TreeLink;
137
138 times_catalogue *CatTimes;
139
140 private:
141 void mergertree_determine_descendants(int num);
142 void mergertree_determine_descendants_postproc(int num);
143 void mergertree_save_progenitors(int num);
144 void mergertree_read_progenitors(int num);
145 void desc_subfind_init_io_fields(void);
146 void prog_subfind_init_io_fields(void);
147 void treelink_subfind_init_io_fields(void);
148 void mergertree_read_snap_ids(int num);
149 void mergertree_match_ids_of_previous_snap(void);
150 void mrgtr_init_io_fields(void);
151 int halotrees_join_via_descendants(int num);
152 int halotrees_join_via_progenitors(int num);
153 void halotrees_assign_global_subhalonr_and_groupnr(void);
154 void halotrees_load_catalogues(fof<simparticles> *FoF);
155 void halotrees_initial_treeassignment(void);
156 void halotrees_assign_new_treeindices(void);
157 void halotrees_save_trees(void);
158 void halotrees_save_subhalo_treelinks(void);
159 void halotrees_collect_treehalos(void);
160 void halotrees_link_trees(void);
161 void halotrees_propagate_max_branch_length_descendants(int num);
162 void halotrees_propagate_max_branch_length_progenitors(int num);
163 void halotrees_determine_mainprogenitor(void);
164 void halotrees_reshuffle(char **ptr, size_t len, int ncurrent, int ntarget);
165 void halotrees_remap_treepointers(void);
166 void mergertree_assign_group_numbers(fof<simparticles> *FoF);
167 void trees_subfind_init_io_fields(void);
168 long long halotrees_join_trees_via_fof_or_mostboundid_bridges(int mode);
169 void mergertree_match_ids_of_current_snap(void);
170
171 void mergertree_chain_up_progenitors_with_same_descendant(void);
172 void mergertree_set_first_progenitor_with_same_descendant(void);
173 void mergertree_select_maximum_score_progenitors(int nmatch);
174 void mergertree_select_maximum_score_descendants(int nmatch);
175 int mergertree_find_matching_segments_and_scores(void);
176 void mergertree_chain_up_descendants_with_same_progenitor(void);
177 void mergertree_set_first_descendant_with_same_progenitor(void);
178
179 struct subhalo_extension
180 {
181 int TreeDescendant;
182 int TreeFirstProgenitor;
183 int TreeNextProgenitor;
184 int TreeFirstHaloInFOFgroup;
185 int TreeNextHaloInFOFgroup;
186 int TreeProgenitor;
187 int TreeFirstDescendant;
188 int TreeNextDescendant;
189 int TreeMainProgenitor;
190
191 long long MaxLenProgBranch;
192 };
193
194 /* PrevTotNsubhalos is the total number of subhalos in the previous catalogue. This list is split onto
195 * the processors, with 'PrevNsubhalos' being the number of these subhalos assigned to the local MPI task.
196 */
197
198 static bool compare_MtrP_FileOffset(const mergertree_particle_data &a, const mergertree_particle_data &b)
199 {
200 return a.FileOffset < b.FileOffset;
201 }
202
203 static bool compare_MtrP_SubhaloNr(const mergertree_particle_data &a, const mergertree_particle_data &b)
204 {
205 if(a.PrevSubhaloNr < b.PrevSubhaloNr)
206 return true;
207 if(a.PrevSubhaloNr > b.PrevSubhaloNr)
208 return false;
209
210 if(a.PrevRankInSubhalo < b.PrevRankInSubhalo)
211 return true;
212 if(a.PrevRankInSubhalo > b.PrevRankInSubhalo)
213 return false;
214
215 return a.ID < b.ID;
216 }
217
218 static bool compare_Group_FileOffset(const fof<simparticles>::group_properties &a, const fof<simparticles>::group_properties &b)
219 {
220 return a.FileOffset < b.FileOffset;
221 }
222
223 static bool compare_Subhalo_FileOffset(const fof<simparticles>::subhalo_properties &a,
224 const fof<simparticles>::subhalo_properties &b)
225 {
226 return a.FileOffset < b.FileOffset;
227 }
228
229 static bool compare_MtrP_ID(const mergertree_particle_data &a, const mergertree_particle_data &b) { return a.ID < b.ID; }
230
231 struct assign_particle_data
232 {
233 MyIDType ID;
234 long long PrevSubhaloNr;
235 MyLenType PrevSubhaloLen;
236 int OriginTask;
237 int OriginIndex;
238 };
239
240 static bool compare_AssignP_ID(const assign_particle_data &a, const assign_particle_data &b) { return a.ID < b.ID; }
241
242 static bool compare_AssignP_Origin(const assign_particle_data &a, const assign_particle_data &b)
243 {
244 if(a.OriginTask < b.OriginTask)
245 return true;
246 if(a.OriginTask > b.OriginTask)
247 return false;
248
249 return a.OriginIndex < b.OriginIndex;
250 }
251
252 /* This structure is used to do the matching/identification of the descendants. First, every particle is listed here
253 * with its subhalo number and rank in the previous subhalo catalogue, while GroupNr/SubRankInGr (or equivalently the combined
254 * SubhaloNr) give the number of the subhalo they are in the new catalogue. By first sorting according to PrevSubhaloNr
255 * and then by SubhaloNr, we get all descendant candidates a previous subhalo can have. We then need to figure out
256 * which one to pick, which we do via the Score variable.
257 */
258 struct desc_partdata
259 {
260 MyHaloNrType PrevSubhaloNr; // Global subhalo number of the particle in the previous group catalogue
261 MyHaloNrType CurrSubhaloNr; // New global subhalo number in the current group catalogue
262
263 float DescScore; // auxiliary variable to score the different possible descendants
264 float ProgScore; // auxiliary variable to score the different possible progenitors
265
266 compactrank_t PrevRankInSubhalo; // Rank of particle within previous subhalo
267 compactrank_t CurrRankInSubhalo; // Rank of particle within current subhalo
268 };
269 desc_partdata *desc;
270
271 /* sort kernel, first by PrevSubhaloNr, then by SubhaloNr */
272 static bool mergertree_compare_PrevSubNr_NewSubNr(const desc_partdata &a, const desc_partdata &b)
273 {
274 if(a.PrevSubhaloNr < b.PrevSubhaloNr)
275 return true;
276 if(a.PrevSubhaloNr > b.PrevSubhaloNr)
277 return false;
278
279 return a.CurrSubhaloNr < b.CurrSubhaloNr;
280 }
281
282 static bool mergertree_compare_NewSubNr_PrevSubNr(const desc_partdata &a, const desc_partdata &b)
283 {
284 if(a.CurrSubhaloNr < b.CurrSubhaloNr)
285 return true;
286 if(a.CurrSubhaloNr > b.CurrSubhaloNr)
287 return false;
288
289 return a.PrevSubhaloNr < b.PrevSubhaloNr;
290 }
291
292 /* sort kernel */
293 static bool mergertree_compare_DescSubhaloNr(const desc_list &a, const desc_list &b)
294 {
295 if(a.DescSubhaloNr < b.DescSubhaloNr)
296 return true;
297 if(a.DescSubhaloNr > b.DescSubhaloNr)
298 return false;
299
300 return a.PrevSubhaloNr < b.PrevSubhaloNr;
301 }
302
303 /* sort kernel */
304 static bool mergertree_compare_ProgSubhaloNr(const prog_list &a, const prog_list &b)
305 {
306 if(a.ProgSubhaloNr < b.ProgSubhaloNr)
307 return true;
308 if(a.ProgSubhaloNr > b.ProgSubhaloNr)
309 return false;
310
311 return a.SubhaloNr < b.SubhaloNr;
312 }
313
314 static bool mergertree_compare_SubhaloNr(const prog_list &a, const prog_list &b) { return a.SubhaloNr < b.SubhaloNr; }
315
316 /* sort kernel */
317 static bool mergertree_compare_PrevSubhaloNr(const desc_list &a, const desc_list &b) { return a.PrevSubhaloNr < b.PrevSubhaloNr; }
318
319 /* This structure is needed to organize the information of all the group and subhalo catalogs that are read in.
320 * The array Cats[] holds a table with all the group catalogs, indexes by the snapshot number.
321 */
322 struct halo_catalogue
323 {
324 fof<simparticles>::group_properties *Group; // table of local groups
325 long long FirstGroup; // first group number on this processor
326 long long TotNgroups; // total number of groups in this catalog
327 int Ngroups; // number of groups stored on local processor
328 int *TabNgroups; // used to store a table with the group numbers on all processors
329
330 fof<simparticles>::subhalo_properties *Subhalo; // table of local subhalos
331 long long FirstSubhalo; // first subhalo number on this processor
332 long long TotNsubhalos; // total number of subhalos in catalog
333 int Nsubhalos; // local number of subhalos on this processor
334 int *TabNsubhalos; // used to store a table with the subhalo numbers on all processors
335
336 subhalo_extension *SubExt; // additional subhalo properties that we determine as part of the tree building
337
338 desc_list *Descendants; // stores descendant information
339 prog_list *Progenitors; // stores progenitor information
340 };
341 halo_catalogue *Cats;
342
343 struct tlink
344 {
345 long long UniqueGroupNr;
346 long long OrderIndex;
347
348 long long TreeID;
349 long long NewTreeID;
350
351 int TreeTask;
352 int NewTreeTask;
353
354 int OrigTask;
355 };
356
357 static bool compare_tlink_GroupNr(const tlink &a, const tlink &b) { return a.UniqueGroupNr < b.UniqueGroupNr; }
358
359 static bool compare_tlink_TreeID(const tlink &a, const tlink &b) { return a.TreeID < b.TreeID; }
360
361 static bool compare_tlink_OrigTask_OrderIndex(const tlink &a, const tlink &b)
362 {
363 if(a.OrigTask < b.OrigTask)
364 return true;
365 if(a.OrigTask > b.OrigTask)
366 return false;
367
368 return a.OrderIndex < b.OrderIndex;
369 }
370
371 static bool compare_Halos_TreeID_TreeIndex(const treehalo_type &a, const treehalo_type &b)
372 {
373 if(a.TreeID < b.TreeID)
374 return true;
375 if(a.TreeID > b.TreeID)
376 return false;
377
378 return a.TreeIndex < b.TreeIndex;
379 }
380
381 static bool compare_Halos_UniqueGroupNr_SubhaloNr(const treehalo_type &a, const treehalo_type &b)
382 {
383 if(a.UniqueGroupNr < b.UniqueGroupNr)
384 return true;
385 if(a.UniqueGroupNr > b.UniqueGroupNr)
386 return false;
387
388 return a.SubhaloNr < b.SubhaloNr;
389 }
390
391 static bool compare_Desc_FileOffset(const desc_list &a, const desc_list &b) { return a.FileOffset < b.FileOffset; }
392
393 static bool compare_Prog_FileOffset(const prog_list &a, const prog_list &b) { return a.FileOffset < b.FileOffset; }
394
395 /*--------------------------------------------------------------------------------------------------------------*/
396
397 struct data_list
398 {
399 long long targetsubhalonr;
400 long long intreeid;
401 long long originsubhalonr;
402 int origin;
403 };
404
405 static bool compare_data_list_subhalonnr(const data_list &a, const data_list &b) { return a.targetsubhalonr < b.targetsubhalonr; }
406
407 struct remap_data
408 {
409 int loc_index;
410 int new_treeindexptr;
411 long long targetsubhalonr;
412 long long originsubhalonr;
413 long long treeid;
414 long long intreeid;
415 int orig_index;
416 };
417
418 static bool compare_remap_data_subhalonr(const remap_data &a, const remap_data &b) { return a.targetsubhalonr < b.targetsubhalonr; }
419
420 static bool compare_remap_data_orig_index(const remap_data &a, const remap_data &b) { return a.orig_index < b.orig_index; }
421
422 /*--------------------------------------------------------------------------------------------------------------*/
423
424 /* the following one is used to assign consecutive indices within each tree */
425 struct assign_data
426 {
427 int origin_task;
428 int origin_num;
429 int origin_index;
430
431 long long treeid;
432 long long newtreeid;
433 long long treeindex;
434 };
435
436 /* some sort kernels */
437 static bool compare_assign_data_treeid_origin_num_origin_task_origin_index(const assign_data &a, const assign_data &b)
438 {
439 if(a.treeid < b.treeid)
440 return true;
441 if(a.treeid > b.treeid)
442 return false;
443
444 if(a.origin_num > b.origin_num)
445 return true;
446 if(a.origin_num < b.origin_num)
447 return false;
448
449 if(a.origin_task < b.origin_task)
450 return true;
451 if(a.origin_task > b.origin_task)
452 return false;
453
454 return a.origin_index < b.origin_index;
455 }
456
457 static bool compare_assign_data_origin_task_origin_num_origin_index(const assign_data &a, const assign_data &b)
458 {
459 if(a.origin_task < b.origin_task)
460 return true;
461 if(a.origin_task > b.origin_task)
462 return false;
463
464 if(a.origin_num < b.origin_num)
465 return true;
466 if(a.origin_num > b.origin_num)
467 return false;
468
469 return a.origin_index < b.origin_index;
470 }
471
472 /*--------------------------------------------------------------------------------------------------------------*/
473
474 struct halotrees_data
475 {
476 long long descendantnr;
477 long long progenitornr;
478 int loc_index;
479 int orig_order;
480
481 long long treeid;
482 int treetask;
483 };
484
485 static bool compare_halotrees_data_descendantnr(const halotrees_data &a, const halotrees_data &b)
486 {
487 return a.descendantnr < b.descendantnr;
488 }
489
490 static bool compare_halotrees_data_progenitornr(const halotrees_data &a, const halotrees_data &b)
491 {
492 return a.progenitornr < b.progenitornr;
493 }
494
495 static bool compare_halotrees_data_orig_order(const halotrees_data &a, const halotrees_data &b)
496 {
497 return a.orig_order < b.orig_order;
498 }
499
500 struct halotrees_propagate_data
501 {
502 long long DescSubhaloNr;
503 long long ProgSubhaloNr;
504 long long SubhaloNr;
505 long long MaxLenProgBranch;
506 int index;
507 int orig_order;
508 };
509
510 static bool compare_halotrees_propagate_data_orig_order(const halotrees_propagate_data &a, const halotrees_propagate_data &b)
511 {
512 return a.orig_order < b.orig_order;
513 }
514
515 static bool compare_halotrees_propagate_data_DescSubhaloNr(const halotrees_propagate_data &a, const halotrees_propagate_data &b)
516 {
517 return a.DescSubhaloNr < b.DescSubhaloNr;
518 }
519
520 static bool compare_halotrees_propagate_data_ProgSubhaloNr(const halotrees_propagate_data &a, const halotrees_propagate_data &b)
521 {
522 return a.ProgSubhaloNr < b.ProgSubhaloNr;
523 }
524
525 struct halotrees_firstprog_data
526 {
527 long long DescSubhaloNr;
528 long long SubhaloNr;
529 };
530
531 static bool compare_halotrees_firstprog_data_DescSubhaloNr(const halotrees_firstprog_data &a, const halotrees_firstprog_data &b)
532 {
533 return a.DescSubhaloNr < b.DescSubhaloNr;
534 }
535
536 struct descnr_data
537 {
538 long long DescSubhaloNr;
539 long long SubhaloNr;
540 long long CumulLen;
541 long long TreeID;
542 int TreeTask;
543 int orig_index;
544 };
545
546 static bool compare_sorted_list_descsubhalonr(const descnr_data &a, const descnr_data &b)
547 {
548 return a.DescSubhaloNr < b.DescSubhaloNr;
549 }
550
551 struct prognr_data
552 {
553 long long ProgSubhaloNr;
554 long long SubhaloNr;
555 long long TreeID;
556 int TreeTask;
557 int orig_index;
558 };
559
560 static bool compare_sorted_list_progsubhalonr(const prognr_data &a, const prognr_data &b)
561 {
562 return a.ProgSubhaloNr < b.ProgSubhaloNr;
563 }
564
565 void halotrees_select_interior_min_newtreeid(int mode, tlink *treehalos, long long totnsubs);
566};
567
568#endif
569#endif
int MyLenType
Definition: dtypes.h:76
unsigned int MyIDType
Definition: dtypes.h:68