11 #ifndef vtk_m_filter_flow_internal_AdvectAlgorithm_h
12 #define vtk_m_filter_flow_internal_AdvectAlgorithm_h
18 #ifdef VTKM_ENABLE_MPI
21 #include <vtkm/thirdparty/diy/diy.h>
22 #include <vtkm/thirdparty/diy/mpi-cast.h>
34 template <
typename DSIType>
38 using ParticleType =
typename DSIType::PType;
40 AdvectAlgorithm(
const vtkm::filter::flow::internal::BoundsMap& bm, std::vector<DSIType>& blocks)
44 , Exchanger(this->Comm)
45 , Terminator(this->Comm)
47 , NumRanks(this->Comm.size())
48 , Rank(this->Comm.rank())
54 this->SetStepSize(stepSize);
55 this->SetSeeds(seeds);
63 for (
const auto& b : this->Blocks)
76 this->ClearParticles();
81 std::vector<std::vector<vtkm::Id>> blockIDs;
82 std::vector<ParticleType> particles;
85 const ParticleType p = portal.Get(i);
86 std::vector<vtkm::Id> ids = this->BoundsMap.FindBlocks(p.GetPosition());
91 auto ranks = this->BoundsMap.FindRank(ids[0]);
92 if (!ranks.empty() && this->Rank == ranks[0])
94 particles.emplace_back(p);
95 blockIDs.emplace_back(ids);
99 this->SetSeedArray(particles, blockIDs);
102 virtual bool HaveWork()
104 const bool haveParticles = !this->Active.empty() || !this->Inactive.empty();
105 #ifndef VTKM_ENABLE_MPI
106 return haveParticles;
108 return haveParticles || this->Exchanger.HaveWork();
112 virtual bool GetDone()
114 #ifndef VTKM_ENABLE_MPI
115 return !this->HaveWork();
117 return this->Terminator.Done();
124 while (!this->GetDone())
126 std::vector<ParticleType> v;
129 if (this->GetActiveParticles(v, blockId))
132 auto& block = this->GetDataSet(blockId);
133 DSIHelperInfo<ParticleType> bb(v, this->BoundsMap, this->ParticleBlockIDsMap);
134 block.Advect(bb, this->StepSize);
135 this->UpdateResult(bb);
138 this->ExchangeParticles();
142 virtual void ClearParticles()
144 this->Active.clear();
145 this->Inactive.clear();
146 this->ParticleBlockIDsMap.clear();
149 DataSetIntegrator<DSIType, ParticleType>& GetDataSet(
vtkm::Id id)
151 for (
auto& it : this->Blocks)
152 if (it.GetID() ==
id)
158 virtual void SetSeedArray(
const std::vector<ParticleType>& particles,
159 const std::vector<std::vector<vtkm::Id>>& blockIds)
163 auto pit = particles.begin();
164 auto bit = blockIds.begin();
165 while (pit != particles.end() && bit != blockIds.end())
168 this->ParticleBlockIDsMap[pit->GetID()] = *bit;
169 if (this->Active.find(blockId0) == this->Active.end())
170 this->Active[blockId0] = { *pit };
172 this->Active[blockId0].emplace_back(*pit);
178 virtual bool GetActiveParticles(std::vector<ParticleType>& particles,
vtkm::Id& blockId)
182 if (this->Active.empty())
186 if (this->Active.size() == 1)
188 blockId = this->Active.begin()->first;
189 particles = std::move(this->Active.begin()->second);
190 this->Active.clear();
195 std::size_t maxNum = 0;
196 auto maxIt = this->Active.end();
197 for (
auto it = this->Active.begin(); it != this->Active.end(); it++)
199 auto sz = it->second.size();
209 this->Active.clear();
213 blockId = maxIt->first;
214 particles = std::move(maxIt->second);
215 this->Active.erase(maxIt);
218 return !particles.empty();
221 void ExchangeParticles()
223 #ifndef VTKM_ENABLE_MPI
224 this->SerialExchange();
227 if (this->NumRanks == 1)
228 this->SerialExchange();
231 std::vector<ParticleType> outgoing;
232 std::vector<vtkm::Id> outgoingRanks;
234 this->GetOutgoingParticles(outgoing, outgoingRanks);
236 std::vector<ParticleType> incoming;
237 std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> incomingBlockIDs;
239 this->Exchanger.Exchange(
240 outgoing, outgoingRanks, this->ParticleBlockIDsMap, incoming, incomingBlockIDs);
243 for (
const auto& p : outgoing)
244 this->ParticleBlockIDsMap.erase(p.GetID());
246 this->UpdateActive(incoming, incomingBlockIDs);
249 this->Terminator.Control(this->HaveWork());
253 void SerialExchange()
255 for (
const auto& p : this->Inactive)
257 const auto& bid = this->ParticleBlockIDsMap[p.GetID()];
259 this->Active[bid[0]].emplace_back(std::move(p));
261 this->Inactive.clear();
264 #ifdef VTKM_ENABLE_MPI
265 void GetOutgoingParticles(std::vector<ParticleType>& outgoing,
266 std::vector<vtkm::Id>& outgoingRanks)
269 outgoingRanks.clear();
271 outgoing.reserve(this->Inactive.size());
272 outgoingRanks.reserve(this->Inactive.size());
274 std::vector<ParticleType> particlesStaying;
275 std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> particlesStayingBlockIDs;
277 for (
const auto& p : this->Inactive)
279 const auto& bid = this->ParticleBlockIDsMap[p.GetID()];
282 auto ranks = this->BoundsMap.FindRank(bid[0]);
286 if (ranks.size() == 1)
288 if (ranks[0] == this->Rank)
290 particlesStaying.emplace_back(p);
291 particlesStayingBlockIDs[p.GetID()] = this->ParticleBlockIDsMap[p.GetID()];
295 outgoing.emplace_back(p);
296 outgoingRanks.emplace_back(ranks[0]);
304 vtkm::Id outRank = std::rand() % ranks.size();
305 if (outRank == this->Rank)
307 particlesStayingBlockIDs[p.GetID()] = this->ParticleBlockIDsMap[p.GetID()];
308 particlesStaying.emplace_back(p);
312 outgoing.emplace_back(p);
313 outgoingRanks.emplace_back(outRank);
318 this->Inactive.clear();
319 VTKM_ASSERT(outgoing.size() == outgoingRanks.size());
321 VTKM_ASSERT(particlesStaying.size() == particlesStayingBlockIDs.size());
322 if (!particlesStaying.empty())
323 this->UpdateActive(particlesStaying, particlesStayingBlockIDs);
327 virtual void UpdateActive(
const std::vector<ParticleType>& particles,
328 const std::unordered_map<
vtkm::Id, std::vector<vtkm::Id>>& idsMap)
332 if (!particles.empty())
334 for (
auto pit = particles.begin(); pit != particles.end(); pit++)
337 const auto& it = idsMap.find(particleID);
338 VTKM_ASSERT(it != idsMap.end() && !it->second.empty());
340 this->Active[blockId].emplace_back(*pit);
343 for (
const auto& it : idsMap)
344 this->ParticleBlockIDsMap[it.first] = it.second;
348 virtual void UpdateInactive(
const std::vector<ParticleType>& particles,
349 const std::unordered_map<
vtkm::Id, std::vector<vtkm::Id>>& idsMap)
353 this->Inactive.insert(this->Inactive.end(), particles.begin(), particles.end());
354 for (
const auto& it : idsMap)
355 this->ParticleBlockIDsMap[it.first] = it.second;
358 vtkm::Id UpdateResult(
const DSIHelperInfo<ParticleType>& stuff)
360 this->UpdateActive(stuff.InBounds.Particles, stuff.InBounds.BlockIDs);
361 this->UpdateInactive(stuff.OutOfBounds.Particles, stuff.OutOfBounds.BlockIDs);
367 for (
const auto&
id : stuff.TermID)
368 this->ParticleBlockIDsMap.erase(
id);
376 std::unordered_map<vtkm::Id, std::vector<ParticleType>> Active;
377 std::vector<DSIType> Blocks;
378 vtkm::filter::flow::internal::BoundsMap BoundsMap;
380 #ifdef VTKM_ENABLE_MPI
381 ParticleExchanger<ParticleType> Exchanger;
382 AdvectAlgorithmTerminator Terminator;
384 std::vector<ParticleType> Inactive;
388 std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> ParticleBlockIDsMap;
398 #endif //vtk_m_filter_flow_internal_AdvectAlgorithm_h