12#include "gadgetconfig.h"
16#include <gsl/gsl_rng.h>
27#include "../data/allvars.h"
28#include "../data/dtypes.h"
29#include "../data/mymalloc.h"
30#include "../fof/fof.h"
31#include "../fof/fof_io.h"
32#include "../io/hdf5_util.h"
34#include "../logs/timer.h"
35#include "../main/main.h"
36#include "../main/simulation.h"
37#include "../mergertree/io_descendant.h"
38#include "../mergertree/io_halotrees.h"
39#include "../mergertree/io_progenitors.h"
40#include "../mergertree/io_treelinks.h"
41#include "../mergertree/mergertree.h"
42#include "../mpi_utils/mpi_utils.h"
43#include "../sort/parallel_sort.h"
44#include "../subfind/subfind.h"
45#include "../system/system.h"
49void mergertree::halotrees_construct(
int lastsnapnr)
52 fof<simparticles> FoF{Communicator, Sp, &Domain};
54 LastSnapShotNr = lastsnapnr;
56 Cats = (halo_catalogue *)
Mem.mymalloc_clear(
"Cats",
sizeof(halo_catalogue) * (LastSnapShotNr + 1));
60 halotrees_load_catalogues(&FoF);
61 mpi_printf(
"\nMERGERTREE: Catalogues loaded\n");
64 halotrees_assign_global_subhalonr_and_groupnr();
65 mpi_printf(
"\nMERGERTREE: SubhaloNr assigned\n");
69 halotrees_initial_treeassignment();
70 mpi_printf(
"\nMERGERTREE: Initial tree assignment\n");
73 halotrees_link_trees();
74 mpi_printf(
"\nMERGERTREE: Halo tree linked\n");
78 halotrees_determine_mainprogenitor();
79 mpi_printf(
"\nMERGERTREE: Determined the main progenitor\n");
83 halotrees_assign_new_treeindices();
84 mpi_printf(
"\nMERGERTREE: New tree indices assigned\n");
88 halotrees_remap_treepointers();
89 mpi_printf(
"\nMERGERTREE: Remapping done\n");
92 halotrees_collect_treehalos();
93 mpi_printf(
"\nMERGERTREE: Treehalos collected\n\n");
96 halotrees_io TreesIO{
this, this->Communicator,
All.
SnapFormat};
97 TreesIO.halotrees_save_trees();
99 mpi_printf(
"\nMERGERTREE: Trees saved: A total number of %lld subhalos have been assembled in %lld trees.", TotNhalos, TotNtrees);
100 mpi_printf(
"\nMERGERTREE: Largest tree contains %d halos.\n\n", LargestHaloCount);
103 halotrees_save_subhalo_treelinks();
104 mpi_printf(
"\nMERGERTREE: Tree links saved\n\n");
109void mergertree::halotrees_load_catalogues(fof<simparticles> *FoF)
112 for(
int num = 0; num <= LastSnapShotNr; num++)
116 FoF_IO.fof_subfind_load_groups(num);
121 mycxxsort_parallel(FoF->Group, FoF->Group + FoF->Ngroups, compare_Group_FileOffset, Communicator);
122 mycxxsort_parallel(FoF->Subhalo, FoF->Subhalo + FoF->Nsubhalos, compare_Subhalo_FileOffset, Communicator);
124 if(FoF_IO.LegacyFormat)
126 mpi_printf(
"\nFOF/SUBFIND: Legacy format from Arepo detected, trying to adjust for this.\n");
127 FoF->subfind_redetermine_groupnr();
128 FoF->fof_assign_group_offset();
129 FoF->subfind_assign_subhalo_offsettype();
133 Cats[num].Ngroups = FoF->Ngroups;
134 Cats[num].TotNgroups = FoF->TotNgroups;
136 Cats[num].Nsubhalos = FoF->Nsubhalos;
137 Cats[num].TotNsubhalos = FoF->TotNsubhalos;
139 CatTimes[num].Time = FoF->Time;
140 CatTimes[num].Redshift = FoF->Redshift;
144 Cats[num].Group = (fof<simparticles>::group_properties *)
Mem.mymalloc_movable(
145 &Cats[num].Group,
"Cats[num].Group", FoF->Ngroups *
sizeof(fof<simparticles>::group_properties));
146 memcpy(Cats[num].Group, FoF->Group, FoF->Ngroups *
sizeof(fof<simparticles>::group_properties));
147 Mem.myfree_movable(FoF->Group);
149 Cats[num].Subhalo = (fof<simparticles>::subhalo_properties *)
Mem.mymalloc_movable(
150 &Cats[num].Subhalo,
"Subhalo", Cats[num].Nsubhalos *
sizeof(fof<simparticles>::subhalo_properties));
151 memcpy(Cats[num].Subhalo, FoF->Subhalo, Cats[num].Nsubhalos *
sizeof(fof<simparticles>::subhalo_properties));
152 Mem.myfree_movable(FoF->Subhalo);
156 (subhalo_extension *)
Mem.mymalloc_movable(&Cats[num].SubExt,
"Cats[num].SubExt", FoF->Nsubhalos *
sizeof(subhalo_extension));
160 for(
int num = 0; num < LastSnapShotNr; num++)
163 descendant_io DescIO{
this, this->Communicator,
All.
SnapFormat};
164 DescIO.mergertree_read_descendants(num);
167 mycxxsort_parallel(Descendants, Descendants + DescIO.Nsubhalos, compare_Desc_FileOffset, Communicator);
169 if(DescIO.TotNsubhalos != Cats[num].TotNsubhalos)
170 Terminate(
"inconsistency: DescIO.TotNsubhalos=%lld != Cats[num].TotNsubhalos=%lld", DescIO.TotNsubhalos,
171 Cats[num].TotNsubhalos);
176 halotrees_reshuffle((
char **)&Descendants,
sizeof(desc_list), DescIO.Nsubhalos, Cats[num].Nsubhalos);
182 Cats[num].Descendants =
183 (desc_list *)
Mem.mymalloc_movable(&Cats[num].Descendants,
"Cats[num].Descendants", Cats[num].Nsubhalos *
sizeof(desc_list));
184 memcpy(Cats[num].Descendants, Descendants, Cats[num].Nsubhalos *
sizeof(desc_list));
185 Mem.myfree_movable(Descendants);
189 for(
int num = 1; num <= LastSnapShotNr; num++)
192 progenitors_io ProgIO{
this, this->Communicator,
All.
SnapFormat};
193 ProgIO.mergertree_read_progenitors(num);
196 mycxxsort_parallel(Progenitors, Progenitors + ProgIO.Nsubhalos, compare_Prog_FileOffset, Communicator);
198 if(ProgIO.TotNsubhalos != Cats[num].TotNsubhalos)
199 Terminate(
"inconsistency: ProgIO.TotNsubhalos=%lld != Cats[num].TotNsubhalos=%lld", ProgIO.TotNsubhalos,
200 Cats[num].TotNsubhalos);
205 halotrees_reshuffle((
char **)&Progenitors,
sizeof(prog_list), ProgIO.Nsubhalos, Cats[num].Nsubhalos);
211 Cats[num].Progenitors =
212 (prog_list *)
Mem.mymalloc_movable(&Cats[num].Progenitors,
"Cats[num].Progenitors", Cats[num].Nsubhalos *
sizeof(prog_list));
213 memcpy(Cats[num].Progenitors, Progenitors, Cats[num].Nsubhalos *
sizeof(prog_list));
214 Mem.myfree_movable(Progenitors);
218void mergertree::halotrees_save_subhalo_treelinks(
void)
220 for(
int num = 0; num <= LastSnapShotNr; num++)
222 treelinks_io TreeLinkIO{
this, this->Communicator,
All.
SnapFormat};
224 TreeLinkIO.Nsubhalos = Cats[num].Nsubhalos;
225 TreeLinkIO.TotNsubhalos = Cats[num].TotNsubhalos;
227 TreeLink = (treelink_data *)
Mem.mymalloc(
"TreeLink", TreeLinkIO.Nsubhalos *
sizeof(treelink_data));
228 for(
int i = 0; i < TreeLinkIO.Nsubhalos; i++)
230 TreeLink[i].TreeID = Cats[num].Subhalo[i].TreeID;
231 TreeLink[i].TreeIndex = Cats[num].Subhalo[i].TreeIndex;
235 TreeLinkIO.treelinks_save(num);
237 Mem.myfree(TreeLink);
245void mergertree::halotrees_assign_global_subhalonr_and_groupnr(
void)
247 long long grprev = 0;
249 for(
int num = 0; num <= LastSnapShotNr; num++)
251 Cats[num].TabNgroups = (
int *)
Mem.mymalloc(
"Cats[num].TabNgroups", NTask *
sizeof(
int));
252 MPI_Allgather(&Cats[num].Ngroups, 1, MPI_INT, Cats[num].TabNgroups, 1, MPI_INT, Communicator);
254 Cats[num].TabNsubhalos = (
int *)
Mem.mymalloc(
"Cats[num].TabNsubhalos", NTask *
sizeof(
int));
255 MPI_Allgather(&Cats[num].Nsubhalos, 1, MPI_INT, Cats[num].TabNsubhalos, 1, MPI_INT, Communicator);
257 long long subprev = 0;
259 for(
int i = 0; i < ThisTask; i++)
260 subprev += Cats[num].TabNsubhalos[i];
262 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
263 Cats[num].Subhalo[i].SubhaloNr = subprev + i;
270 long long nbefore = 0;
272 for(
int i = 0; i < ThisTask; i++)
273 nbefore += Cats[num].TabNgroups[i];
275 for(
int i = 0; i < Cats[num].Ngroups; i++)
276 Cats[num].Group[i].GroupNr = nbefore + i;
279 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
280 Cats[num].Subhalo[i].UniqueGroupNr = Cats[num].Subhalo[i].GroupNr + grprev;
282 grprev += Cats[num].TotNgroups;
286 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
287 Cats[num].Subhalo[i].M_Crit200 = 0;
289 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
290 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
291 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
292 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
301 exch_data *export_data = NULL, *import_data = NULL;
302 int nimport = 0, nexport = 0;
305 for(
int mode = 0; mode < 2; mode++)
307 for(
int i = 0; i < NTask; i++)
311 long long ngroup_previous = 0;
313 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
316 if(Cats[num].Subhalo[i].SubRankInGr == 0)
318 while(target < NTask - 1 && Cats[num].Subhalo[i].GroupNr >= (ngroup_previous + Cats[num].TabNgroups[target]))
320 ngroup_previous += Cats[num].TabNgroups[target];
325 Send_count[target]++;
328 int off = Send_offset[target] + Send_count[target]++;
330 export_data[off].loc_index = i;
331 export_data[off].GroupNr = Cats[num].Subhalo[i].GroupNr;
338 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
339 Recv_offset[0] = Send_offset[0] = 0;
340 for(
int j = 0; j < NTask; j++)
342 nimport += Recv_count[j];
343 nexport += Send_count[j];
346 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
347 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
351 export_data = (exch_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(exch_data));
352 import_data = (exch_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(exch_data));
357 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
359 int recvTask = ThisTask ^ ngrp;
361 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
362 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(exch_data), MPI_BYTE, recvTask,
363 TAG_DENS_B, &import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(exch_data), MPI_BYTE,
364 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
367 long long firstgrnr = 0;
368 for(
int i = 0; i < ThisTask; i++)
369 firstgrnr += Cats[num].TabNgroups[i];
373 for(
int i = 0; i < nimport; i++)
375 int index = import_data[i].GroupNr - firstgrnr;
377 if(Cats[num].Group[index].GroupNr != import_data[i].GroupNr)
379 "bummer: num=%d i=%d Cats[num].Ngroups=%d nimport=%d index=%d Cats[num].Group[index].GroupNr=%lld "
380 "import_data[i].GroupNr=%lld\n",
381 num, i, Cats[num].Ngroups, nimport, index, Cats[num].Group[index].GroupNr, import_data[i].GroupNr);
383 import_data[i].M_Crit200 = Cats[num].Group[index].M_Crit200;
387 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
389 int recvTask = ThisTask ^ ngrp;
391 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
392 myMPI_Sendrecv(&import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(exch_data), MPI_BYTE, recvTask,
393 TAG_DENS_B, &export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(exch_data), MPI_BYTE,
394 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
398 for(
int i = 0; i < nexport; i++)
399 Cats[num].Subhalo[export_data[i].loc_index].M_Crit200 = export_data[i].M_Crit200;
401 Mem.myfree(import_data);
402 Mem.myfree(export_data);
404 Mem.myfree(Recv_offset);
405 Mem.myfree(Recv_count);
406 Mem.myfree(Send_offset);
407 Mem.myfree(Send_count);
413void mergertree::halotrees_initial_treeassignment(
void)
415 long long previous = 0;
416 for(
int num = LastSnapShotNr; num >= 0; num--)
418 long long prevtask = 0;
419 for(
int i = 0; i < ThisTask; i++)
420 prevtask += Cats[num].TabNsubhalos[i];
422 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
425 Cats[num].Subhalo[i].TreeID = previous + prevtask + i;
428 previous += Cats[num].TotNsubhalos;
432void mergertree::halotrees_select_interior_min_newtreeid(
int mode, tlink *treehalos,
long long totnsubs)
434 for(
int backforth = -1; backforth <= 1; backforth += 2)
443 while(i >= 0 && i <= totnsubs - 2)
445 if((mode == 0 && treehalos[i].UniqueGroupNr == treehalos[i + 1].UniqueGroupNr) ||
446 (mode == 1 && treehalos[i].TreeID == treehalos[i + 1].TreeID))
448 if(treehalos[i].NewTreeID > treehalos[i + 1].NewTreeID)
450 treehalos[i].NewTreeID = treehalos[i + 1].NewTreeID;
451 treehalos[i].NewTreeTask = treehalos[i + 1].NewTreeTask;
453 else if(treehalos[i].NewTreeID < treehalos[i + 1].NewTreeID)
455 treehalos[i + 1].NewTreeID = treehalos[i].NewTreeID;
456 treehalos[i + 1].NewTreeTask = treehalos[i].NewTreeTask;
467long long mergertree::halotrees_join_trees_via_fof_or_mostboundid_bridges(
int mode)
469 long long totnsubs = 0;
471 for(
int num = 0; num <= LastSnapShotNr; num++)
472 totnsubs += Cats[num].Nsubhalos;
474 tlink *treehalos = (tlink *)
Mem.mymalloc(
"treehalos", (totnsubs + 1) *
sizeof(tlink));
478 for(
int num = 0; num <= LastSnapShotNr; num++)
479 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
481 treehalos[count].TreeID = Cats[num].Subhalo[i].TreeID;
482 treehalos[count].TreeTask = Cats[num].Subhalo[i].TreeTask;
484 treehalos[count].NewTreeID = Cats[num].Subhalo[i].TreeID;
485 treehalos[count].NewTreeTask = Cats[num].Subhalo[i].TreeTask;
487 treehalos[count].OrigTask = ThisTask;
488 treehalos[count].OrderIndex = count;
491 treehalos[count].UniqueGroupNr = Cats[num].Subhalo[i].UniqueGroupNr;
493 treehalos[count].UniqueGroupNr = Cats[num].Subhalo[i].SubMostBoundID;
498 long long *count_list = (
long long *)
Mem.mymalloc(
"count_list", NTask *
sizeof(
long long));
499 MPI_Allgather(&totnsubs,
sizeof(
long long), MPI_BYTE, count_list,
sizeof(
long long), MPI_BYTE, Communicator);
502 for(
int i = ThisTask + 1; i < NTask; i++)
503 if(count_list[i] > 0)
510 for(
int i = ThisTask - 1; i >= 0; i--)
511 if(count_list[i] > 0)
517 tlink *elem_first = (tlink *)
Mem.mymalloc(
"elem_first", NTask *
sizeof(tlink));
518 tlink *elem_last = (tlink *)
Mem.mymalloc(
"elem_last", NTask *
sizeof(tlink));
520 for(
int mode = 0; mode < 2; mode++)
525 mycxxsort_parallel(treehalos, treehalos + totnsubs, compare_tlink_GroupNr, Communicator);
526 halotrees_select_interior_min_newtreeid(mode, treehalos, totnsubs);
531 mycxxsort_parallel(treehalos, treehalos + totnsubs, compare_tlink_TreeID, Communicator);
532 halotrees_select_interior_min_newtreeid(mode, treehalos, totnsubs);
535 long long totchanges = 0;
542 MPI_Allgather(&treehalos[0],
sizeof(tlink), MPI_BYTE, elem_first,
sizeof(tlink), MPI_BYTE, Communicator);
543 MPI_Allgather(&treehalos[totnsubs > 0 ? totnsubs - 1 : 0],
sizeof(tlink), MPI_BYTE, elem_last,
sizeof(tlink), MPI_BYTE,
546 if(prev_task >= 0 && totnsubs > 0 &&
547 ((mode == 0 && elem_last[prev_task].UniqueGroupNr == treehalos[0].UniqueGroupNr) ||
548 (mode == 1 && elem_last[prev_task].TreeID == treehalos[0].TreeID)) &&
549 elem_last[prev_task].NewTreeID < treehalos[0].NewTreeID)
551 treehalos[0].NewTreeID = elem_last[prev_task].NewTreeID;
552 treehalos[0].NewTreeTask = elem_last[prev_task].NewTreeTask;
556 if(next_task >= 0 && totnsubs > 0 &&
557 ((mode == 0 && elem_first[next_task].UniqueGroupNr == treehalos[totnsubs - 1].UniqueGroupNr) ||
558 (mode == 1 && elem_first[next_task].TreeID == treehalos[totnsubs - 1].TreeID)) &&
559 elem_first[next_task].NewTreeID < treehalos[totnsubs - 1].NewTreeID)
561 treehalos[totnsubs - 1].NewTreeID = elem_first[next_task].NewTreeID;
562 treehalos[totnsubs - 1].NewTreeTask = elem_first[next_task].NewTreeTask;
566 halotrees_select_interior_min_newtreeid(mode, treehalos, totnsubs);
571 Terminate(
"too many iterations. mode=%d changes=%d", mode, changes);
573 while(totchanges > 0);
576 Mem.myfree(elem_last);
577 Mem.myfree(elem_first);
578 Mem.myfree(count_list);
581 mycxxsort_parallel(treehalos, treehalos + totnsubs, compare_tlink_OrigTask_OrderIndex, Communicator);
588 for(
int num = 0; num <= LastSnapShotNr; num++)
589 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
591 if(treehalos[count].NewTreeID != treehalos[count].TreeID)
593 Cats[num].Subhalo[i].TreeID = treehalos[count].NewTreeID;
594 Cats[num].Subhalo[i].TreeTask = treehalos[count].NewTreeTask;
602 Mem.myfree(treehalos);
609void mergertree::halotrees_link_trees(
void)
613 long long changesA = 0, changesB = 0;
622 for(
int num = 1; num <= LastSnapShotNr; num++)
623 changesA += halotrees_join_via_descendants(num);
625 for(
int num = LastSnapShotNr; num > 0; num--)
626 changesA += halotrees_join_via_descendants(num);
632 for(
int num = LastSnapShotNr - 1; num >= 0; num--)
633 changesB += halotrees_join_via_progenitors(num);
635 for(
int num = 0; num < LastSnapShotNr; num++)
636 changesB += halotrees_join_via_progenitors(num);
638 MPI_Allreduce(MPI_IN_PLACE, &changesA, 1, MPI_LONG_LONG, MPI_SUM, Communicator);
639 MPI_Allreduce(MPI_IN_PLACE, &changesB, 1, MPI_LONG_LONG, MPI_SUM, Communicator);
641 mpi_printf(
"MERGERTREE: iteration %d of joining trees via descendants and progenitor, %lld %lld links\n", iter, changesA,
647 while(changesA + changesB > 0);
651 for(
int mode = 0; mode < 2; mode++)
653 long long totlinks = 0;
657 long long links = halotrees_join_trees_via_fof_or_mostboundid_bridges(mode);
659 MPI_Allreduce(&links, &totlinks, 1, MPI_LONG_LONG, MPI_SUM, Communicator);
662 mpi_printf(
"MERGERTREE: iteration %d of joining trees via common FOF bridges yielded %lld links\n", iter, totlinks);
664 mpi_printf(
"MERGERTREE: iteration %d of joining trees via common MostboundID bridges yielded %lld links\n", iter,
678void mergertree::halotrees_collect_treehalos(
void)
682 for(
int num = 0; num <= LastSnapShotNr; num++)
683 Nhalos += Cats[num].Nsubhalos;
689 for(
int num = LastSnapShotNr; num >= 0; num--)
691 Mem.myfree(Cats[num].TabNsubhalos);
692 Cats[num].TabNsubhalos = NULL;
694 Mem.myfree(Cats[num].TabNgroups);
695 Cats[num].TabNgroups = NULL;
698 for(
int num = LastSnapShotNr; num >= 1; num--)
700 Mem.myfree(Cats[num].Progenitors);
701 Cats[num].Progenitors = NULL;
704 for(
int num = LastSnapShotNr - 1; num >= 0; num--)
706 Mem.myfree(Cats[num].Descendants);
707 Cats[num].Descendants = NULL;
710 for(
int num = LastSnapShotNr; num >= 0; num--)
712 Mem.myfree_movable(Cats[num].Group);
713 Cats[num].Group = NULL;
716 Halos = (treehalo_type *)
Mem.mymalloc_movable(&Halos,
"Halos", (Nhalos + 1) *
sizeof(treehalo_type));
720 for(
int num = 0; num <= LastSnapShotNr; num++)
721 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
723 Halos[off].TreeID = Cats[num].Subhalo[i].TreeID;
724 Halos[off].TreeIndex = Cats[num].Subhalo[i].TreeIndex;
726 Halos[off].TreeMainProgenitor = Cats[num].SubExt[i].TreeMainProgenitor;
727 Halos[off].TreeFirstProgenitor = Cats[num].SubExt[i].TreeFirstProgenitor;
728 Halos[off].TreeNextProgenitor = Cats[num].SubExt[i].TreeNextProgenitor;
729 Halos[off].TreeDescendant = Cats[num].SubExt[i].TreeDescendant;
731 Halos[off].TreeFirstDescendant = Cats[num].SubExt[i].TreeFirstDescendant;
732 Halos[off].TreeNextDescendant = Cats[num].SubExt[i].TreeNextDescendant;
733 Halos[off].TreeProgenitor = Cats[num].SubExt[i].TreeProgenitor;
735 Halos[off].SnapNum = num;
736 Halos[off].SubhaloNr = Cats[num].Subhalo[i].SubhaloNr;
737 Halos[off].GroupNr = Cats[num].Subhalo[i].GroupNr;
738 Halos[off].UniqueGroupNr = Cats[num].Subhalo[i].UniqueGroupNr;
740 Halos[off].SubProp = Cats[num].Subhalo[i];
746 for(
int num = LastSnapShotNr; num >= 0; num--)
748 Mem.myfree_movable(Cats[num].SubExt);
749 Cats[num].SubExt = NULL;
752 long long *count_list = (
long long *)
Mem.mymalloc(
"count_list", NTask *
sizeof(
long long));
753 long long totnsubs = Nhalos;
754 MPI_Allgather(&totnsubs,
sizeof(
long long), MPI_BYTE, count_list,
sizeof(
long long), MPI_BYTE, Communicator);
757 mycxxsort_parallel(Halos, Halos + Nhalos, compare_Halos_UniqueGroupNr_SubhaloNr, Communicator);
759 long long previous_UniqueGroupNr =
HALONR_MAX;
761 for(
int i = 0; i < Nhalos; i++)
763 if(Halos[i].UniqueGroupNr != previous_UniqueGroupNr)
765 previous_UniqueGroupNr = Halos[i].UniqueGroupNr;
766 new_treeindex = Halos[i].TreeIndex;
769 Halos[i].TreeFirstHaloInFOFgroup = new_treeindex;
771 if(i < Nhalos - 1 && Halos[i].UniqueGroupNr == Halos[i + 1].UniqueGroupNr)
772 Halos[i].TreeNextHaloInFOFgroup = Halos[i + 1].TreeIndex;
774 Halos[i].TreeNextHaloInFOFgroup = -1;
777 treehalo_type *efirst = (treehalo_type *)
Mem.mymalloc(
"efirst", NTask *
sizeof(treehalo_type));
778 treehalo_type *elast = (treehalo_type *)
Mem.mymalloc(
"elast", NTask *
sizeof(treehalo_type));
780 MPI_Allgather(&Halos[0],
sizeof(treehalo_type), MPI_BYTE, efirst,
sizeof(treehalo_type), MPI_BYTE, Communicator);
781 MPI_Allgather(&Halos[Nhalos > 0 ? Nhalos - 1 : 0],
sizeof(treehalo_type), MPI_BYTE, elast,
sizeof(treehalo_type), MPI_BYTE,
785 for(
int task = ThisTask + 1; task < NTask; task++)
786 if(count_list[task] > 0)
788 if(Halos[Nhalos - 1].UniqueGroupNr == efirst[task].UniqueGroupNr)
789 Halos[Nhalos - 1].TreeNextHaloInFOFgroup = efirst[task].TreeIndex;
796 long long previous_UniqueGroupNr =
HALONR_MAX;
799 for(
int task = ThisTask - 1; task >= 0; task--)
801 if(count_list[task] > 0)
803 if(elast[task].UniqueGroupNr == Halos[0].UniqueGroupNr)
805 previous_UniqueGroupNr = elast[task].UniqueGroupNr;
806 new_treeindex = elast[task].TreeFirstHaloInFOFgroup;
811 for(
int i = 0; i < Nhalos; i++)
813 if(Halos[i].UniqueGroupNr != previous_UniqueGroupNr)
815 previous_UniqueGroupNr = Halos[i].UniqueGroupNr;
816 new_treeindex = Halos[i].TreeIndex;
820 Halos[i].TreeFirstHaloInFOFgroup = new_treeindex;
828 mycxxsort_parallel(Halos, Halos + Nhalos, compare_Halos_TreeID_TreeIndex, Communicator);
830 treehalo_type *elem_last = (treehalo_type *)
Mem.mymalloc(
"elem_last", NTask *
sizeof(treehalo_type));
832 MPI_Allgather(&Halos[Nhalos > 0 ? Nhalos - 1 : 0],
sizeof(treehalo_type), MPI_BYTE, elem_last,
sizeof(treehalo_type), MPI_BYTE,
835 long long treeid_previous = -1;
836 for(
int task = ThisTask - 1; task >= 0; task--)
838 if(count_list[task] > 0)
840 treeid_previous = elem_last[task].TreeID;
846 for(
int i = 0; i < Nhalos; i++)
848 if(Halos[i].TreeID != treeid_previous)
851 treeid_previous = Halos[i].TreeID;
852 Halos[i].TreeID = Ntrees - 1;
855 int *ntrees_list = (
int *)
Mem.mymalloc(
"ntrees_list", NTask *
sizeof(
int));
856 MPI_Allgather(&Ntrees, 1, MPI_INT, ntrees_list, 1, MPI_INT, Communicator);
859 long long ntrees_before = 0;
860 for(
int i = 0; i < NTask; i++)
862 TotNtrees += ntrees_list[i];
864 ntrees_before += ntrees_list[i];
867 for(
int i = 0; i < Nhalos; i++)
868 Halos[i].TreeID += ntrees_before;
876 MPI_Allgather(&Halos[Nhalos > 0 ? Nhalos - 1 : 0],
sizeof(treehalo_type), MPI_BYTE, elem_last,
sizeof(treehalo_type), MPI_BYTE,
879 treeid_previous = -1;
880 for(
int task = ThisTask - 1; task >= 0; task--)
882 if(count_list[task] > 0)
884 treeid_previous = elem_last[task].TreeID;
890 for(
int i = 0; i < Nhalos; i++)
892 if(Halos[i].TreeID != treeid_previous)
895 treeid_previous = Halos[i].TreeID;
896 TreeTable[Ntrees - 1].HaloCount++;
897 TreeTable[Ntrees - 1].TreeID = Halos[i].TreeID;
907 for(
int task = ThisTask + 1; task < NTask; task++)
909 if(TreeTable[Ntrees - 1].TreeID == elem_first[task].TreeID)
910 TreeTable[Ntrees - 1].HaloCount += elem_first[task].
HaloCount;
915 Mem.myfree(elem_first);
917 long long sumhalos = 0;
918 LargestHaloCount = 0;
919 for(
int i = 0; i < Ntrees; i++)
921 sumhalos += TreeTable[i].HaloCount;
922 if(TreeTable[i].HaloCount > LargestHaloCount)
923 LargestHaloCount = TreeTable[i].HaloCount;
925 MPI_Allreduce(MPI_IN_PLACE, &LargestHaloCount, 1, MPI_INT, MPI_MAX, Communicator);
927 long long *list_sumhalos = (
long long *)
Mem.mymalloc(
"list_sumhalos", NTask *
sizeof(
long long));
928 MPI_Allgather(&sumhalos,
sizeof(
long long), MPI_BYTE, list_sumhalos,
sizeof(
long long), MPI_BYTE, Communicator);
930 long long sum_check = 0;
931 for(
int i = 0; i < NTask; i++)
932 sum_check += list_sumhalos[i];
934 if(sum_check != TotNhalos)
935 Terminate(
"TotNTrees=%lld sum_check=%lld != TotNhalos=%lld", (
long long)TotNtrees, sum_check, (
long long)TotNhalos);
939 TreeTable[0].FirstHalo = 0;
940 for(
int task = 0; task < ThisTask; task++)
941 TreeTable[0].FirstHalo += list_sumhalos[task];
944 Mem.myfree(list_sumhalos);
946 for(
int i = 1; i < Ntrees; i++)
947 TreeTable[i].FirstHalo = TreeTable[i - 1].FirstHalo + TreeTable[i - 1].HaloCount;
949 Mem.myfree_movable(ntrees_list);
950 Mem.myfree_movable(elem_last);
951 Mem.myfree_movable(count_list);
961void mergertree::halotrees_reshuffle(
char **ptr,
size_t len,
int ncurrent,
int ntarget)
963 int *Send_count = (
int *)
Mem.mymalloc_movable(&Send_count,
"Send_count",
sizeof(
int) * NTask);
964 int *Send_offset = (
int *)
Mem.mymalloc_movable(&Send_offset,
"Send_offset",
sizeof(
int) * NTask);
965 int *Recv_count = (
int *)
Mem.mymalloc_movable(&Recv_count,
"Recv_count",
sizeof(
int) * NTask);
966 int *Recv_offset = (
int *)
Mem.mymalloc_movable(&Recv_offset,
"Recv_offset",
sizeof(
int) * NTask);
969 char *buf = (
char *)
Mem.mymalloc_movable(&buf,
"buf", ncurrent * len);
970 memcpy(buf, *ptr, ncurrent * len);
973 *ptr = (
char *)
Mem.myrealloc_movable(*ptr, ntarget * len);
976 int *tab_ncurrent = (
int *)
Mem.mymalloc(
"tab_ncurrent", NTask *
sizeof(
int));
977 MPI_Allgather(&ncurrent, 1, MPI_INT, tab_ncurrent, 1, MPI_INT, Communicator);
979 int *tab_ntarget = (
int *)
Mem.mymalloc(
"tab_ntarget", NTask *
sizeof(
int));
980 MPI_Allgather(&ntarget, 1, MPI_INT, tab_ntarget, 1, MPI_INT, Communicator);
983 int nexport = 0, nimport = 0;
985 for(
int i = 0; i < NTask; i++)
989 for(
int i = 0; i < ThisTask; i++)
990 nbefore += tab_ncurrent[i];
992 int target = 0, ncum = 0;
993 for(
int i = 0; i < ncurrent; i++)
995 while(target < NTask - 1 && nbefore + i >= ncum + tab_ntarget[target])
996 ncum += tab_ntarget[target++];
998 Send_count[target]++;
1001 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
1002 Recv_offset[0] = Send_offset[0] = 0;
1004 for(
int j = 0; j < NTask; j++)
1006 nimport += Recv_count[j];
1007 nexport += Send_count[j];
1011 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
1012 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
1016 if(nimport != ntarget)
1019 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1021 int recvTask = ThisTask ^ ngrp;
1022 if(recvTask < NTask)
1023 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1025 *ptr + Recv_offset[recvTask] * len, Recv_count[recvTask] * len, MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
1029 Mem.myfree(tab_ntarget);
1030 Mem.myfree(tab_ncurrent);
1033 Mem.myfree(Recv_offset);
1034 Mem.myfree(Recv_count);
1035 Mem.myfree(Send_offset);
1036 Mem.myfree(Send_count);
1042void mergertree::halotrees_remap_treepointers(
void)
1044 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
1045 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
1046 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
1047 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
1050 for(
int num = 0; num <= LastSnapShotNr; num++)
1051 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
1053 Cats[num].SubExt[i].TreeMainProgenitor = -1;
1054 Cats[num].SubExt[i].TreeFirstProgenitor = -1;
1055 Cats[num].SubExt[i].TreeNextProgenitor = -1;
1056 Cats[num].SubExt[i].TreeDescendant = -1;
1057 Cats[num].SubExt[i].TreeFirstDescendant = -1;
1058 Cats[num].SubExt[i].TreeNextDescendant = -1;
1059 Cats[num].SubExt[i].TreeProgenitor = -1;
1065 for(
int set = 0; set < 3; set++)
1066 for(
int delta = 1; delta >= -1; delta--)
1068 if(set == 2 && delta != -1)
1074 for(
int base = 0; base <= LastSnapShotNr; base++)
1077 int num = base + delta;
1079 if(set == 1 && delta != 1 && num == 0)
1082 if((delta == -1 && num >= 0) || (delta >= 0 && base < LastSnapShotNr))
1085 long long *list_min_subhalonr = (
long long *)
Mem.mymalloc(
"list_min_subhalonr", NTask *
sizeof(
long long));
1086 long long *list_max_subhalonr = (
long long *)
Mem.mymalloc(
"list_max_subhalonr", NTask *
sizeof(
long long));
1088 long long min_subhalonr =
1089 Cats[num].Nsubhalos > 0 ? Cats[num].Subhalo[0].SubhaloNr :
HALONR_MAX;
1090 long long max_subhalonr = Cats[num].Nsubhalos > 0 ? Cats[num].Subhalo[Cats[num].Nsubhalos - 1].SubhaloNr
1093 MPI_Allgather(&min_subhalonr,
sizeof(
long long), MPI_BYTE, list_min_subhalonr,
sizeof(
long long), MPI_BYTE,
1095 MPI_Allgather(&max_subhalonr,
sizeof(
long long), MPI_BYTE, list_max_subhalonr,
sizeof(
long long), MPI_BYTE,
1099 data_list *list = (data_list *)
Mem.mymalloc(
"list", Cats[base].Nsubhalos *
sizeof(data_list));
1101 for(
int i = 0; i < Cats[base].Nsubhalos; i++)
1107 list[count].targetsubhalonr = Cats[base].Progenitors[i].FirstProgSubhaloNr;
1110 list[count].targetsubhalonr = Cats[base].Descendants[i].NextProgSubhaloNr;
1113 list[count].targetsubhalonr = Cats[base].Descendants[i].DescSubhaloNr;
1120 list[count].targetsubhalonr = Cats[base].Progenitors[i].ProgSubhaloNr;
1123 list[count].targetsubhalonr = Cats[base].Progenitors[i].NextDescSubhaloNr;
1126 list[count].targetsubhalonr = Cats[base].Descendants[i].FirstDescSubhaloNr;
1133 list[count].targetsubhalonr = Cats[base].Progenitors[i].MainProgSubhaloNr;
1137 list[count].originsubhalonr = Cats[base].Subhalo[i].SubhaloNr;
1139 if(list[count].targetsubhalonr >= 0 &&
1140 list[count].targetsubhalonr < (
long long)
HALONR_MAX)
1142 if(list[count].targetsubhalonr >= Cats[num].TotNsubhalos)
1143 Terminate(
"set=%d delta=%d num=%d base=%d list[count].targetsubhalonr=%lld >= Cats[num].TotNsubhalos=%lld\n",
1144 set, delta, num, base, list[count].targetsubhalonr, Cats[num].TotNsubhalos);
1146 list[count].origin = i;
1147 list[count].intreeid = Cats[base].Subhalo[i].TreeID;
1153 mycxxsort(list, list + count, compare_data_list_subhalonnr);
1157 int nexport = 0, nimport = 0;
1159 remap_data *import_data = NULL, *export_data = NULL;
1161 for(
int mode = 0; mode < 2; mode++)
1163 for(
int i = 0; i < NTask; i++)
1168 for(
int i = 0; i < count; i++)
1170 while(target < NTask - 1 &&
1171 (list_min_subhalonr[target] ==
HALONR_MAX || list[i].targetsubhalonr > list_max_subhalonr[target]))
1174 if(list_min_subhalonr[target] !=
HALONR_MAX && list[i].targetsubhalonr >= list_min_subhalonr[target] &&
1175 list[i].targetsubhalonr <= list_max_subhalonr[target])
1178 Send_count[target]++;
1181 int off = Send_offset[target] + Send_count[target]++;
1183 export_data[off].loc_index = i;
1184 export_data[off].targetsubhalonr = list[i].targetsubhalonr;
1185 export_data[off].originsubhalonr = list[i].originsubhalonr;
1186 export_data[off].intreeid = list[i].intreeid;
1191 "this shouldn't happen: set=%d delta=%d num=%d base=%d delta=%d i=%d|count=%d "
1192 "list[i].targetsubhalonr=%lld "
1194 "list_min_subhalonr[target]=%lld list_max_subhalonr[target]=%lld\n",
1195 set, delta, num, base, delta, i, count, (
long long)list[i].targetsubhalonr, target,
1196 list_min_subhalonr[target], list_max_subhalonr[target]);
1201 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
1202 Recv_offset[0] = Send_offset[0] = 0;
1203 for(
int j = 0; j < NTask; j++)
1205 nimport += Recv_count[j];
1206 nexport += Send_count[j];
1209 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
1210 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
1214 export_data = (remap_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(remap_data));
1215 import_data = (remap_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(remap_data));
1219 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1222 int recvTask = ThisTask ^ ngrp;
1223 if(recvTask < NTask)
1224 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1225 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(remap_data), MPI_BYTE,
1226 recvTask,
TAG_DENS_B, &import_data[Recv_offset[recvTask]],
1227 Recv_count[recvTask] *
sizeof(remap_data), MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
1232 for(
int i = 0; i < nimport; i++)
1233 import_data[i].orig_index = i;
1235 mycxxsort(import_data, import_data + nimport, compare_remap_data_subhalonr);
1238 for(
int i = 0, j = 0; i < Cats[num].Nsubhalos && j < nimport;)
1240 if(Cats[num].Subhalo[i].SubhaloNr < import_data[j].targetsubhalonr)
1242 else if(Cats[num].Subhalo[i].SubhaloNr > import_data[j].targetsubhalonr)
1244 Terminate(
"Can't find targetsubhalonr=%lld Cats[num].Subhalo[i].SubhaloNr=%lld i=%d|%d j=%d|%d",
1245 import_data[j].targetsubhalonr, Cats[num].Subhalo[i].SubhaloNr, i, Cats[num].Nsubhalos, j, nimport);
1249 import_data[j].new_treeindexptr = Cats[num].Subhalo[i].TreeIndex;
1250 import_data[j].treeid = Cats[num].Subhalo[i].TreeID;
1252 if(Cats[num].Subhalo[i].TreeID != import_data[j].intreeid)
1254 "\nWe are not in the same tree, which shouldn't be the case: set=%d delta=%d num=%d\n"
1255 "Cats[num].Subhalo[i].SubhaloNr=%lld \nCats[num].Subhalo[i].DescSubhaloNr=%lld\n"
1256 "Cats[num].Subhalo[i].NextProgSubhalor=%lld\nCats[num].Subhalo[i].FirstProgSubhalor=%lld\n"
1257 "Cats[num].Subhalo[i].NextDescSubhalor=%lld\nCats[num].Subhalo[i].FirstDescSubhalor=%lld\n"
1258 "Cats[num].Subhalo[i].ProgSubhalorNr=%lld\n"
1259 "originsubgalonr=%lld targetsubgalonr=%lld Cats[num].Subhalo[i].TreeID=%lld "
1260 "import_data[j].intreeid=%lld i=%d|%d j=%d|%d num=%d",
1261 set, delta, num, Cats[num].Subhalo[i].SubhaloNr, Cats[num].Descendants[i].DescSubhaloNr,
1262 Cats[num].Descendants[i].NextProgSubhaloNr, Cats[num].Progenitors[i].FirstProgSubhaloNr,
1263 Cats[num].Progenitors[i].NextDescSubhaloNr, Cats[num].Descendants[i].FirstDescSubhaloNr,
1264 Cats[num].Progenitors[i].ProgSubhaloNr, import_data[j].originsubhalonr, import_data[j].targetsubhalonr,
1265 Cats[num].Subhalo[i].TreeID, import_data[j].intreeid, i, Cats[num].Nsubhalos, j, nimport, num);
1271 mycxxsort(import_data, import_data + nimport, compare_remap_data_orig_index);
1274 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1277 int recvTask = ThisTask ^ ngrp;
1278 if(recvTask < NTask)
1279 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1280 myMPI_Sendrecv(&import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(remap_data), MPI_BYTE,
1281 recvTask,
TAG_DENS_B, &export_data[Send_offset[recvTask]],
1282 Send_count[recvTask] *
sizeof(remap_data), MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
1286 for(
int i = 0; i < nexport; i++)
1288 int idx = list[export_data[i].loc_index].origin;
1290 if(Cats[base].Subhalo[idx].TreeID != export_data[i].treeid)
1291 Terminate(
"something is wrong: delta=%d i=%d|%d idx=%d|%d %lld %lld %lld", delta, i, nexport, idx,
1292 Cats[base].Nsubhalos, Cats[base].Subhalo[idx].TreeID, export_data[i].treeid, export_data[i].intreeid);
1298 Cats[base].SubExt[idx].TreeFirstProgenitor = export_data[i].new_treeindexptr;
1302 Cats[base].SubExt[idx].TreeNextProgenitor = export_data[i].new_treeindexptr;
1306 Cats[base].SubExt[idx].TreeDescendant = export_data[i].new_treeindexptr;
1313 Cats[base].SubExt[idx].TreeProgenitor = export_data[i].new_treeindexptr;
1317 Cats[base].SubExt[idx].TreeNextDescendant = export_data[i].new_treeindexptr;
1321 Cats[base].SubExt[idx].TreeFirstDescendant = export_data[i].new_treeindexptr;
1328 Cats[base].SubExt[idx].TreeMainProgenitor = export_data[i].new_treeindexptr;
1333 Mem.myfree(import_data);
1334 Mem.myfree(export_data);
1336 Mem.myfree(list_max_subhalonr);
1337 Mem.myfree(list_min_subhalonr);
1342 Mem.myfree(Recv_offset);
1343 Mem.myfree(Recv_count);
1344 Mem.myfree(Send_offset);
1345 Mem.myfree(Send_count);
1352void mergertree::halotrees_assign_new_treeindices(
void)
1354 long long totnsubs = 0;
1356 for(
int num = 0; num <= LastSnapShotNr; num++)
1357 totnsubs += Cats[num].Nsubhalos;
1359 assign_data *a_data = (assign_data *)
Mem.mymalloc(
"a_data", (totnsubs + 1) *
sizeof(assign_data));
1361 long long count = 0;
1362 for(
int num = 0; num <= LastSnapShotNr; num++)
1363 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
1365 a_data[count].origin_task = ThisTask;
1366 a_data[count].origin_num = num;
1367 a_data[count].origin_index = i;
1368 a_data[count].treeid = Cats[num].Subhalo[i].TreeID;
1372 mycxxsort_parallel(a_data, a_data + totnsubs, compare_assign_data_treeid_origin_num_origin_task_origin_index, Communicator);
1374 long long newid = 0;
1376 for(
long long i = 0, treeindex = 0; i < totnsubs; i++)
1378 if(i == 0 || a_data[i].treeid != a_data[i - 1].treeid)
1381 a_data[i].treeindex = treeindex++;
1383 if(i > 0 && a_data[i].treeid != a_data[i - 1].treeid)
1386 a_data[i].newtreeid = newid;
1389 long long *count_list = (
long long *)
Mem.mymalloc(
"count_list", NTask *
sizeof(
long long));
1390 long long *newid_list = (
long long *)
Mem.mymalloc(
"newid_list", NTask *
sizeof(
long long));
1391 MPI_Allgather(&totnsubs,
sizeof(
long long), MPI_BYTE, count_list,
sizeof(
long long), MPI_BYTE, Communicator);
1392 MPI_Allgather(&newid,
sizeof(
long long), MPI_BYTE, newid_list,
sizeof(
long long), MPI_BYTE, Communicator);
1394 assign_data *elem_last = (assign_data *)
Mem.mymalloc(
"elem_last", NTask *
sizeof(assign_data));
1395 assign_data *elem_first = (assign_data *)
Mem.mymalloc(
"elem_first", NTask *
sizeof(assign_data));
1398 MPI_Allgather(&a_data[totnsubs > 0 ? totnsubs - 1 : 0],
sizeof(assign_data), MPI_BYTE, elem_last,
sizeof(assign_data), MPI_BYTE,
1400 MPI_Allgather(&a_data[0],
sizeof(assign_data), MPI_BYTE, elem_first,
sizeof(assign_data), MPI_BYTE, Communicator);
1402 if(count_list[ThisTask] > 0)
1404 long long count_before = 0;
1405 for(
int task = 0; task < ThisTask; task++)
1406 if(count_list[task] > 0)
1408 if(a_data[0].treeid == elem_last[task].treeid)
1409 count_before += (elem_last[task].treeindex + 1);
1411 if(count_before > 0)
1413 for(
long long i = 0; i < totnsubs; i++)
1415 if(a_data[i].treeid != a_data[0].treeid)
1418 a_data[i].treeindex += count_before;
1422 long long newidoff = 0;
1423 for(
int task = 0; task < ThisTask; task++)
1424 newidoff += newid_list[task];
1433 while(taleft < ThisTask && count_list[taleft] == 0)
1436 if(taleft < ThisTask)
1438 int taright = taleft + 1;
1440 while(count_list[taright] == 0)
1445 if(elem_last[taleft].treeid != elem_first[taright].treeid)
1451 while(taleft < ThisTask);
1454 for(
long long i = 0; i < totnsubs; i++)
1455 a_data[i].newtreeid += newidoff;
1458 Mem.myfree(elem_first);
1459 Mem.myfree(elem_last);
1460 Mem.myfree(newid_list);
1461 Mem.myfree(count_list);
1463 mycxxsort_parallel(a_data, a_data + totnsubs, compare_assign_data_origin_task_origin_num_origin_index, Communicator);
1466 for(
int num = 0; num <= LastSnapShotNr; num++)
1467 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
1469 Cats[num].Subhalo[i].TreeIndex = a_data[count].treeindex;
1470 Cats[num].Subhalo[i].TreeID = a_data[count].newtreeid;
1482int mergertree::halotrees_join_via_descendants(
int num)
1484 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
1485 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
1486 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
1487 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
1492 long long *list_min_subhalonr = (
long long *)
Mem.mymalloc(
"list_min_subhalonr", NTask *
sizeof(
long long));
1493 long long *list_max_subhalonr = (
long long *)
Mem.mymalloc(
"list_max_subhalonr", NTask *
sizeof(
long long));
1498 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[0].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE, list_min_subhalonr,
1499 sizeof(
long long), MPI_BYTE, Communicator);
1500 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[Cats[num].Nsubhalos - 1].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE,
1501 list_max_subhalonr,
sizeof(
long long), MPI_BYTE, Communicator);
1503 int nexport = 0, nimport = 0;
1505 halotrees_data *import_data = NULL, *export_data = NULL;
1510 descnr_data *sorted_list = (descnr_data *)
Mem.mymalloc(
"sorted_list", Cats[num - 1].Nsubhalos *
sizeof(descnr_data));
1512 for(
int i = 0; i < Cats[num - 1].Nsubhalos; i++)
1514 sorted_list[i].DescSubhaloNr = Cats[num - 1].Descendants[i].DescSubhaloNr;
1515 sorted_list[i].TreeID = Cats[num - 1].Subhalo[i].TreeID;
1516 sorted_list[i].TreeTask = Cats[num - 1].Subhalo[i].TreeTask;
1517 sorted_list[i].orig_index = i;
1520 mycxxsort(sorted_list, sorted_list + Cats[num - 1].Nsubhalos, compare_sorted_list_descsubhalonr);
1523 for(
int mode = 0; mode < 2; mode++)
1525 for(
int i = 0; i < NTask; i++)
1530 for(
int i = 0; i < Cats[num - 1].Nsubhalos; i++)
1532 while(target < NTask - 1 &&
1533 (list_min_subhalonr[target] == empty || sorted_list[i].DescSubhaloNr > list_max_subhalonr[target]))
1536 if(list_min_subhalonr[target] != empty && sorted_list[i].DescSubhaloNr >= list_min_subhalonr[target] &&
1537 sorted_list[i].DescSubhaloNr <= list_max_subhalonr[target])
1540 Send_count[target]++;
1543 int off = Send_offset[target] + Send_count[target]++;
1545 export_data[off].loc_index = sorted_list[i].orig_index;
1546 export_data[off].descendantnr = sorted_list[i].DescSubhaloNr;
1547 export_data[off].treeid = sorted_list[i].TreeID;
1548 export_data[off].treetask = sorted_list[i].TreeTask;
1555 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
1556 Recv_offset[0] = Send_offset[0] = 0;
1557 for(
int j = 0; j < NTask; j++)
1559 nimport += Recv_count[j];
1560 nexport += Send_count[j];
1563 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
1564 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
1568 export_data = (halotrees_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(halotrees_data));
1569 import_data = (halotrees_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(halotrees_data));
1574 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1576 int recvTask = ThisTask ^ ngrp;
1577 if(recvTask < NTask)
1578 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1579 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE, recvTask,
1580 TAG_DENS_B, &import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE,
1581 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
1586 for(
int i = 0; i < nimport; i++)
1587 import_data[i].orig_order = i;
1589 mycxxsort(import_data, import_data + nimport, compare_halotrees_data_descendantnr);
1594 for(
int i = 0, j = 0; i < Cats[num].Nsubhalos && j < nimport;)
1596 if(Cats[num].Subhalo[i].SubhaloNr < import_data[j].descendantnr)
1598 else if(Cats[num].Subhalo[i].SubhaloNr > import_data[j].descendantnr)
1602 if(import_data[j].treeid > Cats[num].Subhalo[i].TreeID)
1604 import_data[j].treeid = Cats[num].Subhalo[i].TreeID;
1605 import_data[j].treetask = Cats[num].Subhalo[i].TreeTask;
1608 else if(import_data[j].treeid < Cats[num].Subhalo[i].TreeID)
1610 Cats[num].Subhalo[i].TreeID = import_data[j].treeid;
1611 Cats[num].Subhalo[i].TreeTask = import_data[j].treetask;
1619 mycxxsort(import_data, import_data + nimport, compare_halotrees_data_orig_order);
1622 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1624 int recvTask = ThisTask ^ ngrp;
1625 if(recvTask < NTask)
1626 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1627 myMPI_Sendrecv(&import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE, recvTask,
1628 TAG_DENS_B, &export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE,
1629 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
1633 for(
int i = 0; i < nexport; i++)
1637 Cats[num - 1].Subhalo[export_data[i].loc_index].TreeID = export_data[i].treeid;
1638 Cats[num - 1].Subhalo[export_data[i].loc_index].TreeTask = export_data[i].treetask;
1642 Mem.myfree(import_data);
1643 Mem.myfree(export_data);
1644 Mem.myfree(sorted_list);
1645 Mem.myfree(list_max_subhalonr);
1646 Mem.myfree(list_min_subhalonr);
1648 Mem.myfree(Recv_offset);
1649 Mem.myfree(Recv_count);
1650 Mem.myfree(Send_offset);
1651 Mem.myfree(Send_count);
1656int mergertree::halotrees_join_via_progenitors(
int num)
1658 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
1659 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
1660 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
1661 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
1666 long long *list_min_subhalonr = (
long long *)
Mem.mymalloc(
"list_min_subhalonr", NTask *
sizeof(
long long));
1667 long long *list_max_subhalonr = (
long long *)
Mem.mymalloc(
"list_max_subhalonr", NTask *
sizeof(
long long));
1672 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[0].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE, list_min_subhalonr,
1673 sizeof(
long long), MPI_BYTE, Communicator);
1674 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[Cats[num].Nsubhalos - 1].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE,
1675 list_max_subhalonr,
sizeof(
long long), MPI_BYTE, Communicator);
1677 int nexport = 0, nimport = 0;
1679 halotrees_data *import_data = NULL, *export_data = NULL;
1684 prognr_data *sorted_list = (prognr_data *)
Mem.mymalloc(
"sorted_list", Cats[num + 1].Nsubhalos *
sizeof(prognr_data));
1686 for(
int i = 0; i < Cats[num + 1].Nsubhalos; i++)
1688 sorted_list[i].ProgSubhaloNr = Cats[num + 1].Progenitors[i].ProgSubhaloNr;
1689 sorted_list[i].TreeID = Cats[num + 1].Subhalo[i].TreeID;
1690 sorted_list[i].TreeTask = Cats[num + 1].Subhalo[i].TreeTask;
1691 sorted_list[i].orig_index = i;
1694 mycxxsort(sorted_list, sorted_list + Cats[num + 1].Nsubhalos, compare_sorted_list_progsubhalonr);
1697 for(
int mode = 0; mode < 2; mode++)
1699 for(
int i = 0; i < NTask; i++)
1704 for(
int i = 0; i < Cats[num + 1].Nsubhalos; i++)
1706 while(target < NTask - 1 &&
1707 (list_min_subhalonr[target] == empty || sorted_list[i].ProgSubhaloNr > list_max_subhalonr[target]))
1710 if(list_min_subhalonr[target] != empty && sorted_list[i].ProgSubhaloNr >= list_min_subhalonr[target] &&
1711 sorted_list[i].ProgSubhaloNr <= list_max_subhalonr[target])
1714 Send_count[target]++;
1717 int off = Send_offset[target] + Send_count[target]++;
1719 export_data[off].loc_index = sorted_list[i].orig_index;
1720 export_data[off].progenitornr = sorted_list[i].ProgSubhaloNr;
1721 export_data[off].treeid = sorted_list[i].TreeID;
1722 export_data[off].treetask = sorted_list[i].TreeTask;
1729 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
1730 Recv_offset[0] = Send_offset[0] = 0;
1731 for(
int j = 0; j < NTask; j++)
1733 nimport += Recv_count[j];
1734 nexport += Send_count[j];
1737 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
1738 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
1742 export_data = (halotrees_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(halotrees_data));
1743 import_data = (halotrees_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(halotrees_data));
1748 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1750 int recvTask = ThisTask ^ ngrp;
1751 if(recvTask < NTask)
1752 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1753 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE, recvTask,
1754 TAG_DENS_B, &import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE,
1755 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
1761 for(
int i = 0; i < nimport; i++)
1762 import_data[i].orig_order = i;
1764 mycxxsort(import_data, import_data + nimport, compare_halotrees_data_progenitornr);
1769 for(
int i = 0, j = 0; i < Cats[num].Nsubhalos && j < nimport;)
1771 if(Cats[num].Subhalo[i].SubhaloNr < import_data[j].progenitornr)
1773 else if(Cats[num].Subhalo[i].SubhaloNr > import_data[j].progenitornr)
1777 if(import_data[j].treeid > Cats[num].Subhalo[i].TreeID)
1779 import_data[j].treeid = Cats[num].Subhalo[i].TreeID;
1780 import_data[j].treetask = Cats[num].Subhalo[i].TreeTask;
1783 else if(import_data[j].treeid < Cats[num].Subhalo[i].TreeID)
1785 Cats[num].Subhalo[i].TreeID = import_data[j].treeid;
1786 Cats[num].Subhalo[i].TreeTask = import_data[j].treetask;
1794 mycxxsort(import_data, import_data + nimport, compare_halotrees_data_orig_order);
1797 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1799 int recvTask = ThisTask ^ ngrp;
1800 if(recvTask < NTask)
1801 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1802 myMPI_Sendrecv(&import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE, recvTask,
1803 TAG_DENS_B, &export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_data), MPI_BYTE,
1804 recvTask,
TAG_DENS_B, Communicator, MPI_STATUS_IGNORE);
1808 for(
int i = 0; i < nexport; i++)
1812 Cats[num + 1].Subhalo[export_data[i].loc_index].TreeID = export_data[i].treeid;
1813 Cats[num + 1].Subhalo[export_data[i].loc_index].TreeTask = export_data[i].treetask;
1817 Mem.myfree(import_data);
1818 Mem.myfree(export_data);
1819 Mem.myfree(sorted_list);
1820 Mem.myfree(list_max_subhalonr);
1821 Mem.myfree(list_min_subhalonr);
1823 Mem.myfree(Recv_offset);
1824 Mem.myfree(Recv_count);
1825 Mem.myfree(Send_offset);
1826 Mem.myfree(Send_count);
1831void mergertree::halotrees_determine_mainprogenitor(
void)
1833 for(
int num = 1; num <= LastSnapShotNr; num++)
1834 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
1835 Cats[num].Progenitors[i].MainProgSubhaloNr =
HALONR_MAX;
1838 for(
int num = 0; num <= LastSnapShotNr; num++)
1839 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
1840 Cats[num].SubExt[i].MaxLenProgBranch = Cats[num].Subhalo[i].Len;
1844 for(
int num = 1; num <= LastSnapShotNr; num++)
1845 halotrees_propagate_max_branch_length_descendants(num);
1853 mpi_printf(
"MERGERTREE: determination of main progenitor branch done\n");
1859void mergertree::halotrees_propagate_max_branch_length_descendants(
int num)
1861 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
1862 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
1863 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
1864 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
1869 long long *list_min_subhalonr = (
long long *)
Mem.mymalloc(
"list_min_subhalonr", NTask *
sizeof(
long long));
1870 long long *list_max_subhalonr = (
long long *)
Mem.mymalloc(
"list_max_subhalonr", NTask *
sizeof(
long long));
1875 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[0].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE, list_min_subhalonr,
1876 sizeof(
long long), MPI_BYTE, Communicator);
1877 MPI_Allgather(Cats[num].Nsubhalos > 0 ? &Cats[num].Subhalo[Cats[num].Nsubhalos - 1].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE,
1878 list_max_subhalonr,
sizeof(
long long), MPI_BYTE, Communicator);
1880 int nexport = 0, nimport = 0;
1882 halotrees_propagate_data *import_data = NULL, *export_data = NULL;
1887 halotrees_propagate_data *sorted_list =
1888 (halotrees_propagate_data *)
Mem.mymalloc(
"sorted_list", Cats[num - 1].Nsubhalos *
sizeof(halotrees_propagate_data));
1890 for(
int i = 0; i < Cats[num - 1].Nsubhalos; i++)
1892 sorted_list[i].DescSubhaloNr = Cats[num - 1].Descendants[i].DescSubhaloNr;
1893 sorted_list[i].SubhaloNr = Cats[num - 1].Descendants[i].PrevSubhaloNr;
1894 sorted_list[i].MaxLenProgBranch = Cats[num - 1].SubExt[i].MaxLenProgBranch;
1897 mycxxsort(sorted_list, sorted_list + Cats[num - 1].Nsubhalos, compare_halotrees_propagate_data_DescSubhaloNr);
1900 for(
int mode = 0; mode < 2; mode++)
1902 for(
int i = 0; i < NTask; i++)
1907 for(
int i = 0; i < Cats[num - 1].Nsubhalos; i++)
1909 while(target < NTask - 1 &&
1910 (list_min_subhalonr[target] == empty || sorted_list[i].DescSubhaloNr > list_max_subhalonr[target]))
1913 if(list_min_subhalonr[target] != empty && sorted_list[i].DescSubhaloNr >= list_min_subhalonr[target] &&
1914 sorted_list[i].DescSubhaloNr <= list_max_subhalonr[target])
1917 Send_count[target]++;
1920 int off = Send_offset[target] + Send_count[target]++;
1922 export_data[off].DescSubhaloNr = sorted_list[i].DescSubhaloNr;
1923 export_data[off].SubhaloNr = sorted_list[i].SubhaloNr;
1924 export_data[off].MaxLenProgBranch = sorted_list[i].MaxLenProgBranch;
1931 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
1932 Recv_offset[0] = Send_offset[0] = 0;
1933 for(
int j = 0; j < NTask; j++)
1935 nimport += Recv_count[j];
1936 nexport += Send_count[j];
1939 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
1940 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
1944 export_data = (halotrees_propagate_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(halotrees_propagate_data));
1945 import_data = (halotrees_propagate_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(halotrees_propagate_data));
1950 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
1952 int recvTask = ThisTask ^ ngrp;
1953 if(recvTask < NTask)
1954 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
1955 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE,
1956 recvTask,
TAG_DENS_B, &import_data[Recv_offset[recvTask]],
1957 Recv_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
1964 mycxxsort(import_data, import_data + nimport, compare_halotrees_propagate_data_DescSubhaloNr);
1967 for(
int i = 0, j = 0; i < Cats[num].Nsubhalos && j < nimport;)
1969 if(Cats[num].Subhalo[i].SubhaloNr < import_data[j].DescSubhaloNr)
1971 else if(Cats[num].Subhalo[i].SubhaloNr > import_data[j].DescSubhaloNr)
1975 if(import_data[j].MaxLenProgBranch > Cats[num].SubExt[i].MaxLenProgBranch - Cats[num].Subhalo[i].Len)
1977 Cats[num].SubExt[i].MaxLenProgBranch = import_data[j].MaxLenProgBranch + Cats[num].Subhalo[i].Len;
1978 Cats[num].Progenitors[i].MainProgSubhaloNr = import_data[j].SubhaloNr;
1985 Mem.myfree(import_data);
1986 Mem.myfree(export_data);
1987 Mem.myfree(sorted_list);
1988 Mem.myfree(list_max_subhalonr);
1989 Mem.myfree(list_min_subhalonr);
1991 Mem.myfree(Recv_offset);
1992 Mem.myfree(Recv_count);
1993 Mem.myfree(Send_offset);
1994 Mem.myfree(Send_count);
2000void mergertree::halotrees_propagate_max_branch_length_progenitors(
int num)
2002 int *Send_count = (
int *)
Mem.mymalloc(
"Send_count",
sizeof(
int) * NTask);
2003 int *Send_offset = (
int *)
Mem.mymalloc(
"Send_offset",
sizeof(
int) * NTask);
2004 int *Recv_count = (
int *)
Mem.mymalloc(
"Recv_count",
sizeof(
int) * NTask);
2005 int *Recv_offset = (
int *)
Mem.mymalloc(
"Recv_offset",
sizeof(
int) * NTask);
2010 long long *list_min_subhalonr = (
long long *)
Mem.mymalloc(
"list_min_subhalonr", NTask *
sizeof(
long long));
2011 long long *list_max_subhalonr = (
long long *)
Mem.mymalloc(
"list_max_subhalonr", NTask *
sizeof(
long long));
2016 MPI_Allgather(Cats[num - 1].Nsubhalos > 0 ? &Cats[num - 1].Subhalo[0].SubhaloNr : &empty,
sizeof(
long long), MPI_BYTE,
2017 list_min_subhalonr,
sizeof(
long long), MPI_BYTE, Communicator);
2018 MPI_Allgather(Cats[num - 1].Nsubhalos > 0 ? &Cats[num - 1].Subhalo[Cats[num - 1].Nsubhalos - 1].SubhaloNr : &empty,
2019 sizeof(
long long), MPI_BYTE, list_max_subhalonr,
sizeof(
long long), MPI_BYTE, Communicator);
2021 int nexport = 0, nimport = 0;
2023 halotrees_propagate_data *import_data = NULL, *export_data = NULL;
2028 halotrees_propagate_data *sorted_list =
2029 (halotrees_propagate_data *)
Mem.mymalloc(
"sorted_list", Cats[num].Nsubhalos *
sizeof(halotrees_propagate_data));
2031 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
2033 sorted_list[i].ProgSubhaloNr = Cats[num].Progenitors[i].ProgSubhaloNr;
2034 sorted_list[i].index = i;
2037 mycxxsort(sorted_list, sorted_list + Cats[num].Nsubhalos, compare_halotrees_propagate_data_ProgSubhaloNr);
2040 for(
int mode = 0; mode < 2; mode++)
2042 for(
int i = 0; i < NTask; i++)
2047 for(
int i = 0; i < Cats[num].Nsubhalos; i++)
2049 while(target < NTask - 1 &&
2050 (list_min_subhalonr[target] == empty || sorted_list[i].ProgSubhaloNr > list_max_subhalonr[target]))
2053 if(list_min_subhalonr[target] != empty && sorted_list[i].ProgSubhaloNr >= list_min_subhalonr[target] &&
2054 sorted_list[i].ProgSubhaloNr <= list_max_subhalonr[target])
2057 Send_count[target]++;
2060 int off = Send_offset[target] + Send_count[target]++;
2062 export_data[off].ProgSubhaloNr = sorted_list[i].ProgSubhaloNr;
2063 export_data[off].index = sorted_list[i].index;
2070 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
2071 Recv_offset[0] = Send_offset[0] = 0;
2072 for(
int j = 0; j < NTask; j++)
2074 nimport += Recv_count[j];
2075 nexport += Send_count[j];
2078 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
2079 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
2083 export_data = (halotrees_propagate_data *)
Mem.mymalloc(
"export_data", nexport *
sizeof(halotrees_propagate_data));
2084 import_data = (halotrees_propagate_data *)
Mem.mymalloc(
"import_data", nimport *
sizeof(halotrees_propagate_data));
2089 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
2091 int recvTask = ThisTask ^ ngrp;
2092 if(recvTask < NTask)
2093 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
2094 myMPI_Sendrecv(&export_data[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE,
2095 recvTask,
TAG_DENS_B, &import_data[Recv_offset[recvTask]],
2096 Recv_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
2100 for(
int i = 0; i < nimport; i++)
2101 import_data[i].orig_order = i;
2106 mycxxsort(import_data, import_data + nimport, compare_halotrees_propagate_data_ProgSubhaloNr);
2109 for(
int i = 0, j = 0; i < Cats[num - 1].Nsubhalos && j < nimport;)
2111 if(Cats[num - 1].Subhalo[i].SubhaloNr < import_data[j].ProgSubhaloNr)
2113 else if(Cats[num - 1].Subhalo[i].SubhaloNr > import_data[j].ProgSubhaloNr)
2117 import_data[j].MaxLenProgBranch = Cats[num - 1].SubExt[i].MaxLenProgBranch;
2118 import_data[j].SubhaloNr = Cats[num - 1].Subhalo[i].SubhaloNr;
2120 if(Cats[num - 1].Subhalo[i].SubhaloNr != import_data[j].ProgSubhaloNr)
2121 Terminate(
"Cats[num - 1].Subhalo[i].SubhaloNr != import_data[j].ProgSubhaloNr)");
2128 mycxxsort(import_data, import_data + nimport, compare_halotrees_propagate_data_orig_order);
2131 for(
int ngrp = 0; ngrp < (1 << PTask); ngrp++)
2133 int recvTask = ThisTask ^ ngrp;
2134 if(recvTask < NTask)
2135 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
2136 myMPI_Sendrecv(&import_data[Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE,
2137 recvTask,
TAG_DENS_B, &export_data[Send_offset[recvTask]],
2138 Send_count[recvTask] *
sizeof(halotrees_propagate_data), MPI_BYTE, recvTask,
TAG_DENS_B, Communicator,
2143 for(
int i = 0; i < nexport; i++)
2145 int q = export_data[i].index;
2147 if(export_data[i].MaxLenProgBranch > Cats[num].SubExt[q].MaxLenProgBranch - Cats[num].Subhalo[q].Len)
2149 Cats[num].SubExt[q].MaxLenProgBranch = export_data[i].MaxLenProgBranch + Cats[num].Subhalo[q].Len;
2150 Cats[num].Progenitors[q].MainProgSubhaloNr = export_data[i].SubhaloNr;
2154 Mem.myfree(import_data);
2155 Mem.myfree(export_data);
2156 Mem.myfree(sorted_list);
2157 Mem.myfree(list_max_subhalonr);
2158 Mem.myfree(list_min_subhalonr);
2160 Mem.myfree(Recv_offset);
2161 Mem.myfree(Recv_count);
2162 Mem.myfree(Send_offset);
2163 Mem.myfree(Send_count);
global_data_all_processes All
double mycxxsort(T *begin, T *end, Tcomp comp)
void sumup_large_ints(int n, int *src, long long *res, MPI_Comm comm)
int myMPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
int myMPI_Sendrecv(void *sendbuf, size_t sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, size_t recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status)
double mycxxsort_parallel(T *begin, T *end, Comp comp, MPI_Comm comm)
double get_random_number(void)