VTK-m  2.2
DataSetIntegrator.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 
11 #ifndef vtk_m_filter_flow_internal_DataSetIntegrator_h
12 #define vtk_m_filter_flow_internal_DataSetIntegrator_h
13 
14 #include <vtkm/cont/DataSet.h>
19 #include <vtkm/filter/flow/worklet/EulerIntegrator.h>
20 #include <vtkm/filter/flow/worklet/IntegratorStatus.h>
21 #include <vtkm/filter/flow/worklet/ParticleAdvection.h>
22 #include <vtkm/filter/flow/worklet/RK4Integrator.h>
23 #include <vtkm/filter/flow/worklet/Stepper.h>
24 
25 #include <vtkm/cont/Variant.h>
26 
27 namespace vtkm
28 {
29 namespace filter
30 {
31 namespace flow
32 {
33 namespace internal
34 {
35 
36 template <typename ParticleType>
37 class DSIHelperInfo
38 {
39 public:
40  DSIHelperInfo(const std::vector<ParticleType>& v,
41  const vtkm::filter::flow::internal::BoundsMap& boundsMap,
42  const std::unordered_map<vtkm::Id, std::vector<vtkm::Id>>& particleBlockIDsMap)
43  : BoundsMap(boundsMap)
44  , ParticleBlockIDsMap(particleBlockIDsMap)
45  , Particles(v)
46  {
47  }
48 
49  struct ParticleBlockIds
50  {
51  void Clear()
52  {
53  this->Particles.clear();
54  this->BlockIDs.clear();
55  }
56 
57  void Add(const ParticleType& p, const std::vector<vtkm::Id>& bids)
58  {
59  this->Particles.emplace_back(p);
60  this->BlockIDs[p.GetID()] = std::move(bids);
61  }
62 
63  std::vector<ParticleType> Particles;
64  std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> BlockIDs;
65  };
66 
67  void Clear()
68  {
69  this->InBounds.Clear();
70  this->OutOfBounds.Clear();
71  this->TermIdx.clear();
72  this->TermID.clear();
73  }
74 
75  void Validate(vtkm::Id num)
76  {
77  //Make sure we didn't miss anything. Every particle goes into a single bucket.
78  if ((static_cast<std::size_t>(num) !=
79  (this->InBounds.Particles.size() + this->OutOfBounds.Particles.size() +
80  this->TermIdx.size())) ||
81  (this->InBounds.Particles.size() != this->InBounds.BlockIDs.size()) ||
82  (this->OutOfBounds.Particles.size() != this->OutOfBounds.BlockIDs.size()) ||
83  (this->TermIdx.size() != this->TermID.size()))
84  {
85  throw vtkm::cont::ErrorFilterExecution("Particle count mismatch after classification");
86  }
87  }
88 
89  void AddTerminated(vtkm::Id idx, vtkm::Id pID)
90  {
91  this->TermIdx.emplace_back(idx);
92  this->TermID.emplace_back(pID);
93  }
94 
95  vtkm::filter::flow::internal::BoundsMap BoundsMap;
96  std::unordered_map<vtkm::Id, std::vector<vtkm::Id>> ParticleBlockIDsMap;
97 
98  ParticleBlockIds InBounds;
99  ParticleBlockIds OutOfBounds;
100  std::vector<ParticleType> Particles;
101  std::vector<vtkm::Id> TermID;
102  std::vector<vtkm::Id> TermIdx;
103 };
104 
105 template <typename Derived, typename ParticleType>
106 class DataSetIntegrator
107 {
108 public:
109  DataSetIntegrator(vtkm::Id id, vtkm::filter::flow::IntegrationSolverType solverType)
110  : Id(id)
111  , SolverType(solverType)
112  , Rank(this->Comm.rank())
113  {
114  //check that things are valid.
115  }
116 
117  VTKM_CONT vtkm::Id GetID() const { return this->Id; }
118  VTKM_CONT void SetCopySeedFlag(bool val) { this->CopySeedArray = val; }
119 
120  VTKM_CONT
121  void Advect(DSIHelperInfo<ParticleType>& b,
122  vtkm::FloatDefault stepSize) //move these to member data(?)
123  {
124  Derived* inst = static_cast<Derived*>(this);
125  inst->DoAdvect(b, stepSize);
126  }
127 
128  VTKM_CONT bool GetOutput(vtkm::cont::DataSet& dataset) const
129  {
130  Derived* inst = static_cast<Derived*>(this);
131  return inst->GetOutput(dataset);
132  }
133 
134 protected:
135  VTKM_CONT inline void ClassifyParticles(const vtkm::cont::ArrayHandle<ParticleType>& particles,
136  DSIHelperInfo<ParticleType>& dsiInfo) const;
137 
138  //Data members.
139  vtkm::Id Id;
141  vtkmdiy::mpi::communicator Comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
142  vtkm::Id Rank;
143  bool CopySeedArray = false;
144 };
145 
146 template <typename Derived, typename ParticleType>
147 VTKM_CONT inline void DataSetIntegrator<Derived, ParticleType>::ClassifyParticles(
148  const vtkm::cont::ArrayHandle<ParticleType>& particles,
149  DSIHelperInfo<ParticleType>& dsiInfo) const
150 {
151  /*
152  each particle: --> T,I,A
153  if T: update TermIdx, TermID
154  if A: update IdMapA;
155  if I: update IdMapI;
156  */
157  dsiInfo.Clear();
158 
159  auto portal = particles.WritePortal();
160  vtkm::Id n = portal.GetNumberOfValues();
161 
162  for (vtkm::Id i = 0; i < n; i++)
163  {
164  auto p = portal.Get(i);
165 
166  //Terminated.
167  if (p.GetStatus().CheckTerminate())
168  {
169  dsiInfo.AddTerminated(i, p.GetID());
170  }
171  else
172  {
173  //Didn't terminate.
174  //Get the blockIDs.
175  const auto& it = dsiInfo.ParticleBlockIDsMap.find(p.GetID());
176  VTKM_ASSERT(it != dsiInfo.ParticleBlockIDsMap.end());
177  auto currBIDs = it->second;
178  VTKM_ASSERT(!currBIDs.empty());
179 
180  std::vector<vtkm::Id> newIDs;
181  if (p.GetStatus().CheckSpatialBounds() && !p.GetStatus().CheckTookAnySteps())
182  {
183  //particle is OUTSIDE but didn't take any steps.
184  //this means that the particle wasn't in the block.
185  //assign newIDs to currBIDs[1:]
186  newIDs.assign(std::next(currBIDs.begin(), 1), currBIDs.end());
187  }
188  else
189  {
190  //Otherwise, get new blocks from the current position.
191  newIDs = dsiInfo.BoundsMap.FindBlocks(p.GetPosition(), currBIDs);
192  }
193 
194  //reset the particle status.
195  p.GetStatus() = vtkm::ParticleStatus();
196 
197  if (newIDs.empty()) //No blocks, we're done.
198  {
199  p.GetStatus().SetTerminate();
200  dsiInfo.AddTerminated(i, p.GetID());
201  }
202  else
203  {
204  //If we have more than one blockId, we want to minimize communication
205  //and put any blocks owned by this rank first.
206  if (newIDs.size() > 1)
207  {
208  for (auto idit = newIDs.begin(); idit != newIDs.end(); idit++)
209  {
210  vtkm::Id bid = *idit;
211  auto ranks = dsiInfo.BoundsMap.FindRank(bid);
212  if (std::find(ranks.begin(), ranks.end(), this->Rank) != ranks.end())
213  {
214  newIDs.erase(idit);
215  newIDs.insert(newIDs.begin(), bid);
216  break;
217  }
218  }
219  }
220 
221  dsiInfo.OutOfBounds.Add(p, newIDs);
222  }
223  }
224  portal.Set(i, p);
225  }
226 
227  //Make sure everything is copacetic.
228  dsiInfo.Validate(n);
229 }
230 
231 }
232 }
233 }
234 } //vtkm::filter::flow::internal
235 
236 #endif //vtk_m_filter_flow_internal_DataSetIntegrator_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
BoundsMap.h
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
vtkm::cont::ErrorFilterExecution
This class is primarily intended to filters to throw in the control environment to indicate an execut...
Definition: ErrorFilterExecution.h:27
Variant.h
vtkm::cont::DataSet
Contains and manages the geometric data structures that VTK-m operates on.
Definition: DataSet.h:57
ErrorFilterExecution.h
vtkm::filter::flow::IntegrationSolverType
IntegrationSolverType
Definition: FlowTypes.h:19
ParticleArrayCopy.h
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
vtkm::ParticleStatus
Definition: Particle.h:23
vtkm::cont::EnvironmentTracker::GetCommunicator
static const vtkmdiy::mpi::communicator & GetCommunicator()
vtkm::FloatDefault
vtkm::Float32 FloatDefault
The floating point type to use when no other precision is specified.
Definition: Types.h:236
vtkm::cont::ArrayHandle::WritePortal
WritePortalType WritePortal() const
Get an array portal that can be used in the control environment.
Definition: ArrayHandle.h:454
FlowTypes.h
DataSet.h