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 
25 class 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