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