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
29template <typename partset>
30class 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
665inline 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
673inline 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