GADGET-4
fof.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 FOF_H
13 #define FOF_H
14 
15 #include "gadgetconfig.h"
16 
17 #ifdef FOF
18 
19 #include "../data/simparticles.h"
20 #include "../domain/domain.h"
21 #include "../fof/foftree.h"
22 #include "../gravtree/gravtree.h"
23 
29 template <typename partset>
30 class fof : public setcomm
31 {
32  public:
33  fof(MPI_Comm comm, partset *Tp_ptr, domain<partset> *D_ptr) : setcomm(comm)
34  {
35  Tp = Tp_ptr;
36  FoFDomain = D_ptr;
37  }
38 
39  partset *Tp;
40 
41  int Ngroups;
42  int MaxNgroups;
43  long long TotNgroups;
44 
45  int Nsubhalos;
46  int MaxNsubhalos = 0;
47  long long TotNsubhalos;
48 
49  long long Nids;
50  long long TotNids;
51 
52  double Time;
53  double Redshift;
54 
55  struct group_properties
56  {
57  long long GroupNr;
58  long long OffsetType[NTYPES];
59  MyLenType Len;
60  MyLenType LenType[NTYPES];
61  MyIDType MinID;
62  int MinIDTask;
63  int OriginTask;
64 
65  MyDouble MassType[NTYPES];
66  MyDouble Mass;
67  MyDouble Ascale;
68  MyDouble CM[3];
69  MyDouble Pos[3];
70  MyIntPosType IntPos[3];
71  MyIntPosType FirstIntPos[3];
72 
73  MyFloat Vel[3];
74 #ifdef STARFORMATION
75  MyFloat Sfr;
76 #endif
77 
78 #ifdef SUBFIND
79  int TargetTask; /* primary CPU responsible for running subfind on this group */
80  int Nsubs;
81  long long FirstSub;
82  MyFloat M_Mean200, R_Mean200;
83  MyFloat M_Crit200, R_Crit200;
84  MyFloat M_Crit500, R_Crit500;
85  MyFloat M_TopHat200, R_TopHat200;
86 #endif
87 #ifdef MERGERTREE
88  long long FileOffset;
89 #endif
90 #if defined(SUBFIND_ORPHAN_TREATMENT)
91  int LenPrevMostBnd;
92 #endif
93  };
94  group_properties *Group;
95 
96 #ifdef SUBFIND
97  struct subhalo_properties
98  {
99  MyLenType Len;
100  MyLenType LenType[NTYPES];
101  long long OffsetType[NTYPES];
103  long long GroupNr;
104  int SubRankInGr; /* local subhalo index within a given FOF group */
105  int SubParentRank;
106  MyIDType SubMostBoundID;
107  MyFloat Mass;
108  MyFloat MassType[NTYPES];
109  MyFloat SubVelDisp;
110  MyFloat SubVmax;
111  MyFloat SubVmaxRad;
112  MyFloat SubHalfMassRad;
113  MyFloat SubHalfMassRadType[NTYPES];
114  MyFloat Pos[3];
115  MyIntPosType IntPos[3];
116  MyFloat CM[3];
117  MyFloat Vel[3];
118  MyFloat Spin[3];
119 
120 #ifdef STARFORMATION
121  MyFloat Sfr;
122  MyFloat GasMassSfr;
123 #endif
124 #ifdef MERGERTREE
125  long long SubhaloNr; /* global subhalo number within a given snapshot */
126  long long UniqueGroupNr; /* global group number within whole merger tree */
127  long long FileOffset;
128  long long TreeID;
129  int TreeTask;
130  int TreeIndex;
131  MyFloat M_Crit200; /* will only be set for main subhalos in halos */
132 #endif
133 #if defined(SUBFIND_ORPHAN_TREATMENT)
134  int SubhaloLenPrevMostBnd;
135 #endif
136  };
137  subhalo_properties *Subhalo;
138 
139 #if defined(MERGERTREE)
140  /* Subhalos as they appear in the merger tree */
141  struct treehalo_t
142  {
143  /* the following pointers are always meant to be relative to the halos in the same tree */
144  int TreeDescendant;
145  int TreeFirstProgenitor;
146  int TreeNextProgenitor;
147  int TreeFirstHaloInFOFgroup;
148  int TreeNextHaloInFOFgroup;
149  int TreeProgenitor;
150  int TreeFirstDescendant;
151  int TreeNextDescendant;
152  int TreeMainProgenitor;
153 
154  long long TreeID;
155  int TreeIndex;
156 
157  /* original position of the subhalo in the subhalo group catalogue output */
158  int SnapNum;
159  long long SubhaloNr; /* number of subhalo in the full group catalogue of this snapshot */
160  long long GroupNr;
161  long long UniqueGroupNr;
162 
163  /* properties of subhalo */
164  subhalo_properties SubProp;
165  };
166 #endif
167 
168 #endif // SUBFIND
169 
170  void fof_fof(int num, const char *grpcat_basename, const char *grpcat_dirbasename, double inner_distance);
171  double fof_get_comoving_linking_length(void);
172  void fof_subfind_exchange(MPI_Comm Communicator);
173  void fof_subfind_write_file(char *fname, int writeTask, int lastTask, void *CommBuffer);
174  double fof_find_nearest_dmparticle(void);
175  double fof_find_groups(void);
176  void fof_subfind_save_groups(int num, const char *basename, const char *grpcat_dirbasename);
177  void fof_subfind_init_io_fields(void);
178  void fof_subfind_load_groups(int num);
179  void fof_assign_group_offset(void);
180  void fof_reorder_PS(int *Id, int Nstart, int N);
181 
182  private:
183  gravtree<partset> FoFGravTree;
184  foftree<partset> FoFNgbTree;
185  domain<partset> *FoFDomain;
187  int NgroupsExt;
188 
189  void fof_compile_catalogue(double inner_distance);
190  void fof_compute_group_properties(int gr, int start, int len);
191  void fof_prepare_output_order(void);
192  void fof_add_in_properties_of_group_segments(void);
193  void fof_finish_group_properties(void);
194  void fof_assign_group_numbers(void);
195  void fof_get_halo_position(MyIntPosType *intpos, double *pos);
196 
197 #if defined(LIGHTCONE_PARTICLES_GROUPS)
198  double fof_distance_to_origin(int i);
199 #endif
200 
201  public:
202  struct fof_particle_list
203  {
204  MyIDStorage MinID;
205  int MinIDTask;
206  int Pindex;
207 #if defined(LIGHTCONE_PARTICLES_GROUPS)
208  double DistanceOrigin;
209 #endif
210  };
211  fof_particle_list *FOF_PList;
212 
213  struct fof_group_list
214  {
215  MyIDStorage MinID;
216  int MinIDTask;
217  MyLenType Count;
218 #if defined(LIGHTCONE_PARTICLES_GROUPS)
219  double DistanceOrigin;
220 #endif
221  };
222  fof_group_list *FOF_GList;
223 
224  public:
225 #ifndef LEAN
226  static bool fof_compare_subfind_data_Type(const subfind_data &a, const subfind_data &b) { return a.Type < b.Type; }
227 #endif
228 
229  static bool fof_compare_subfind_data_GroupNr_SubNr_Egy_Key(const subfind_data &a, const subfind_data &b)
230  {
231  if(a.GroupNr < b.GroupNr)
232  return true;
233  if(a.GroupNr > b.GroupNr)
234  return false;
235 
236 #ifdef SUBFIND
237  if(a.SubRankInGr < b.SubRankInGr)
238  return true;
239  if(a.SubRankInGr > b.SubRankInGr)
240  return false;
241 
242  if(a.v.DM_BindingEnergy < b.v.DM_BindingEnergy)
243  return true;
244  if(a.v.DM_BindingEnergy > b.v.DM_BindingEnergy)
245  return false;
246 #endif
247 
248  return a.u.Key < b.u.Key;
249  }
250 
251 #if defined(MERGERTREE) && defined(SUBFIND)
252 
253  static bool fof_compare_subfind_data_GroupNr_SubRankInNr_BndEgy(const subfind_data &a, const subfind_data &b)
254  {
255  if(a.GroupNr < b.GroupNr)
256  return true;
257  if(a.GroupNr > b.GroupNr)
258  return false;
259 
260  if(a.SubRankInGr < b.SubRankInGr)
261  return true;
262  if(a.SubRankInGr > b.SubRankInGr)
263  return false;
264 
265  return a.v.DM_BindingEnergy < b.v.DM_BindingEnergy;
266  }
267 
268 #endif
269 
270  static bool fof_compare_subfind_data_OriginTask_OriginIndex(const subfind_data &a, const subfind_data &b)
271  {
272  if(a.OriginTask < b.OriginTask)
273  return true;
274  if(a.OriginTask > b.OriginTask)
275  return false;
276 
277  return a.OriginIndex < b.OriginIndex;
278  }
279 
280  static bool fof_compare_FOF_PList_MinID(const fof_particle_list &a, const fof_particle_list &b)
281  {
282  return a.MinID.get() < b.MinID.get();
283  }
284 
285  static bool fof_compare_FOF_GList_MinID(const fof_group_list &a, const fof_group_list &b) { return a.MinID.get() < b.MinID.get(); }
286 
287  static bool fof_compare_FOF_GList_MinIDTask(const fof_group_list &a, const fof_group_list &b) { return a.MinIDTask < b.MinIDTask; }
288 
289  static bool fof_compare_Group_Len_MinID_DiffOriginTaskMinIDTask(const group_properties &a, const group_properties &b)
290  {
291  if(a.Len > b.Len)
292  return true;
293  if(a.Len < b.Len)
294  return false;
295 
296  if(a.MinID < b.MinID)
297  return true;
298  if(a.MinID > b.MinID)
299  return false;
300 
301  return labs(a.OriginTask - a.MinIDTask) < labs(b.OriginTask - b.MinIDTask);
302  }
303 
304  static bool fof_compare_Group_OriginTask_MinID(const group_properties &a, const group_properties &b)
305  {
306  if(a.OriginTask < b.OriginTask)
307  return true;
308  if(a.OriginTask > b.OriginTask)
309  return false;
310 
311  return a.MinID < b.MinID;
312  }
313 
314  /* now comes the group catalogue created with execution of FOF */
315 
316  public:
317  static inline bool fof_compare_Group_GroupNr(const group_properties &a, const group_properties &b) { return a.GroupNr < b.GroupNr; }
318 
319  static bool fof_compare_Group_MinID(const group_properties &a, const group_properties &b) { return a.MinID < b.MinID; }
320 
321  static bool fof_compare_Group_MinIDTask(const group_properties &a, const group_properties &b) { return a.MinIDTask < b.MinIDTask; }
322 
323  /******************************************** SubFind part ****************************************/
324 #ifdef SUBFIND
325  public:
326  unsigned char *ProcessedFlag;
327 
328  unsigned long long GroupNr;
329  double Ascale;
330 
331  MPI_Comm SubComm;
332  int CommSplitColor;
333  int SubNTask, SubThisTask;
334 
335  int Ncollective;
336  int NprocsCollective;
337  int MaxSerialGroupLen;
338 
339  void subfind_density_hsml_guess(void);
340  void subfind_find_subhalos(int num, const char *basename, const char *grpcat_dirbasename);
341 
342  public:
343  struct sort_r2list
344  {
345  double r;
346  double mass;
347  };
348 
349  static bool subfind_compare_dist_rotcurve(const sort_r2list &a, const sort_r2list &b) { return a.r < b.r; }
350 
351  double subfind_density(void);
352  double subfind_overdensity(void);
353  double subfind_get_overdensity_value(int type, double ascale);
354  void subfind_save_final(int num, const char *basename, const char *grpcat_dirbasename);
355 
356  void subfind_processing(domain<partset> *SubDomain, domain_options mode);
357  void subfind_potential_compute(domain<partset> *SubDomain, int num, int *d);
358  void subfind_find_linkngb(domain<partset> *SubDomain, int num, int *list);
359  void subfind_find_nearesttwo(domain<partset> *SubDomain, int num, int *list);
360  void subfind_redetermine_groupnr(void);
361 
362  void subfind_process_groups_serially(void);
363  void subfind_distribute_particles(MPI_Comm Communicator);
364  void subfind_distribute_groups(void);
365  double subfind_get_particle_balance(void);
366  void subfind_assign_subhalo_offsettype(void);
367  void subfind_match_ids_of_previously_most_bound_ids(partset *Tp);
368 
369  double subfind_locngb_treefind(MyDouble xyz[3], int desngb, double hguess);
370  int subfind_unbind(domain<partset> *D, MPI_Comm Communicator, int *unbind_list, int len);
371 
372  int subfind_determine_sub_halo_properties(int *d, int num, subhalo_properties *subhalo, MPI_Comm Communicator);
373 
374  void subfind_hbt_single_group(domain<partset> *SubDomain, domain<partset> *SingleDomain, domain_options mode, int gr);
375 
376  struct proc_assign_data
377  {
378  long long GroupNr;
379  MyLenType Len;
380  int FirstTask;
381  int NTask;
382  };
383  proc_assign_data *ProcAssign;
384 
385  struct submp_data
386  {
387  long long GroupNr;
388  int index;
389 
390 #ifndef SUBFIND_HBT
391  MyFloat DM_Density;
392 #endif
393  };
394  submp_data *submp;
395 
396  struct cand_dat
397  {
398  location head;
399  MyLenType len;
400  MyLenType bound_length;
401 
402  int nsub;
403  int rank, subnr, parent;
404  };
405 
406  struct coll_cand_dat
407  {
408  location head;
409  MyLenType rank;
410  MyLenType len;
411  MyLenType bound_length;
412 
413  int nsub;
414  int subnr, parent;
415  };
416  coll_cand_dat *coll_candidates;
417 
418  struct SubDMData
419  {
420  double rho;
421  double vx, vy, vz;
422  double v2;
423  };
424 
425  static inline bool subfind_compare_submp_GroupNr_DM_Density(const submp_data &a, const submp_data &b)
426  {
427 #ifndef SUBFIND_HBT
428  if(a.GroupNr < b.GroupNr)
429  return true;
430  if(a.GroupNr > b.GroupNr)
431  return false;
432 
433  return (a.DM_Density > b.DM_Density);
434 #else
435  return a.GroupNr < b.GroupNr;
436 #endif
437  }
438 
439  static inline bool subfind_compare_binding_energy(const double &a, const double &b) { return a > b; }
440 
441  static inline bool subfind_compare_potential(const double &a, const double &b) { return a < b; }
442 
443  static inline bool subfind_compare_Subhalo_GroupNr_SubRankInGr(const subhalo_properties &a, const subhalo_properties &b)
444  {
445  if(a.GroupNr < b.GroupNr)
446  return true;
447  if(a.GroupNr > b.GroupNr)
448  return false;
449 
450  return a.SubRankInGr < b.SubRankInGr;
451  }
452 
453  static inline bool subfind_compare_procassign_GroupNr(const proc_assign_data &a, const proc_assign_data &b)
454  {
455  return a.GroupNr < b.GroupNr;
456  }
457 
458  private:
459  long long count_decisions;
460  long long count_different_decisions;
461 
462  struct sort_density_data
463  {
464  MyFloat density;
465  int ngbcount;
466  location index; /* this will store the task in the upper word */
467  location ngb_index1;
468  location ngb_index2;
469  approxlen PrevSizeOfSubhalo;
470  };
471  sort_density_data *sd;
472 
473  struct PPS_data
474  {
475  int index;
476  int submark;
477  };
478  PPS_data *PPS;
479 
480  void subfind_col_find_coll_candidates(long long totgrouplen);
481 
482  void subfind_poll_for_requests(void);
483 
484  int subfind_distlinklist_get_tail_set_tail_increaselen(location index, location &tail, location newtail, approxlen prevlen);
485 
486  void subfind_distlinklist_get_two_heads(location ngb_index1, location ngb_index2, location &head, location &head_attach);
487  void subfind_distlinklist_set_next(location index, location next);
488  void subfind_distlinklist_add_particle(location index);
489  void subfind_distlinklist_add_bound_particles(location index, int nsub);
490  void subfind_distlinklist_mark_particle(location index, int target, int submark);
491  void subfind_distlinklist_set_headandnext(location index, location head, location next);
492  void subfind_distlinklist_set_tailandlen(location index, location tail, MyLenType len, double prevlen);
493  void subfind_distlinklist_get_tailandlen(location index, location &tail, MyLenType &len, double &prevlen);
494  void subfind_distlinklist_set_all(location index, location head, location tail, MyLenType len, location next, approxlen prevlen);
495  location subfind_distlinklist_get_next(location index);
496  location subfind_distlinklist_get_head(location index);
497  location subfind_distlinklist_setrank_and_get_next(location index, MyLenType &rank);
498  location subfind_distlinklist_set_head_get_next(location index, location head);
499  MyLenType subfind_distlinklist_get_rank(location index);
500 
501  void subfind_get_factors(double &fac_vel_to_phys, double &fac_hubbleflow, double &fac_comov_to_phys);
502 
503  void subfind_process_single_group(domain<partset> *SubDomain, domain<partset> *SingleDomain, domain_options mode, int gr);
504  void subfind_unbind_independent_ones(domain<partset> *SingleDomain, int count);
505  double subfind_vel_to_phys_factor(void);
506 
507  void subfind_collective_printf(const char *fmt, ...)
508  {
509  if(SubNTask > 1 && SubThisTask == 0)
510  {
511  va_list l;
512  va_start(l, fmt);
513  vprintf(fmt, l);
514  va_end(l);
515  }
516  }
517 
518  static bool subfind_compare_densities(const sort_density_data &a, const sort_density_data &b) /* largest density first */
519  {
520  return a.density > b.density;
521  }
522 
523  static bool subfind_PS_compare_DM_density(const subfind_data &a, const subfind_data &b) /* largest density first */
524  {
525  return a.u.s.u.DM_Density > b.u.s.u.DM_Density;
526  }
527 
528  static bool subfind_PS_compare_origintask_originindex(const subfind_data &a, const subfind_data &b)
529  {
530  if(a.u.s.origintask < b.u.s.origintask)
531  return true;
532  if(a.u.s.origintask > b.u.s.origintask)
533  return false;
534 
535  return a.u.s.originindex < b.u.s.originindex;
536  }
537 
538  static bool subfind_compare_coll_candidates_subnr(const coll_cand_dat &a, const coll_cand_dat &b) { return a.subnr < b.subnr; }
539 
540  static bool subfind_compare_coll_candidates_nsubs(const coll_cand_dat &a, const coll_cand_dat &b) { return a.nsub < b.nsub; }
541 
542  static bool subfind_compare_coll_candidates_boundlength(const coll_cand_dat &a, const coll_cand_dat &b)
543  {
544  if(a.bound_length > b.bound_length)
545  return true;
546  if(a.bound_length < b.bound_length)
547  return false;
548 
549  return a.rank < b.rank;
550  }
551 
552  static bool subfind_compare_coll_candidates_rank(const coll_cand_dat &a, const coll_cand_dat &b)
553  {
554  if(a.rank < b.rank)
555  return true;
556  if(a.rank > b.rank)
557  return false;
558  return a.len > b.len;
559  }
560 
561  static bool subfind_compare_PPS(const PPS_data &a, const PPS_data &b) { return a.submark < b.submark; }
562 
563  MyLenType *SFLen;
564  location *SFHead;
565  location *SFNext;
566  location *SFTail;
567  double *SFPrevLen;
568 
569  int count_cand, max_coll_candidates;
570  int *unbind_list;
571 
572  int NumPartGroup;
573  int *IndexList;
574  int LocalLen;
575 
576  struct sort_as_data
577  {
578  double density;
579  int targettask;
580  long long origin;
581  };
582 
583  static bool subfind_compare_as_density(const sort_as_data &a, const sort_as_data &b) /* largest density first */
584  {
585  return a.density > b.density;
586  }
587 
588  static bool subfind_compare_as_origin(const sort_as_data &a, const sort_as_data &b) /* largest density first */
589  {
590  return a.origin < b.origin;
591  }
592 
593  struct hbt_pcand_t
594  {
595  MyHaloNrType SubhaloNr;
596  approxlen PrevSizeOfSubhalo;
597  int index;
598  };
599 
600  static bool subfind_hbt_compare_pcand_subhalonr(const hbt_pcand_t &a, const hbt_pcand_t &b) { return a.SubhaloNr < b.SubhaloNr; }
601 
602  struct hbt_subcand_t
603  {
604  MyHaloNrType SubhaloNr;
605  MyLenType len;
606  bool DoIt;
607 
608  int TargetTask;
609  int TargetIndex;
610  long long summedprevlen;
611 
612  /*
613  location head;
614  MyLenType rank;
615 
616  MyLenType bound_length;
617 
618  int nsub;
619  int subnr, parent;
620  */
621  };
622 
623  static bool subfind_hbt_compare_subcand_subhalonr(const hbt_subcand_t &a, const hbt_subcand_t &b)
624  {
625  return a.SubhaloNr < b.SubhaloNr;
626  }
627 
628  static bool subfind_hbt_compare_subcand_len(const hbt_subcand_t &a, const hbt_subcand_t &b) { return a.len < b.len; }
629 
630  static bool subfind_hbt_compare_subcand_summedprevlen(const hbt_subcand_t &a, const hbt_subcand_t &b)
631  {
632  return a.summedprevlen < b.summedprevlen;
633  }
634 
635  struct hbt_subhalo_t
636  {
637  MyLenType Len;
638  int SubRankInGr;
639  int ThisTask;
640  int ThisIndex;
641  long long SubhaloNr;
642  };
643 
644  static bool subfind_hbt_compare_subhalolist_len(const hbt_subhalo_t &a, const hbt_subhalo_t &b) { return a.Len > b.Len; }
645 
646  static bool subfind_hbt_compare_subhalolist_thistask_thisindex(const hbt_subhalo_t &a, const hbt_subhalo_t &b)
647 
648  {
649  if(a.ThisTask < b.ThisTask)
650  return true;
651  if(a.ThisTask > b.ThisTask)
652  return false;
653 
654  return a.ThisIndex < b.ThisIndex;
655  }
656 
657  static bool subfind_hbt_compare_subhalolist_prevsubhalonr(const hbt_subhalo_t &a, const hbt_subhalo_t &b)
658  {
659  return a.SubhaloNr < b.SubhaloNr;
660  }
661 
662 #endif
663 };
664 
665 inline bool is_type_primary_link_type(int type)
666 {
667  if((1 << type) & (FOF_PRIMARY_LINK_TYPES))
668  return true;
669  else
670  return false;
671 }
672 
673 inline bool is_type_secondary_link_type(int type)
674 {
675  if((1 << type) & (FOF_SECONDARY_LINK_TYPES))
676  return true;
677  else
678  return false;
679 }
680 #endif // end of FOF
681 
682 #endif
Definition: domain.h:31
#define FOF_PRIMARY_LINK_TYPES
Definition: constants.h:131
#define NTYPES
Definition: constants.h:308
#define FOF_SECONDARY_LINK_TYPES
Definition: constants.h:135
domain_options
Definition: domain.h:22
float MyDouble
Definition: dtypes.h:87
float MyFloat
Definition: dtypes.h:86
uint32_t MyIntPosType
Definition: dtypes.h:35
int MyLenType
Definition: dtypes.h:76
unsigned int MyIDType
Definition: dtypes.h:68
MyHaloNrType GroupNr
peanokey Key
union subfind_data::@0 u