VTK-m  2.0
ParticleAdvectionWorklets.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_worklet_ParticleAdvectionWorklets_h
12 #define vtk_m_filter_flow_worklet_ParticleAdvectionWorklets_h
13 
14 #include <vtkm/cont/Algorithm.h>
18 
19 #include <vtkm/Particle.h>
22 
23 #ifdef VTKM_CUDA
25 #endif
26 
27 namespace vtkm
28 {
29 namespace worklet
30 {
31 namespace flow
32 {
33 
35 {
36 public:
37  using ControlSignature = void(FieldIn idx,
38  ExecObject integrator,
39  ExecObject integralCurve,
40  FieldIn maxSteps);
41  using ExecutionSignature = void(_1 idx, _2 integrator, _3 integralCurve, _4 maxSteps);
42  using InputDomain = _1;
43 
44  template <typename IntegratorType, typename IntegralCurveType>
45  VTKM_EXEC void operator()(const vtkm::Id& idx,
46  const IntegratorType& integrator,
47  IntegralCurveType& integralCurve,
48  const vtkm::Id& maxSteps) const
49  {
50  auto particle = integralCurve.GetParticle(idx);
51  vtkm::FloatDefault time = particle.GetTime();
52  bool tookAnySteps = false;
53 
54  //the integrator status needs to be more robust:
55  // 1. you could have success AND at temporal boundary.
56  // 2. could you have success AND at spatial?
57  // 3. all three?
58  integralCurve.PreStepUpdate(idx);
59  do
60  {
61  particle = integralCurve.GetParticle(idx);
62  vtkm::Vec3f outpos;
63  auto status = integrator.Step(particle, time, outpos);
64  if (status.CheckOk())
65  {
66  integralCurve.StepUpdate(idx, particle, time, outpos);
67  tookAnySteps = true;
68  }
69 
70  //We can't take a step inside spatial boundary.
71  //Try and take a step just past the boundary.
72  else if (status.CheckSpatialBounds())
73  {
74  status = integrator.SmallStep(particle, time, outpos);
75  if (status.CheckOk())
76  {
77  integralCurve.StepUpdate(idx, particle, time, outpos);
78  tookAnySteps = true;
79  }
80  }
81  integralCurve.StatusUpdate(idx, status, maxSteps);
82  } while (integralCurve.CanContinue(idx));
83 
84  //Mark if any steps taken
85  integralCurve.UpdateTookSteps(idx, tookAnySteps);
86  }
87 };
88 
89 
90 template <typename IntegratorType, typename ParticleType>
92 {
93 public:
95 
97 
98  void Run(const IntegratorType& integrator,
100  vtkm::Id& MaxSteps)
101  {
102 
103  using ParticleAdvectWorkletType = vtkm::worklet::flow::ParticleAdvectWorklet;
104  using ParticleWorkletDispatchType =
106  using ParticleArrayType = vtkm::worklet::flow::Particles<ParticleType>;
107 
108  vtkm::Id numSeeds = static_cast<vtkm::Id>(particles.GetNumberOfValues());
109  //Create and invoke the particle advection.
110  vtkm::cont::ArrayHandleConstant<vtkm::Id> maxSteps(MaxSteps, numSeeds);
111  vtkm::cont::ArrayHandleIndex idxArray(numSeeds);
112 
113  // TODO: The particle advection sometimes behaves incorrectly on CUDA if the stack size
114  // is not changed thusly. This is concerning as the compiler should be able to determine
115  // staticly the required stack depth. What is even more concerning is that the runtime
116  // does not report a stack overflow. Rather, the worklet just silently reports the wrong
117  // value. Until we determine the root cause, other problems may pop up.
118 #ifdef VTKM_CUDA
119  // This worklet needs some extra space on CUDA.
120  vtkm::cont::cuda::internal::ScopedCudaStackSize stack(16 * 1024);
121  (void)stack;
122 #endif // VTKM_CUDA
123 
124  ParticleArrayType particlesObj(particles, MaxSteps);
125 
126  //Invoke particle advection worklet
127  ParticleWorkletDispatchType particleWorkletDispatch;
128 
129  particleWorkletDispatch.Invoke(idxArray, integrator, particlesObj, maxSteps);
130  }
131 };
132 
133 namespace detail
134 {
135 class GetSteps : public vtkm::worklet::WorkletMapField
136 {
137 public:
138  VTKM_CONT
139  GetSteps() {}
140  using ControlSignature = void(FieldIn, FieldOut);
141  using ExecutionSignature = void(_1, _2);
142 
143  template <typename ParticleType>
144  VTKM_EXEC void operator()(const ParticleType& p, vtkm::Id& numSteps) const
145  {
146  numSteps = p.GetNumberOfSteps();
147  }
148 };
149 
150 class ComputeNumPoints : public vtkm::worklet::WorkletMapField
151 {
152 public:
153  VTKM_CONT
154  ComputeNumPoints() {}
155  using ControlSignature = void(FieldIn, FieldIn, FieldOut);
156  using ExecutionSignature = void(_1, _2, _3);
157 
158  // Offset is number of points in streamline.
159  // 1 (inital point) + number of steps taken (p.GetNumberOfSteps() - initalNumSteps)
160  template <typename ParticleType>
161  VTKM_EXEC void operator()(const ParticleType& p,
162  const vtkm::Id& initialNumSteps,
163  vtkm::Id& diff) const
164  {
165  diff = 1 + p.GetNumberOfSteps() - initialNumSteps;
166  }
167 };
168 } // namespace detail
169 
170 
171 template <typename IntegratorType, typename ParticleType>
173 {
174 public:
175  template <typename PointStorage, typename PointStorage2>
176  void Run(const IntegratorType& it,
178  vtkm::Id& MaxSteps,
181  {
182 
183  using ParticleWorkletDispatchType =
186 
187  vtkm::cont::ArrayHandle<vtkm::Id> initialStepsTaken;
188 
189  vtkm::Id numSeeds = static_cast<vtkm::Id>(particles.GetNumberOfValues());
190  vtkm::cont::ArrayHandleIndex idxArray(numSeeds);
191 
192  vtkm::worklet::DispatcherMapField<detail::GetSteps> getStepDispatcher{ (detail::GetSteps{}) };
193  getStepDispatcher.Invoke(particles, initialStepsTaken);
194 
195  // This method uses the same workklet as ParticleAdvectionWorklet::Run (and more). Yet for
196  // some reason ParticleAdvectionWorklet::Run needs this adjustment while this method does
197  // not.
198 #ifdef VTKM_CUDA
199  // // This worklet needs some extra space on CUDA.
200  // vtkm::cont::cuda::internal::ScopedCudaStackSize stack(16 * 1024);
201  // (void)stack;
202 #endif // VTKM_CUDA
203 
204  //Run streamline worklet
205  StreamlineArrayType streamlines(particles, MaxSteps);
206  ParticleWorkletDispatchType particleWorkletDispatch;
207  vtkm::cont::ArrayHandleConstant<vtkm::Id> maxSteps(MaxSteps, numSeeds);
208  particleWorkletDispatch.Invoke(idxArray, it, streamlines, maxSteps);
209 
210  //Get the positions
211  streamlines.GetCompactedHistory(positions);
212 
213  //Create the cells
216  detail::ComputeNumPoints{}) };
217  computeNumPointsDispatcher.Invoke(particles, initialStepsTaken, numPoints);
218 
220  vtkm::Id connectivityLen = vtkm::cont::Algorithm::ScanExclusive(numPoints, cellIndex);
221  vtkm::cont::ArrayHandleIndex connCount(connectivityLen);
223  vtkm::cont::ArrayCopy(connCount, connectivity);
224 
226  auto polyLineShape =
227  vtkm::cont::make_ArrayHandleConstant<vtkm::UInt8>(vtkm::CELL_SHAPE_POLY_LINE, numSeeds);
228  vtkm::cont::ArrayCopy(polyLineShape, cellTypes);
229 
230  auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPoints);
231  polyLines.Fill(positions.GetNumberOfValues(), cellTypes, connectivity, offsets);
232  }
233 };
234 
235 }
236 }
237 } // namespace vtkm::worklet::flow
238 
239 #endif // vtk_m_filter_flow_worklet_ParticleAdvectionWorklets_h
vtkm::cont::ArrayHandle::GetNumberOfValues
VTKM_CONT vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:448
vtkm::worklet::flow::ParticleAdvectWorklet::InputDomain
_1 InputDomain
Definition: ParticleAdvectionWorklets.h:42
vtkm::cont::ArrayHandle< ParticleType >
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::worklet::flow::ParticleAdvectionWorklet
Definition: ParticleAdvectionWorklets.h:91
vtkm::worklet::flow::ParticleAdvectWorklet::ControlSignature
void(FieldIn idx, ExecObject integrator, ExecObject integralCurve, FieldIn maxSteps) ControlSignature
Definition: ParticleAdvectionWorklets.h:40
WorkletMapField.h
CellSetExplicit.h
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
ScopedCudaStackSize.h
vtkm::worklet::flow::Particles
Definition: Particles.h:112
vtkm::worklet::flow::ParticleAdvectionWorklet::~ParticleAdvectionWorklet
~ParticleAdvectionWorklet()
Definition: ParticleAdvectionWorklets.h:96
vtkm::worklet::flow::ParticleAdvectWorklet::operator()
VTKM_EXEC void operator()(const vtkm::Id &idx, const IntegratorType &integrator, IntegralCurveType &integralCurve, const vtkm::Id &maxSteps) const
Definition: ParticleAdvectionWorklets.h:45
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::flow::ParticleAdvectionWorklet::ParticleAdvectionWorklet
VTKM_EXEC_CONT ParticleAdvectionWorklet()
Definition: ParticleAdvectionWorklets.h:94
vtkm::worklet::flow::StreamlineWorklet::Run
void Run(const IntegratorType &it, vtkm::cont::ArrayHandle< ParticleType, PointStorage > &particles, vtkm::Id &MaxSteps, vtkm::cont::ArrayHandle< vtkm::Vec3f, PointStorage2 > &positions, vtkm::cont::CellSetExplicit<> &polyLines)
Definition: ParticleAdvectionWorklets.h:176
vtkm::worklet::flow::StreamlineWorklet
Definition: ParticleAdvectionWorklets.h:172
vtkm::worklet::DispatcherMapField
Dispatcher for worklets that inherit from WorkletMapField.
Definition: DispatcherMapField.h:25
Particles.h
Algorithm.h
vtkm::CELL_SHAPE_POLY_LINE
@ CELL_SHAPE_POLY_LINE
Definition: CellShape.h:40
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
vtkm::cont::Algorithm::ScanExclusive
static VTKM_CONT T ScanExclusive(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::cont::ArrayHandle< T, COut > &output)
Definition: Algorithm.h:816
vtkm::cont::ArrayCopy
void ArrayCopy(const SourceArrayType &source, DestArrayType &destination)
Does a deep copy from one array to another array.
Definition: ArrayCopy.h:142
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::CellSetExplicit::Fill
VTKM_CONT void Fill(vtkm::Id numPoints, const vtkm::cont::ArrayHandle< vtkm::UInt8, ShapesStorageTag > &cellTypes, const vtkm::cont::ArrayHandle< vtkm::Id, ConnectivityStorageTag > &connectivity, const vtkm::cont::ArrayHandle< vtkm::Id, OffsetsStorageTag > &offsets)
Second method to add cells – all at once.
vtkm::worklet::flow::ParticleAdvectWorklet::ExecutionSignature
void(_1 idx, _2 integrator, _3 integralCurve, _4 maxSteps) ExecutionSignature
Definition: ParticleAdvectionWorklets.h:41
vtkm::cont::ArrayHandleConstant
An array handle with a constant value.
Definition: ArrayHandleConstant.h:63
vtkm::Vec< vtkm::FloatDefault, 3 >
vtkm::cont::ConvertNumComponentsToOffsets
VTKM_CONT_EXPORT void ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle &numComponentsArray, vtkm::cont::ArrayHandle< vtkm::Id > &offsetsArray, vtkm::Id &componentsArraySize, vtkm::cont::DeviceAdapterId device=vtkm::cont::DeviceAdapterTagAny{})
vtkm::FloatDefault
vtkm::Float32 FloatDefault
The floating point type to use when no other precision is specified.
Definition: Types.h:198
ConvertNumComponentsToOffsets.h
vtkm::cont::CellSetExplicit
Definition: CastAndCall.h:36
vtkm::worklet::flow::StateRecordingParticles
Definition: Particles.h:207
vtkm::worklet::flow::ParticleAdvectWorklet
Definition: ParticleAdvectionWorklets.h:34
ExecutionObjectBase.h
vtkm::worklet::flow::ParticleAdvectionWorklet::Run
void Run(const IntegratorType &integrator, vtkm::cont::ArrayHandle< ParticleType > &particles, vtkm::Id &MaxSteps)
Definition: ParticleAdvectionWorklets.h:98
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38
Particle.h