19 #ifndef viskores_filter_flow_internal_BoundsMap_h
20 #define viskores_filter_flow_internal_BoundsMap_h
30 #include <viskores/thirdparty/diy/diy.h>
32 #ifdef VISKORES_ENABLE_MPI
34 #include <viskores/thirdparty/diy/mpi-cast.h>
51 class VISKORES_ALWAYS_EXPORT BoundsMap
60 this->Init({ dataSet }, { blockId });
63 BoundsMap(
const std::vector<viskores::cont::DataSet>& dataSets) { this->Init(dataSets); }
68 const std::vector<viskores::Id>& blockIds)
77 VISKORES_ASSERT(idx >= 0 &&
static_cast<std::size_t
>(idx) < this->BlockBounds.size());
79 return this->BlockBounds[
static_cast<std::size_t
>(idx)];
85 return this->LocalIDs[
static_cast<std::size_t
>(idx)];
90 auto it = this->BlockToRankMap.find(blockId);
91 if (it == this->BlockToRankMap.end())
99 return this->FindBlocks(p, -1);
103 const std::vector<viskores::Id>& ignoreBlocks)
const
105 viskores::Id ignoreID = (ignoreBlocks.empty() ? -1 : ignoreBlocks[0]);
106 return FindBlocks(p, ignoreID);
111 std::vector<viskores::Id> blockIDs;
112 if (this->GlobalBounds.Contains(p))
115 for (
auto& it : this->BlockBounds)
117 if (blockId != ignoreBlock && it.Contains(p))
118 blockIDs.emplace_back(blockId);
126 viskores::Id GetTotalNumBlocks()
const {
return this->TotalNumBlocks; }
127 viskores::Id GetLocalNumBlocks()
const {
return this->LocalNumBlocks; }
130 void Init(
const std::vector<viskores::cont::DataSet>& dataSets,
131 const std::vector<viskores::Id>& blockIds)
133 if (dataSets.size() != blockIds.size())
136 this->LocalIDs = blockIds;
137 this->LocalNumBlocks = dataSets.size();
143 if (!this->LocalIDs.empty())
145 locMinId = *std::min_element(this->LocalIDs.begin(), this->LocalIDs.end());
146 locMaxId = *std::max_element(this->LocalIDs.begin(), this->LocalIDs.end());
151 viskoresdiy::mpi::all_reduce(
152 comm, locMinId, globalMinId, viskoresdiy::mpi::minimum<viskores::Id>{});
153 viskoresdiy::mpi::all_reduce(
154 comm, locMaxId, globalMaxId, viskoresdiy::mpi::maximum<viskores::Id>{});
155 if (globalMinId != 0 || (globalMaxId - globalMinId) < 1)
159 std::vector<viskores::Id> locBlockCounts(comm.size(), 0), globalBlockCounts(comm.size(), 0);
160 locBlockCounts[comm.rank()] = this->LocalIDs.size();
161 viskoresdiy::mpi::all_reduce(
162 comm, locBlockCounts, globalBlockCounts, std::plus<viskores::Id>{});
166 std::accumulate(globalBlockCounts.begin(), globalBlockCounts.end(),
viskores::Id{ 0 });
170 for (
int i = 0; i < comm.rank(); i++)
171 offset += globalBlockCounts[i];
174 std::vector<viskores::Id> localBlockIds(globalNumBlocks, 0);
176 for (
const auto& bid : this->LocalIDs)
177 localBlockIds[offset + idx++] = bid;
180 std::vector<viskores::Id> globalBlockIds(globalNumBlocks, 0);
181 viskoresdiy::mpi::all_reduce(comm, localBlockIds, globalBlockIds, std::plus<viskores::Id>{});
186 std::vector<std::vector<viskores::Id>> rankToBlockIds(comm.size());
189 for (
int rank = 0; rank < comm.size(); rank++)
192 rankToBlockIds[rank].resize(numBIds);
194 rankToBlockIds[rank][i] = globalBlockIds[offset + i];
200 std::set<viskores::Id> globalUniqueBlockIds;
201 globalUniqueBlockIds.insert(globalBlockIds.begin(), globalBlockIds.end());
202 this->TotalNumBlocks = globalUniqueBlockIds.size();
205 std::vector<std::vector<viskores::Id>> blockIdsToRank(this->TotalNumBlocks);
206 for (
int rank = 0; rank < comm.size(); rank++)
208 for (
const auto& bid : rankToBlockIds[rank])
210 blockIdsToRank[bid].push_back(rank);
211 this->BlockToRankMap[bid].push_back(rank);
215 this->Build(dataSets);
218 void Init(
const std::vector<viskores::cont::DataSet>& dataSets)
220 this->LocalNumBlocks = dataSets.size();
223 this->TotalNumBlocks = assigner.nblocks();
224 std::vector<int> ids;
227 assigner.local_gids(Comm.rank(), ids);
228 for (
const auto& i : ids)
229 this->LocalIDs.emplace_back(
static_cast<viskores::Id>(i));
231 for (
viskores::Id id = 0;
id < this->TotalNumBlocks;
id++)
232 this->BlockToRankMap[
id] = { assigner.rank(
static_cast<int>(
id)) };
233 this->Build(dataSets);
236 void Build(
const std::vector<viskores::cont::DataSet>& dataSets)
238 std::vector<viskores::Float64> vals(
static_cast<std::size_t
>(this->TotalNumBlocks * 6), 0);
239 std::vector<viskores::Float64> vals2(vals.size());
241 std::vector<viskores::Float64> localMins((this->TotalNumBlocks * 3),
242 std::numeric_limits<viskores::Float64>::max());
243 std::vector<viskores::Float64> localMaxs((this->TotalNumBlocks * 3),
244 -std::numeric_limits<viskores::Float64>::max());
246 for (std::size_t i = 0; i < this->LocalIDs.size(); i++)
252 localMins[localID * 3 + 0] = bounds.
X.
Min;
253 localMins[localID * 3 + 1] = bounds.Y.Min;
254 localMins[localID * 3 + 2] = bounds.Z.Min;
255 localMaxs[localID * 3 + 0] = bounds.X.Max;
256 localMaxs[localID * 3 + 1] = bounds.Y.Max;
257 localMaxs[localID * 3 + 2] = bounds.Z.Max;
260 std::vector<viskores::Float64> globalMins, globalMaxs;
262 #ifdef VISKORES_ENABLE_MPI
263 globalMins.resize(this->TotalNumBlocks * 3);
264 globalMaxs.resize(this->TotalNumBlocks * 3);
268 viskoresdiy::mpi::all_reduce(
269 comm, localMins, globalMins, viskoresdiy::mpi::minimum<viskores::Float64>{});
270 viskoresdiy::mpi::all_reduce(
271 comm, localMaxs, globalMaxs, viskoresdiy::mpi::maximum<viskores::Float64>{});
273 globalMins = localMins;
274 globalMaxs = localMaxs;
277 this->BlockBounds.resize(
static_cast<std::size_t
>(this->TotalNumBlocks));
281 for (
auto& block : this->BlockBounds)
288 globalMaxs[idx + 2]);
289 this->GlobalBounds.Include(block);
295 std::vector<viskores::Id> LocalIDs;
296 std::map<viskores::Id, std::vector<viskores::Int32>> BlockToRankMap;
298 std::vector<viskores::Bounds> BlockBounds;
307 #endif //viskores_filter_flow_internal_BoundsMap_h