OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
SamplingBase.cpp
Go to the documentation of this file.
1#include "SamplingBase.hpp"
2#include <mpi.h>
3#include <algorithm>
4#include <vector>
5
6size_t SamplingBase::computeLocalEmitCount(size_t totalToSample) const {
7 if (!pc_m) {
8 return 0;
9 }
10 const int nranks = ippl::Comm->size();
11 const int rank = ippl::Comm->rank();
12 if (nranks <= 0) {
13 return totalToSample;
14 }
15 if (totalToSample == 0) {
16 return 0;
17 }
18
19 const size_t capacity = pc_m->R.size();
20 const size_t localNum = pc_m->getLocalNum();
21 const size_t spaceLeft = (localNum <= capacity) ? (capacity - localNum) : size_t(0);
22
23 std::vector<unsigned long> spaceLeftAll(static_cast<size_t>(nranks), 0);
24 unsigned long mySpace = static_cast<unsigned long>(spaceLeft);
25 MPI_Allgather(
26 &mySpace, 1, MPI_UNSIGNED_LONG, spaceLeftAll.data(), 1, MPI_UNSIGNED_LONG,
27 ippl::Comm->getCommunicator());
28
29 const size_t nranks_u = static_cast<size_t>(nranks);
30 const size_t base = totalToSample / nranks_u;
31 const size_t rem = totalToSample % nranks_u;
32
33 std::vector<size_t> nlocal(static_cast<size_t>(nranks), 0);
34 size_t sum = 0;
35 for (int r = 0; r < nranks; ++r) {
36 size_t ideal = base + (static_cast<size_t>(r) < rem ? 1 : 0);
37 size_t cap = static_cast<size_t>(spaceLeftAll[static_cast<size_t>(r)]);
38 nlocal[static_cast<size_t>(r)] = std::min(ideal, cap);
39 sum += nlocal[static_cast<size_t>(r)];
40 }
41
42 size_t deficit = totalToSample - sum;
43 while (deficit > 0) {
44 int chosen = -1;
45 for (int r = 0; r < nranks && deficit > 0; ++r) {
46 size_t cap = static_cast<size_t>(spaceLeftAll[static_cast<size_t>(r)]);
47 if (nlocal[static_cast<size_t>(r)] < cap) {
48 chosen = r;
49 break;
50 }
51 }
52 if (chosen < 0) {
53 break;
54 }
55 nlocal[static_cast<size_t>(chosen)] += 1;
56 deficit -= 1;
57 }
58
59 return nlocal[static_cast<size_t>(rank)];
60}
size_t computeLocalEmitCount(size_t totalToSample) const
Computes the number of particles this rank should emit so that the global total equals totalToSample ...
std::shared_ptr< ParticleContainer_t > pc_m