12#include "gadgetconfig.h"
23#include "../data/allvars.h"
24#include "../data/dtypes.h"
25#include "../data/intposconvert.h"
26#include "../data/mymalloc.h"
27#include "../domain/domain.h"
28#include "../fof/fof.h"
29#include "../gravtree/gravtree.h"
30#include "../logs/timer.h"
31#include "../main/simulation.h"
32#include "../mpi_utils/mpi_utils.h"
33#include "../sort/cxxsort.h"
34#include "../sort/parallel_sort.h"
35#include "../subfind/subfind.h"
36#include "../system/system.h"
37#include "../time_integration/driftfac.h"
40void fof<simparticles>::subfind_get_factors(
double &fac_vel_to_phys,
double &fac_hubbleflow,
double &fac_comov_to_phys)
44 fac_vel_to_phys = 1.0 /
All.
Time;
52 fac_comov_to_phys = 1;
56#if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES_GROUPS)
58void fof<lcparticles>::subfind_get_factors(
double &fac_vel_to_phys,
double &fac_hubbleflow,
double &fac_comov_to_phys)
60 fac_vel_to_phys = 1.0;
62 fac_comov_to_phys = Ascale;
66template <
typename partset>
67int fof<partset>::subfind_determine_sub_halo_properties(
int *d,
int num, subhalo_properties *subhalo, MPI_Comm Communicator)
70 int commNTask, commThisTask;
71 MPI_Comm_size(Communicator, &commNTask);
72 MPI_Comm_rank(Communicator, &commThisTask);
74 double fac_vel_to_phys, fac_hubbleflow, fac_comov_to_phys;
75 subfind_get_factors(fac_vel_to_phys, fac_hubbleflow, fac_comov_to_phys);
77 typename partset::pdata *P = Tp->P;
81 long long len_type[
NTYPES];
82 for(
int j = 0; j <
NTYPES; j++)
86 halfmassradtype[j] = 0;
95 for(
int i = 0; i < num; i++)
98 if(PS[p].u.s.u.DM_Potential < minpot || minindex == -1)
100 minpot = PS[p].
u.s.
u.DM_Potential;
103 len_type[P[p].getType()]++;
106 if(P[p].getType() == 0)
107 sfr += Tp->SphP[p].Sfr;
111 MPI_Allreduce(MPI_IN_PLACE, len_type,
NTYPES, MPI_LONG_LONG, MPI_SUM, Communicator);
113 double *minpotlist = (
double *)
Mem.mymalloc(
"minpotlist", commNTask *
sizeof(
double));
114 MPI_Allgather(&minpot, 1, MPI_DOUBLE, minpotlist, 1, MPI_DOUBLE, Communicator);
118 for(
int i = 0; i < commNTask; i++)
119 if(minpotlist[i] < minpot)
122 minpot = minpotlist[mincpu];
125 Mem.myfree(minpotlist);
132 if(commThisTask == mincpu)
133 for(
int j = 0; j < 3; j++)
134 intpos[j] = P[minindex].IntPos[j];
136 MPI_Bcast(intpos, 3 *
sizeof(
MyIntPosType), MPI_BYTE, mincpu, Communicator);
139 MPI_Allreduce(MPI_IN_PLACE, &sfr, 1, MPI_DOUBLE, MPI_SUM, Communicator);
148 for(
int i = 0; i < num; i++)
151 if(PS[p].v.DM_BindingEnergy < minpot || minindex == -1)
153 minpot = PS[p].v.DM_BindingEnergy;
160 minpotlist = (
double *)
Mem.mymalloc(
"minpotlist", commNTask *
sizeof(
double));
161 MPI_Allgather(&minpot, 1, MPI_DOUBLE, minpotlist, 1, MPI_DOUBLE, Communicator);
165 for(
int i = 0; i < commNTask; i++)
166 if(minpotlist[i] < minpot)
169 minpot = minpotlist[mincpu];
172 Mem.myfree(minpotlist);
179 if(commThisTask == mincpu)
181 mostboundid = P[minindex].ID.get();
182#if defined(SUBFIND_ORPHAN_TREATMENT)
183 if(!P[minindex].ID.is_previously_most_bound())
185 P[minindex].ID.mark_as_formerly_most_bound();
191 MPI_Bcast(&mostboundid,
sizeof(mostboundid), MPI_BYTE, mincpu, Communicator);
196 double s[3] = {0, 0, 0}, v[3] = {0, 0, 0};
199#if defined(SUBFIND_ORPHAN_TREATMENT)
200 int totprevmostboundlen = 0;
203 for(
int i = 0; i < num; i++)
208 Tp->nearest_image_intpos_to_pos(P[p].IntPos, intpos, dxyz);
210 s[0] += Tp->P[p].getMass() * dxyz[0];
211 s[1] += Tp->P[p].getMass() * dxyz[1];
212 s[2] += Tp->P[p].getMass() * dxyz[2];
214 for(
int j = 0; j < 3; j++)
215 v[j] += Tp->P[p].getMass() * P[p].Vel[j];
217 mass += Tp->P[p].getMass();
219 int ptype = P[p].getType();
220 mass_tab[ptype] += Tp->P[p].getMass();
221#if defined(SUBFIND_ORPHAN_TREATMENT)
222 if(P[p].ID.is_previously_most_bound())
223 totprevmostboundlen++;
227 double stot[3], vtot[3], masstot, mass_tabtot[
NTYPES];
229 MPI_Allreduce(s, stot, 3, MPI_DOUBLE, MPI_SUM, Communicator);
230 MPI_Allreduce(&mass, &masstot, 1, MPI_DOUBLE, MPI_SUM, Communicator);
231 MPI_Allreduce(v, vtot, 3, MPI_DOUBLE, MPI_SUM, Communicator);
232 MPI_Allreduce(mass_tab, mass_tabtot,
NTYPES, MPI_DOUBLE, MPI_SUM, Communicator);
234#if defined(SUBFIND_ORPHAN_TREATMENT)
235 MPI_Allreduce(MPI_IN_PLACE, &totprevmostboundlen, 1, MPI_INT, MPI_SUM, Communicator);
239 for(
int j = 0; j < 3; j++)
245 for(
int j = 0; j <
NTYPES; j++)
246 mass_tab[j] = mass_tabtot[j];
249 for(
int j = 0; j < 3; j++)
253 vel[j] = fac_vel_to_phys * v[j];
257 Tp->pos_to_signedintpos(s, off);
261 int_cm[0] = off[0] + intpos[0];
262 int_cm[1] = off[1] + intpos[1];
263 int_cm[2] = off[2] + intpos[2];
266 Tp->intpos_to_pos(int_cm, cm);
268 double disp = 0, lx = 0, ly = 0, lz = 0;
270 sort_r2list *rr_list = (sort_r2list *)
Mem.mymalloc(
"rr_list",
sizeof(sort_r2list) * (num + 1));
272 for(
int i = 0; i < num; i++)
280 Tp->nearest_image_intpos_to_pos(P[p].IntPos, int_cm, dx);
282 dx[0] *= fac_comov_to_phys;
283 dx[1] *= fac_comov_to_phys;
284 dx[2] *= fac_comov_to_phys;
286 for(
int j = 0; j < 3; j++)
288 dv[j] = fac_vel_to_phys * (P[p].Vel[j] - v[j]);
289 dv[j] += fac_hubbleflow * dx[j];
291 disp += Tp->P[p].getMass() * dv[j] * dv[j];
294 lx += Tp->P[p].getMass() * (dx[1] * dv[2] - dx[2] * dv[1]);
295 ly += Tp->P[p].getMass() * (dx[2] * dv[0] - dx[0] * dv[2]);
296 lz += Tp->P[p].getMass() * (dx[0] * dv[1] - dx[1] * dv[0]);
301 Tp->nearest_image_intpos_to_pos(P[p].IntPos, intpos, dxyz);
303 for(
int j = 0; j < 3; j++)
304 dxyz[j] *= fac_comov_to_phys;
306 double r2 = dxyz[0] * dxyz[0] + dxyz[1] * dxyz[1] + dxyz[2] * dxyz[2];
310 rr_list[i].mass = Tp->P[p].getMass();
314 double spintot[3], disploc = disp;
315 double spinloc[3] = {lx, ly, lz};
316 MPI_Allreduce(spinloc, spintot, 3, MPI_DOUBLE, MPI_SUM, Communicator);
317 MPI_Allreduce(&disploc, &disp, 1, MPI_DOUBLE, MPI_SUM, Communicator);
322 double spin[3] = {lx / mass, ly / mass, lz / mass};
324 double veldisp =
sqrt(disp / (3 * mass));
326 mycxxsort_parallel(rr_list, rr_list + num, subfind_compare_dist_rotcurve, Communicator);
329 for(
int i = 1; i < num; i++)
330 rr_list[i].mass = rr_list[i - 1].mass + rr_list[i].mass;
332 double halfmassrad = 0;
333 double max = 0, maxrad = 0;
335 double mass_part = 0;
337 mass_part = rr_list[num - 1].mass;
338 double *masslist = (
double *)
Mem.mymalloc(
"masslist", commNTask *
sizeof(
double));
339 MPI_Allgather(&mass_part, 1, MPI_DOUBLE, masslist, 1, MPI_DOUBLE, Communicator);
341 double massbefore = 0;
342 for(
int i = 0; i < commThisTask; i++)
343 massbefore += masslist[i];
345 for(
int i = 0; i < num; i++)
346 rr_list[i].mass += massbefore;
348 Mem.myfree(masslist);
352 double halfmassrad_loc = 0;
353 sort_r2list *rr_lowlist = (sort_r2list *)
Mem.mymalloc(
"rr_lowlist", commNTask *
sizeof(sort_r2list));
354 sort_r2list low_element;
356 low_element = rr_list[0];
359 low_element.mass = 0;
362 MPI_Allgather(&low_element,
sizeof(sort_r2list), MPI_BYTE, rr_lowlist,
sizeof(sort_r2list), MPI_BYTE, Communicator);
364 rr_list[num].mass = 0;
367 for(
int j = commThisTask + 1; j < commNTask; j++)
368 if(rr_lowlist[j].mass > 0)
370 rr_list[num] = rr_lowlist[j];
374 Mem.myfree(rr_lowlist);
376 int *numlist = (
int *)
Mem.mymalloc(
"numlist", commNTask *
sizeof(
int));
377 MPI_Allgather(&num, 1, MPI_INT, numlist, 1, MPI_INT, Communicator);
380 for(
int i = 0; i < commThisTask; i++)
381 nbefore += numlist[i];
383 for(
int i = num - 1; i >= 0; i--)
385 if((i + nbefore) > 5 && rr_list[i].mass > max * rr_list[i].r)
387 max = rr_list[i].mass / rr_list[i].r;
388 maxrad = rr_list[i].r;
391 if(rr_list[i].mass < 0.5 * mass && rr_list[i + 1].mass >= 0.5 * mass)
392 halfmassrad_loc = 0.5 * (rr_list[i].r + rr_list[i + 1].r);
397 MPI_Allreduce(&halfmassrad_loc, &halfmassrad, 1, MPI_DOUBLE, MPI_MAX, Communicator);
398 double *maxlist = (
double *)
Mem.mymalloc(
"maxlist", commNTask *
sizeof(
double));
399 double *maxradlist = (
double *)
Mem.mymalloc(
"maxradlist", commNTask *
sizeof(
double));
400 MPI_Allgather(&max, 1, MPI_DOUBLE, maxlist, 1, MPI_DOUBLE, Communicator);
401 MPI_Allgather(&maxrad, 1, MPI_DOUBLE, maxradlist, 1, MPI_DOUBLE, Communicator);
404 for(
int i = 0; i < commNTask; i++)
409 maxrad = maxradlist[i];
412 Mem.myfree(maxradlist);
416 double vmaxrad = maxrad;
423 for(
int j = 0; j <
NTYPES; j++)
426 for(
int i = 0; i < num; i++)
429 int ptype = P[p].getType();
430 len_type_loc[ptype]++;
433 for(
int type = 0; type <
NTYPES; type++)
435 sort_r2list *rr_list = (sort_r2list *)
Mem.mymalloc(
"rr_list",
sizeof(sort_r2list) * (len_type_loc[type] + 1));
437 for(
int i = 0; i < num; i++)
441 int ptype = P[p].getType();
446 Tp->nearest_image_intpos_to_pos(P[p].IntPos, intpos, dxyz);
448 for(
int j = 0; j < 3; j++)
449 dxyz[j] *= fac_comov_to_phys;
451 double r2 = dxyz[0] * dxyz[0] + dxyz[1] * dxyz[1] + dxyz[2] * dxyz[2];
454 rr_list[itmp].mass = Tp->P[p].getMass();
460 if(itmp != len_type_loc[type])
461 Terminate(
"should not occur: %d %d", itmp, len_type_loc[type]);
463 mycxxsort_parallel(rr_list, rr_list + len_type_loc[type], subfind_compare_dist_rotcurve, Communicator);
466 for(
int i = 1; i < len_type_loc[type]; i++)
467 rr_list[i].mass = rr_list[i - 1].mass + rr_list[i].mass;
469 double mass_part = 0;
470 if(len_type_loc[type])
471 mass_part = rr_list[len_type_loc[type] - 1].mass;
472 double *masslist = (
double *)
Mem.mymalloc(
"masslist", commNTask *
sizeof(
double));
473 MPI_Allgather(&mass_part, 1, MPI_DOUBLE, masslist, 1, MPI_DOUBLE, Communicator);
475 double massbefore = 0;
476 for(
int i = 0; i < commThisTask; i++)
477 massbefore += masslist[i];
479 for(
int i = 0; i < len_type_loc[type]; i++)
480 rr_list[i].mass += massbefore;
482 Mem.myfree(masslist);
485 double halfmassrad_loc = 0;
486 sort_r2list *rr_lowlist = (sort_r2list *)
Mem.mymalloc(
"rr_lowlist", commNTask *
sizeof(sort_r2list));
487 sort_r2list low_element;
488 if(len_type_loc[type] > 0)
489 low_element = rr_list[0];
492 low_element.mass = 0;
496 MPI_Allgather(&low_element,
sizeof(sort_r2list), MPI_BYTE, rr_lowlist,
sizeof(sort_r2list), MPI_BYTE, Communicator);
498 rr_list[len_type_loc[type]].mass = 0;
499 rr_list[len_type_loc[type]].r = 0;
500 for(
int j = commThisTask + 1; j < commNTask; j++)
501 if(rr_lowlist[j].mass > 0)
503 rr_list[len_type_loc[type]] = rr_lowlist[j];
507 Mem.myfree(rr_lowlist);
509 for(
int i = len_type_loc[type] - 1; i >= 0; i--)
511 if(rr_list[i].mass < 0.5 * mass_tab[type] && rr_list[i + 1].mass >= 0.5 * mass_tab[type])
512 halfmassrad_loc = 0.5 * (rr_list[i].r + rr_list[i + 1].r);
515 MPI_Allreduce(&halfmassrad_loc, &halfmassradtype[type], 1, MPI_DOUBLE, MPI_MAX, Communicator);
522 double gasMassSfr = 0;
523 for(
int i = 0; i < num; i++)
527 if(P[p].getType() == 0)
528 if(Tp->SphP[p].Sfr > 0)
529 gasMassSfr += P[p].getMass();
534 double gasMassSfrtot;
535 MPI_Allreduce(&gasMassSfr, &gasMassSfrtot, 1, MPI_DOUBLE, MPI_SUM, Communicator);
536 gasMassSfr = gasMassSfrtot;
543 if(commThisTask == 0)
545 subhalo->Len = totlen;
546 subhalo->Mass = mass;
548 for(
int j = 0; j <
NTYPES; j++)
550 subhalo->MassType[j] = mass_tab[j];
551 subhalo->LenType[j] = len_type[j];
552 subhalo->SubHalfMassRadType[j] = halfmassradtype[j];
556 fof_get_halo_position(intpos, pos);
558 for(
int j = 0; j < 3; j++)
560 subhalo->IntPos[j] = intpos[j];
561 subhalo->Pos[j] = pos[j];
562 subhalo->Vel[j] = vel[j];
563 subhalo->CM[j] = cm[j];
564 subhalo->Spin[j] = spin[j];
567 subhalo->SubMostBoundID = mostboundid;
568 subhalo->SubVelDisp = veldisp;
569 subhalo->SubVmax = vmax;
570 subhalo->SubVmaxRad = vmaxrad;
571 subhalo->SubHalfMassRad = halfmassrad;
573#if defined(SUBFIND_ORPHAN_TREATMENT)
574 subhalo->SubhaloLenPrevMostBnd = totprevmostboundlen;
578 subhalo->GasMassSfr = gasMassSfr;
586#include "../data/simparticles.h"
587template class fof<simparticles>;
589#if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES_GROUPS)
590#include "../data/lcparticles.h"
591template class fof<lcparticles>;
global_data_all_processes All
static double hubble_function(double a)
#define MAX_DOUBLE_NUMBER
int32_t MySignedIntPosType
void sumup_large_ints(int n, int *src, long long *res, MPI_Comm comm)
double mycxxsort_parallel(T *begin, T *end, Comp comp, MPI_Comm comm)
int ComovingIntegrationOn