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