11 #ifndef vtk_m_filter_flow_internal_AdvectAlgorithm_h
12 #define vtk_m_filter_flow_internal_AdvectAlgorithm_h
28 template <
typename DSIType,
template <
typename>
class ResultType,
typename ParticleType>
32 AdvectAlgorithm(
const vtkm::filter::flow::internal::BoundsMap& bm, std::vector<DSIType>& blocks)
35 , NumRanks(this->Comm.size())
36 , Rank(this->Comm.rank())
44 this->SetNumberOfSteps(numSteps);
45 this->SetStepSize(stepSize);
46 this->SetSeeds(seeds);
54 for (
const auto& b : this->Blocks)
57 if (b.template GetOutput<ParticleType>(ds))
65 void SetNumberOfSteps(
vtkm::Id numSteps) { this->NumberOfSteps = numSteps; }
68 this->ClearParticles();
73 std::vector<std::vector<vtkm::Id>> blockIDs;
74 std::vector<ParticleType> particles;
77 const ParticleType p = portal.Get(i);
78 std::vector<vtkm::Id> ids = this->BoundsMap.FindBlocks(p.GetPosition());
80 if (!ids.empty() && this->BoundsMap.FindRank(ids[0]) == this->Rank)
82 particles.emplace_back(p);
83 blockIDs.emplace_back(ids);
87 this->SetSeedArray(particles, blockIDs);
93 vtkm::filter::flow::internal::ParticleMessenger<ParticleType> messenger(
94 this->Comm, this->BoundsMap, 1, 128);
96 vtkm::Id nLocal =
static_cast<vtkm::Id>(this->Active.size() + this->Inactive.size());
97 this->ComputeTotalNumParticles(nLocal);
99 while (this->TotalNumTerminatedParticles < this->TotalNumParticles)
101 std::vector<ParticleType> v;
103 if (this->GetActiveParticles(v, blockId))
106 auto& block = this->GetDataSet(blockId);
107 DSIHelperInfoType bb =
108 DSIHelperInfo<ParticleType>(v, this->BoundsMap, this->ParticleBlockIDsMap);
109 block.Advect(bb, this->StepSize, this->NumberOfSteps);
110 numTerm = this->UpdateResult(bb.Get<DSIHelperInfo<ParticleType>>());
114 this->Communicate(messenger, numTerm, numTermMessages);
116 this->TotalNumTerminatedParticles += (numTerm + numTermMessages);
117 if (this->TotalNumTerminatedParticles > this->TotalNumParticles)
123 virtual void ClearParticles()
125 this->Active.clear();
126 this->Inactive.clear();
127 this->ParticleBlockIDsMap.clear();
130 void ComputeTotalNumParticles(
const vtkm::Id& numLocal)
132 long long total =
static_cast<long long>(numLocal);
133 #ifdef VTKM_ENABLE_MPI
134 MPI_Comm mpiComm = vtkmdiy::mpi::mpi_cast(this->Comm.handle());
135 MPI_Allreduce(MPI_IN_PLACE, &total, 1, MPI_LONG_LONG, MPI_SUM, mpiComm);
137 this->TotalNumParticles =
static_cast<vtkm::Id>(total);
140 DataSetIntegrator<DSIType>& GetDataSet(
vtkm::Id id)
142 for (
auto& it : this->Blocks)
143 if (it.GetID() ==
id)
149 virtual void SetSeedArray(
const std::vector<ParticleType>& particles,
150 const std::vector<std::vector<vtkm::Id>>& blockIds)
154 auto pit = particles.begin();
155 auto bit = blockIds.begin();
156 while (pit != particles.end() && bit != blockIds.end())
158 this->ParticleBlockIDsMap[pit->GetID()] = *bit;
163 this->Active.insert(this->Active.end(), particles.begin(), particles.end());
166 virtual bool GetActiveParticles(std::vector<ParticleType>& particles,
vtkm::Id& blockId)
170 if (this->Active.empty())
173 blockId = this->ParticleBlockIDsMap[this->Active.front().GetID()][0];
174 auto it = this->Active.begin();
175 while (it != this->Active.end())
178 if (blockId == this->ParticleBlockIDsMap[p.GetID()][0])
180 particles.emplace_back(p);
181 it = this->Active.erase(it);
187 return !particles.empty();
190 virtual void Communicate(vtkm::filter::flow::internal::ParticleMessenger<ParticleType>& messenger,
194 std::vector<ParticleType> incoming;
195 std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> incomingIDs;
197 messenger.Exchange(this->Inactive,
198 this->ParticleBlockIDsMap,
199 numLocalTerminations,
203 this->GetBlockAndWait(numLocalTerminations));
205 this->Inactive.clear();
206 this->UpdateActive(incoming, incomingIDs);
209 virtual void UpdateActive(
const std::vector<ParticleType>& particles,
210 const std::unordered_map<
vtkm::Id, std::vector<vtkm::Id>>& idsMap)
212 this->Update(this->Active, particles, idsMap);
215 virtual void UpdateInactive(
const std::vector<ParticleType>& particles,
216 const std::unordered_map<
vtkm::Id, std::vector<vtkm::Id>>& idsMap)
218 this->Update(this->Inactive, particles, idsMap);
221 void Update(std::vector<ParticleType>& arr,
222 const std::vector<ParticleType>& particles,
223 const std::unordered_map<
vtkm::Id, std::vector<vtkm::Id>>& idsMap)
227 arr.insert(arr.end(), particles.begin(), particles.end());
228 for (
const auto& it : idsMap)
229 this->ParticleBlockIDsMap[it.first] = it.second;
232 vtkm::Id UpdateResult(
const DSIHelperInfo<ParticleType>& stuff)
234 this->UpdateActive(stuff.A, stuff.IdMapA);
235 this->UpdateInactive(stuff.I, stuff.IdMapI);
241 for (
const auto&
id : stuff.TermID)
242 this->ParticleBlockIDsMap.erase(
id);
248 virtual bool GetBlockAndWait(
const vtkm::Id& numLocalTerm)
255 if (this->Active.empty() && this->Inactive.empty() &&
256 (numLocalTerm + this->TotalNumTerminatedParticles < this->TotalNumParticles))
265 std::vector<ParticleType> Active;
266 std::vector<DSIType> Blocks;
267 vtkm::filter::flow::internal::BoundsMap BoundsMap;
269 std::vector<ParticleType> Inactive;
272 std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> ParticleBlockIDsMap;
276 vtkm::Id TotalNumTerminatedParticles = 0;
284 #endif //vtk_m_filter_flow_internal_AdvectAlgorithm_h