12#include "gadgetconfig.h"
23#include "../data/allvars.h"
24#include "../data/dtypes.h"
25#include "../data/mymalloc.h"
26#include "../domain/domain.h"
27#include "../fof/fof.h"
28#include "../gravtree/gravtree.h"
29#include "../logs/timer.h"
30#include "../main/simulation.h"
31#include "../mpi_utils/mpi_utils.h"
32#include "../sort/cxxsort.h"
33#include "../subfind/subfind.h"
35template <
typename partset>
36void fof<partset>::subfind_distribute_groups(
void)
40 int *Send_count = (
int *)
Mem.mymalloc_movable(&Send_count,
"Send_count",
sizeof(
int) * NTask);
41 int *Send_offset = (
int *)
Mem.mymalloc_movable(&Send_offset,
"Send_offset",
sizeof(
int) * NTask);
42 int *Recv_count = (
int *)
Mem.mymalloc_movable(&Recv_count,
"Recv_count",
sizeof(
int) * NTask);
43 int *Recv_offset = (
int *)
Mem.mymalloc_movable(&Recv_offset,
"Recv_offset",
sizeof(
int) * NTask);
46 for(
int i = 0; i < NTask; i++)
49 for(
int i = 0; i < Ngroups; i++)
51 int target = Group[i].TargetTask;
53 if(target < 0 || target >= NTask)
54 Terminate(
"target < 0 || target >= NTask");
56 if(target != ThisTask)
60 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
62 Recv_offset[0] = Send_offset[0] = 0;
63 int nexport = 0, nimport = 0;
65 for(
int i = 0; i < NTask; i++)
67 nimport += Recv_count[i];
68 nexport += Send_count[i];
72 Send_offset[i] = Send_offset[i - 1] + Send_count[i - 1];
73 Recv_offset[i] = Recv_offset[i - 1] + Recv_count[i - 1];
77 group_properties *send_Group =
78 (group_properties *)
Mem.mymalloc_movable(&send_Group,
"send_Group", nexport *
sizeof(group_properties));
80 for(
int i = 0; i < NTask; i++)
83 for(
int i = 0; i < Ngroups; i++)
85 int target = Group[i].TargetTask;
87 if(target != ThisTask)
89 send_Group[Send_offset[target] + Send_count[target]] = Group[i];
92 Group[i] = Group[Ngroups - 1];
98 if(Ngroups + nimport > MaxNgroups)
100 MaxNgroups = Ngroups + nimport;
101 Group = (group_properties *)
Mem.myrealloc_movable(Group,
sizeof(group_properties) * MaxNgroups);
104 for(
int ngrp = 1; ngrp < (1 << PTask); ngrp++)
106 int recvTask = ThisTask ^ ngrp;
110 if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
113 myMPI_Sendrecv(&send_Group[Send_offset[recvTask]], Send_count[recvTask] *
sizeof(group_properties), MPI_BYTE, recvTask,
114 TAG_DENS_A, &Group[Ngroups + Recv_offset[recvTask]], Recv_count[recvTask] *
sizeof(group_properties),
115 MPI_BYTE, recvTask,
TAG_DENS_A, Communicator, MPI_STATUS_IGNORE);
122 Mem.myfree_movable(send_Group);
124 Mem.myfree(Recv_offset);
125 Mem.myfree(Recv_count);
126 Mem.myfree(Send_offset);
127 Mem.myfree(Send_count);
131 mpi_printf(
"SUBFIND: subfind_distribute_groups() took %g sec\n",
Logs.
timediff(t0, t1));
138template <
typename partset>
139void fof<partset>::subfind_distribute_particles(MPI_Comm Communicator)
141 int *Send_count = (
int *)
Mem.mymalloc_movable(&Send_count,
"Send_count",
sizeof(
int) * NTask);
142 int *Send_offset = (
int *)
Mem.mymalloc_movable(&Send_offset,
"Send_offset",
sizeof(
int) * NTask);
143 int *Recv_count = (
int *)
Mem.mymalloc_movable(&Recv_count,
"Recv_count",
sizeof(
int) * NTask);
144 int *Recv_offset = (
int *)
Mem.mymalloc_movable(&Recv_offset,
"Recv_offset",
sizeof(
int) * NTask);
146 int CommThisTask, CommNTask;
147 MPI_Comm_size(Communicator, &CommNTask);
148 MPI_Comm_rank(Communicator, &CommThisTask);
150 for(
int n = 0; n < CommNTask; n++)
153 for(
int n = 0; n < Tp->NumPart; n++)
155 int target = Tp->PS[n].TargetTask;
157 if(target != CommThisTask)
159 if(target < 0 || target >= CommNTask)
160 Terminate(
"n=%d targettask=%d", n, target);
162 Send_count[target]++;
166 myMPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, Communicator);
168 int nimport = 0, nexport = 0;
169 Recv_offset[0] = 0, Send_offset[0] = 0;
171 for(
int j = 0; j < CommNTask; j++)
173 nexport += Send_count[j];
174 nimport += Recv_count[j];
178 Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
179 Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
184 int load = (Tp->NumPart + (nimport - nexport)), max_load;
185 MPI_Allreduce(&load, &max_load, 1, MPI_INT, MPI_MAX, Communicator);
187 typename partset::pdata *partBuf =
188 (
typename partset::pdata *)
Mem.mymalloc_movable(&partBuf,
"partBuf", nexport *
sizeof(
typename partset::pdata));
191 for(
int i = 0; i < CommNTask; i++)
194 for(
int n = 0; n < Tp->NumPart; n++)
196 int target = Tp->PS[n].TargetTask;
198 if(target != CommThisTask)
200 partBuf[Send_offset[target] + Send_count[target]] = Tp->P[n];
201 subBuf[Send_offset[target] + Send_count[target]] = Tp->PS[n];
203 Tp->P[n] = Tp->P[Tp->NumPart - 1];
204 Tp->PS[n] = Tp->PS[Tp->NumPart - 1];
206 Send_count[target]++;
218 for(
int i = 0; i < CommNTask; i++)
219 Recv_offset[i] += Tp->NumPart;
221#ifdef ISEND_IRECV_IN_DOMAIN
223 MPI_Request *requests = (MPI_Request *)
Mem.mymalloc(
"requests", 8 * CommNTask *
sizeof(MPI_Request));
226 for(
int ngrp = 1; ngrp < (1 << PTask); ngrp++)
228 int target = CommThisTask ^ ngrp;
230 if(target < CommNTask)
232 if(Recv_count[target] > 0)
234 MPI_Irecv(Tp->P + Recv_offset[target], Recv_count[target] *
sizeof(
typename partset::pdata), MPI_BYTE, target,
TAG_PDATA,
235 Communicator, &requests[n_requests++]);
236 MPI_Irecv(Tp->PS + Recv_offset[target], Recv_count[target] *
sizeof(
subfind_data), MPI_BYTE, target,
TAG_KEY,
237 Communicator, &requests[n_requests++]);
242 for(
int ngrp = 1; ngrp < (1 << PTask); ngrp++)
244 int target = CommThisTask ^ ngrp;
246 if(target < CommNTask)
248 if(Send_count[target] > 0)
250 MPI_Issend(partBuf + Send_offset[target], Send_count[target] *
sizeof(
typename partset::pdata), MPI_BYTE, target,
251 TAG_PDATA, Communicator, &requests[n_requests++]);
252 MPI_Issend(subBuf + Send_offset[target], Send_count[target] *
sizeof(
subfind_data), MPI_BYTE, target,
TAG_KEY,
253 Communicator, &requests[n_requests++]);
258 MPI_Waitall(n_requests, requests, MPI_STATUSES_IGNORE);
259 Mem.myfree(requests);
262 for(
int ngrp = 1; ngrp < (1 << PTask); ngrp++)
264 int target = CommThisTask ^ ngrp;
266 if(target < CommNTask)
268 if(Send_count[target] > 0 || Recv_count[target] > 0)
270 myMPI_Sendrecv(partBuf + Send_offset[target], Send_count[target] *
sizeof(
typename partset::pdata), MPI_BYTE, target,
271 TAG_PDATA, Tp->P + Recv_offset[target], Recv_count[target] *
sizeof(
typename partset::pdata), MPI_BYTE,
272 target,
TAG_PDATA, Communicator, MPI_STATUS_IGNORE);
275 Tp->PS + Recv_offset[target], Recv_count[target] *
sizeof(
subfind_data), MPI_BYTE, target,
TAG_KEY,
276 Communicator, MPI_STATUS_IGNORE);
282 Tp->NumPart += nimport;
283 Mem.myfree_movable(subBuf);
284 Mem.myfree_movable(partBuf);
287 FoFDomain->reorder_P_PS(0, Tp->NumPart);
289 Mem.myfree(Recv_offset);
290 Mem.myfree(Recv_count);
291 Mem.myfree(Send_offset);
292 Mem.myfree(Send_count);
296#include "../data/simparticles.h"
297template class fof<simparticles>;
299#if defined(LIGHTCONE) && defined(LIGHTCONE_PARTICLES_GROUPS)
300#include "../data/lcparticles.h"
301template class fof<lcparticles>;
double timediff(double t0, double t1)
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)