123 const auto &grains =
data.d_particlesListTypeParticle;
124 const size_t n_grains = grains.size();
126 std::vector<double> local_c(4 * n_grains, 0.);
127 for (
size_t g = 0; g < n_grains; ++g) {
128 const auto c = grains[g]->getXCenter();
129 local_c[4 * g + 0] = c.d_x;
130 local_c[4 * g + 1] = c.d_y;
131 local_c[4 * g + 2] = c.d_z;
132 local_c[4 * g + 3] = grains[g]->d_geom_p->boundingRadius();
134 std::vector<double> all_c(4 * n_grains *
static_cast<size_t>(size), 0.);
135 MPI_Allgather(local_c.data(),
static_cast<int>(local_c.size()), MPI_DOUBLE,
136 all_c.data(),
static_cast<int>(local_c.size()), MPI_DOUBLE,
139 std::vector<util::Point> centers(n_grains);
140 std::vector<double> radii(n_grains);
141 for (
size_t g = 0; g < n_grains; ++g) {
142 const int own = grains[g]->d_mpiOwner;
143 const size_t base =
static_cast<size_t>(own) * 4 * n_grains + 4 * g;
144 centers[g] =
util::Point(all_c[base + 0], all_c[base + 1], all_c[base + 2]);
145 radii[g] = all_c[base + 3];
148 data.d_mpiIncludeInContactCloud.assign(
data.d_particlesListTypeAll.size(), 0);
149 for (
auto *p :
data.d_particlesListTypeAll) {
151 data.d_mpiIncludeInContactCloud[p->getId()] = 1;
157 std::max(0.25 *
data.d_maxContactR, std::max(
data.d_hMax, 1.0e-16));
158 const double search_r =
159 (
data.d_contNeighSearchRadius > 1.0e-16)
160 ?
data.d_contNeighSearchRadius
161 :
data.d_maxContactR;
162 const double cutoff = search_r + extra;
164 data.d_mpiGhostNeedFrom.assign(
static_cast<size_t>(size), {});
166 auto add_ghost = [&](
size_t g) {
167 auto *pj = grains[g];
170 const int own = pj->d_mpiOwner;
171 if (own < 0 || own == rank)
173 auto &vec =
data.d_mpiGhostNeedFrom[
static_cast<size_t>(own)];
174 const int gid =
static_cast<int>(g);
175 if (std::find(vec.begin(), vec.end(), gid) != vec.end())
178 data.d_mpiIncludeInContactCloud[pj->getId()] = 1;
182 for (
size_t g = 0; g < n_grains; ++g) {
184 for (
size_t i = 0; i < n_grains && !near; ++i) {
187 const double lim = radii[i] + radii[g] + cutoff;
188 if (centers[i].dist(centers[g]) < lim)
197 for (
auto *w :
data.d_particlesListTypeWall) {
200 const auto wc = w->getXCenter();
201 const double wr = w->d_geom_p->boundingRadius();
202 for (
size_t g = 0; g < n_grains; ++g) {
203 const double lim = wr + radii[g] + cutoff;
204 if (wc.dist(centers[g]) < lim)
209 std::vector<int> req_sendcounts(
static_cast<size_t>(size), 0);
210 std::vector<int> req_recvcounts(
static_cast<size_t>(size), 0);
211 for (
int r = 0; r < size; ++r)
212 req_sendcounts[
static_cast<size_t>(r)] =
213 static_cast<int>(
data.d_mpiGhostNeedFrom[
static_cast<size_t>(r)].size());
214 MPI_Alltoall(req_sendcounts.data(), 1, MPI_INT, req_recvcounts.data(), 1,
217 std::vector<int> req_sdispls(
static_cast<size_t>(size), 0);
218 std::vector<int> req_rdispls(
static_cast<size_t>(size), 0);
219 int req_send_total = 0;
220 int req_recv_total = 0;
221 for (
int r = 0; r < size; ++r) {
222 req_sdispls[
static_cast<size_t>(r)] = req_send_total;
223 req_rdispls[
static_cast<size_t>(r)] = req_recv_total;
224 req_send_total += req_sendcounts[
static_cast<size_t>(r)];
225 req_recv_total += req_recvcounts[
static_cast<size_t>(r)];
228 std::vector<int> req_sendbuf(
static_cast<size_t>(req_send_total));
229 for (
int r = 0; r < size; ++r) {
230 const auto &v =
data.d_mpiGhostNeedFrom[
static_cast<size_t>(r)];
231 std::copy(v.begin(), v.end(),
232 req_sendbuf.begin() + req_sdispls[
static_cast<size_t>(r)]);
234 std::vector<int> req_recvbuf(
static_cast<size_t>(req_recv_total));
235 MPI_Alltoallv(req_sendbuf.data(), req_sendcounts.data(), req_sdispls.data(),
236 MPI_INT, req_recvbuf.data(), req_recvcounts.data(),
237 req_rdispls.data(), MPI_INT, comm);
239 data.d_mpiGhostServeTo.assign(
static_cast<size_t>(size), {});
240 for (
int r = 0; r < size; ++r) {
241 const int off = req_rdispls[
static_cast<size_t>(r)];
242 const int nreq = req_recvcounts[
static_cast<size_t>(r)];
243 auto &dst =
data.d_mpiGhostServeTo[
static_cast<size_t>(r)];
244 dst.resize(
static_cast<size_t>(nreq));
245 for (
int k = 0; k < nreq; ++k) {
246 const int g = req_recvbuf[
static_cast<size_t>(off + k)];
247 if (g < 0 ||
static_cast<size_t>(g) >= n_grains)
248 throw std::runtime_error(
"rebuildGhostPlan: bad grain id");
249 if (grains[
static_cast<size_t>(g)]->d_mpiOwner != rank)
250 throw std::runtime_error(
251 "rebuildGhostPlan: requested grain not owned here");
252 dst[
static_cast<size_t>(k)] = g;
256 data.d_mpiGhostPlanValid =
true;
257 data.d_mpiGhostStepsSinceRebuild = 0;
258 data.setKeyData(
"mpi_ghost_grain_count",
static_cast<double>(n_ghost));
264 const auto &grains =
data.d_particlesListTypeParticle;
266 std::vector<std::vector<double>> kin_send(
static_cast<size_t>(size));
267 for (
int r = 0; r < size; ++r) {
268 for (
int g :
data.d_mpiGhostServeTo[
static_cast<size_t>(r)])
270 kin_send[
static_cast<size_t>(r)]);
273 std::vector<int> kin_sendcounts(
static_cast<size_t>(size), 0);
274 std::vector<int> kin_recvcounts(
static_cast<size_t>(size), 0);
275 for (
int r = 0; r < size; ++r)
276 kin_sendcounts[
static_cast<size_t>(r)] =
277 static_cast<int>(kin_send[
static_cast<size_t>(r)].size());
278 MPI_Alltoall(kin_sendcounts.data(), 1, MPI_INT, kin_recvcounts.data(), 1,
281 std::vector<int> kin_sdispls(
static_cast<size_t>(size), 0);
282 std::vector<int> kin_rdispls(
static_cast<size_t>(size), 0);
283 int kin_send_total = 0;
284 int kin_recv_total = 0;
285 for (
int r = 0; r < size; ++r) {
286 kin_sdispls[
static_cast<size_t>(r)] = kin_send_total;
287 kin_rdispls[
static_cast<size_t>(r)] = kin_recv_total;
288 kin_send_total += kin_sendcounts[
static_cast<size_t>(r)];
289 kin_recv_total += kin_recvcounts[
static_cast<size_t>(r)];
292 std::vector<double> kin_sendbuf(
static_cast<size_t>(kin_send_total));
293 for (
int r = 0; r < size; ++r) {
294 const auto &v = kin_send[
static_cast<size_t>(r)];
295 std::copy(v.begin(), v.end(),
296 kin_sendbuf.begin() + kin_sdispls[
static_cast<size_t>(r)]);
298 std::vector<double> kin_recvbuf(
static_cast<size_t>(kin_recv_total));
299 MPI_Alltoallv(kin_sendbuf.data(), kin_sendcounts.data(), kin_sdispls.data(),
300 MPI_DOUBLE, kin_recvbuf.data(), kin_recvcounts.data(),
301 kin_rdispls.data(), MPI_DOUBLE, comm);
303 for (
int r = 0; r < size; ++r) {
304 size_t off =
static_cast<size_t>(kin_rdispls[
static_cast<size_t>(r)]);
305 for (
int g :
data.d_mpiGhostNeedFrom[
static_cast<size_t>(r)])