1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkLagrangianParticleTracker.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10     This software is distributed WITHOUT ANY WARRANTY; without even
11     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12     PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkLagrangianParticleTracker
17  * @brief   Filter to inject and track particles in a flow
18  *
19  *
20  *
21  * Introduce LagrangianParticleTracker
22  *
23  * This is a very flexible and adaptive filter to inject and track particles in a
24  * flow. It takes three inputs :
25  * * port 0 : Flow Input, a volumic dataset containing data to integrate with,
26  *     any kind of data object, support distributed input.
27  * * port 1 : Seed (source) Input, a dataset containing point to generate particles
28  *     with, any kind of data object, support distributed input. Only first leaf
29  *     of composite dataset is used.
30  * * port 2 : Optional Surface Input, containing dataset to interact with, any
31  *     kind of data object, support distributed input.
32  *
33  * It has two outputs :
34  * * port 0 : ParticlePaths : a polyData of polyLines showing the paths of
35  *     particles in the flow
36  * * port 1 : ParticleInteractions : empty if no surface input, contains a
37  *     polydata of vertex
38  * with the same composite layout of surface input if any, showing all
39  *     interactions between particles and the surface input
40  *
41  * It has a parallel implementation which streams particle between domains.
42  *
43  * The most important parameters of this filter is it's integrationModel.
44  * Only one integration model implementation exist currently in ParaView
45  * ,vtkLagrangianMatidaIntegrationModel but the design enables plugin developers
46  * to expand this tracker by creating new models.
47  * A model can define  :
48  * * The number of integration variable and new user defined integration variable
49  * * the way the particle are integrated
50  * * the way particles intersect and interact with the surface
51  * * the way freeFlight termination is handled
52  * * PreProcess and PostProcess methods
53  * * Manual Integration, Manual partichle shifting
54  * see vtkLagrangianBasicIntegrationModel and vtkLagrangianMatidaIntegrationModel
55  * for more information
56  *
57  * It also let the user choose the Locator to use when integrating in the flow,
58  * as well as the Integrator to use. Integration steps are also highly configurable,
59  * step, step min and step max are passed down to the integrator (hence min and max
60  * does not matter with a non adaptive integrator like RK4/5)
61  *
62  *  An IntegrationModel is a very specific vtkFunctionSet with a lot of features
63  * allowing inherited classes
64  * to concentrate on the mathematical part of the code.
65  *  a Particle is basically a class wrapper around three table containing variables
66  * about the particle at previous, current and next position.
67  *  The particle is passed to the integrator, which use the integration model to
68  * integrate the particle in the flow.
69  *
70  * It has other features also, including :
71  *  * Adaptative Step Reintegration, to retry the step with different time step
72  *      when the next position is too far
73  *  * Different kind of cell length computation, including a divergence theorem
74  *      based computation
75  *  * Optional lines rendering controlled by a threshold
76  *  * Ghost cell support
77  *  * Non planar quad interaction support
78  *  * Built-in support for surface interaction including, terminate, bounce,
79  *      break-up and pass-through surface
80  * The serial and parallel filters are fully tested.
81  *
82  * @sa
83  * vtkLagrangianMatidaIntegrationModel vtkLagrangianParticle
84  * vtkLagrangianBasicIntegrationModel
85 */
86 
87 #ifndef vtkLagrangianParticleTracker_h
88 #define vtkLagrangianParticleTracker_h
89 
90 #include "vtkFiltersFlowPathsModule.h" // For export macro
91 #include "vtkDataObjectAlgorithm.h"
92 #include "vtkBoundingBox.h" // For cached bounds
93 
94 #include <queue> // for particle queue
95 
96 class vtkBoundingBox;
97 class vtkCellArray;
98 class vtkDataSet;
99 class vtkDoubleArray;
100 class vtkIdList;
101 class vtkInformation;
102 class vtkInitialValueProblemSolver;
103 class vtkLagrangianBasicIntegrationModel;
104 class vtkLagrangianParticle;
105 class vtkPointData;
106 class vtkPoints;
107 class vtkPolyData;
108 
109 class VTKFILTERSFLOWPATHS_EXPORT vtkLagrangianParticleTracker :
110   public vtkDataObjectAlgorithm
111 {
112 public:
113 
114   vtkTypeMacro(vtkLagrangianParticleTracker, vtkDataObjectAlgorithm);
115   void PrintSelf(ostream& os, vtkIndent indent) override;
116   static vtkLagrangianParticleTracker *New();
117 
118   typedef enum CellLengthComputation{
119     STEP_LAST_CELL_LENGTH = 0,
120     STEP_CUR_CELL_LENGTH = 1,
121     STEP_LAST_CELL_VEL_DIR = 2,
122     STEP_CUR_CELL_VEL_DIR = 3,
123     STEP_LAST_CELL_DIV_THEO = 4,
124     STEP_CUR_CELL_DIV_THEO = 5
125   } CellLengthComputation;
126 
127   //@{
128   /**
129    * Set/Get the integration model.
130    * Default is vtkLagrangianMatidaIntegrationModel
131    */
132   void SetIntegrationModel(vtkLagrangianBasicIntegrationModel* integrationModel);
133   vtkGetObjectMacro(IntegrationModel, vtkLagrangianBasicIntegrationModel);
134   //@}
135 
136   //@{
137   /**
138    * Set/Get the integrator.
139    * Default is vtkRungeKutta2
140    */
141   void SetIntegrator(vtkInitialValueProblemSolver* integrator);
142   vtkGetObjectMacro(Integrator, vtkInitialValueProblemSolver);
143   //@}
144 
145   //@{
146   /**
147    * Set/Get whether or not to use PolyVertex cell type
148    * for the interaction output
149    * Default is false
150    */
151   vtkSetMacro(GeneratePolyVertexInteractionOutput, bool);
152   vtkGetMacro(GeneratePolyVertexInteractionOutput, bool);
153   //@}
154 
155   //@{
156   /**
157    * Set/Get the cell length computation mode.
158    * Available modes are :
159    * - STEP_LAST_CELL_LENGTH :
160    * Compute cell length using getLength method
161    * on the last cell the particle was in
162    * - STEP_CUR_CELL_LENGTH :
163    * Compute cell length using getLength method
164    * on the current cell the particle is in
165    * - STEP_LAST_CELL_VEL_DIR :
166    * Compute cell length using the particle velocity
167    * and the edges of the last cell the particle was in.
168    * - STEP_CUR_CELL_VEL_DIR :
169    * Compute cell length using the particle velocity
170    * and the edges of the last cell the particle was in.
171    * - STEP_LAST_CELL_DIV_THEO :
172    * Compute cell length using the particle velocity
173    * and the divergence theorem, not supported
174    * with vtkVoxel, fallback to STEP_LAST_CELL_LENGTH
175    * - STEP_CUR_CELL_DIV_THEO :
176    * Compute cell length using the particle velocity
177    * and the divergence theorem, not supported
178    * with vtkVoxel, fallback to STEP_CUR_CELL_LENGTH
179    * Default is STEP_LAST_CELL_LENGTH.
180    */
181   vtkSetMacro(CellLengthComputationMode, int);
182   vtkGetMacro(CellLengthComputationMode, int);
183   //@}
184 
185   //@{
186   /**
187    * Set/Get the integration step factor. Default is 1.0.
188    */
189   vtkSetMacro(StepFactor, double);
190   vtkGetMacro(StepFactor, double);
191   //@}
192 
193   //@{
194   /**
195    * Set/Get the integration step factor min. Default is 0.5.
196    */
197   vtkSetMacro(StepFactorMin, double);
198   vtkGetMacro(StepFactorMin, double);
199   //@}
200 
201   //@{
202   /**
203    * Set/Get the integration step factor max. Default is 1.5.
204    */
205   vtkSetMacro(StepFactorMax, double);
206   vtkGetMacro(StepFactorMax, double);
207   //@}
208 
209   //@{
210   /**
211    * Set/Get the maximum number of steps. -1 means no limit. Default is 100.
212    */
213   vtkSetMacro(MaximumNumberOfSteps, int);
214   vtkGetMacro(MaximumNumberOfSteps, int);
215   //@}
216 
217   //@{
218   /**
219    * Set/Get the maximum integration time. A negative value means no limit.
220    * Default is -1.
221    */
222   vtkSetMacro(MaximumIntegrationTime, double);
223   vtkGetMacro(MaximumIntegrationTime, double);
224   //@}
225 
226   //@{
227   /**
228    * Set/Get the Adaptive Step Reintegration feature.
229    * it checks the step size after the integration
230    * and if it is too big will retry with a smaller step
231    * Default is false.
232    */
233   vtkSetMacro(AdaptiveStepReintegration, bool);
234   vtkGetMacro(AdaptiveStepReintegration, bool);
235   vtkBooleanMacro(AdaptiveStepReintegration, bool);
236   //@}
237 
238   //@{
239   /**
240    * Set/Get the Optional Paths Rendering feature,
241    * it allows to not show the particle paths
242    * if there is too many points.
243    * Default is false.
244    */
245   vtkSetMacro(UseParticlePathsRenderingThreshold, bool);
246   vtkGetMacro(UseParticlePathsRenderingThreshold, bool);
247   vtkBooleanMacro(UseParticlePathsRenderingThreshold, bool);
248   //@}
249 
250   //@{
251   /**
252    * Set/Get the Optional Paths Rendering threshold,
253    * ie the maximum number of points to show in the particle
254    * path if the option is activated.
255    * Default is 100
256    */
257   vtkSetMacro(ParticlePathsRenderingPointsThreshold, int);
258   vtkGetMacro(ParticlePathsRenderingPointsThreshold, int);
259   //@}
260 
261   //@{
262   /**
263    * Specify the source object used to generate particle initial position (seeds).
264    * Note that this method does not connect the pipeline. The algorithm will
265    * work on the input data as it is without updating the producer of the data.
266    * See SetSourceConnection for connecting the pipeline.
267    */
268   void SetSourceData(vtkDataObject* source);
269   vtkDataObject* GetSource();
270   //@}
271 
272   /**
273    * Specify the source object used to generate particle initial position (seeds).
274    */
275   void SetSourceConnection(vtkAlgorithmOutput* algOutput);
276 
277   //@{
278   /**
279    * Specify the source object used to compute surface interaction with
280    * Note that this method does not connect the pipeline. The algorithm will
281    * work on the input data as it is without updating the producer of the data.
282    * See SetSurfaceConnection for connecting the pipeline.
283    */
284   void SetSurfaceData(vtkDataObject *source);
285   vtkDataObject *GetSurface();
286   //@}
287 
288   /**
289    * Specify the object used to compute surface interaction with.
290    */
291   void SetSurfaceConnection(vtkAlgorithmOutput* algOutput);
292 
293   /**
294    * Declare input port type
295    */
296   int FillInputPortInformation(int port, vtkInformation* info) override;
297 
298   /**
299    * Declare output port type
300    */
301   int FillOutputPortInformation(int port, vtkInformation* info) override;
302 
303   /**
304    * Create outputs objects.
305    */
306   int RequestDataObject(vtkInformation*,
307     vtkInformationVector**,
308     vtkInformationVector*) override;
309 
310   /**
311    * Process inputs to integrate particle and generate output.
312    */
313   int RequestData(vtkInformation *request,
314     vtkInformationVector **inputVector,
315     vtkInformationVector *outputVector) override;
316 
317   /**
318    * Get the tracker modified time taking into account the integration model
319    * and the integrator.
320    */
321   vtkMTimeType GetMTime() override;
322 
323   /**
324    * Get an unique id for a particle
325    */
326   virtual vtkIdType GetNewParticleId();
327 
328 protected:
329   vtkLagrangianParticleTracker();
330   ~vtkLagrangianParticleTracker() override;
331 
332   virtual bool InitializeInputs(vtkInformationVector **inputVector,
333     vtkDataObject*& flow, vtkDataObject*& seeds, vtkDataObject*& surfaces,
334     std::queue<vtkLagrangianParticle*>& particleQueue, vtkPointData* seedData);
335   virtual bool InitializeFlow(vtkDataObject* flow, vtkBoundingBox* bounds);
336   virtual bool InitializeParticles(const vtkBoundingBox* bounds, vtkDataObject* seeds,
337     std::queue<vtkLagrangianParticle*>& particles, vtkPointData* seedData);
338   virtual void GenerateParticles(const vtkBoundingBox* bounds, vtkDataSet* seeds,
339     vtkDataArray* initialVelocities, vtkDataArray* initialIntegrationTimes,
340     vtkPointData* seedData, int nVar, std::queue<vtkLagrangianParticle*>& particles);
341   virtual bool UpdateSurfaceCacheIfNeeded(vtkDataObject*& surfaces);
342   virtual void InitializeSurface(vtkDataObject*& surfaces);
343   virtual bool InitializeOutputs(vtkInformationVector *outputVector, vtkPointData* seedData,
344     vtkIdType numberOfSeeds, vtkDataObject* surfaces,
345     vtkPolyData*& particlePathsOutput, vtkDataObject*& interactionOutput);
346 
347   virtual bool InitializePathsOutput(vtkInformationVector *outputVector,
348     vtkPointData* seedData, vtkIdType numberOfSeeds,
349     vtkPolyData*& particlePathsOutput);
350 
351   virtual bool InitializeInteractionOutput(vtkInformationVector *outputVector,
352     vtkPointData* seedData, vtkDataObject* surfaces, vtkDataObject*& interractionOutput);
353 
354   virtual void InitializeParticleData(vtkFieldData* particleData, int maxTuples = 0);
355   virtual void InitializePathData(vtkFieldData* data);
356   virtual void InitializeInteractionData(vtkFieldData* data);
357 
358   virtual bool FinalizeOutputs(vtkPolyData* particlePathsOutput,
359     vtkDataObject* interractionOutput);
360 
361   static void InsertPolyVertexCell(vtkPolyData* polydata);
362   static void InsertVertexCells(vtkPolyData* polydata);
363 
364   virtual void GetParticleFeed(std::queue<vtkLagrangianParticle*>& particleQueue);
365 
366   virtual int Integrate(vtkLagrangianParticle*, std::queue<vtkLagrangianParticle*>&,
367     vtkPolyData* particlePathsOutput, vtkIdList* particlePathPointId,
368     vtkDataObject* interactionOutput);
369 
370   void InsertPathOutputPoint(vtkLagrangianParticle* particle,
371     vtkPolyData* particlePathsOutput, vtkIdList* particlePathPointId,
372     bool prev = false);
373 
374   void InsertInteractionOutputPoint(vtkLagrangianParticle* particle,
375     unsigned int interactedSurfaceFlatIndex, vtkDataObject* interactionOutput);
376 
377   void InsertSeedData(vtkLagrangianParticle* particle, vtkFieldData* data);
378   void InsertPathData(vtkLagrangianParticle* particle, vtkFieldData* data);
379   void InsertInteractionData(vtkLagrangianParticle* particle, vtkFieldData* data);
380   void InsertParticleData(vtkLagrangianParticle* particle, vtkFieldData* data, int stepEnum);
381 
382   double ComputeCellLength(vtkLagrangianParticle* particle);
383 
384   bool ComputeNextStep(
385     double* xprev, double* xnext,
386     double t, double& delT, double& delTActual,
387     double minStep, double maxStep,
388     int& integrationRes);
389 
390   virtual bool CheckParticlePathsRenderingThreshold(vtkPolyData* particlePathsOutput);
391 
392   vtkLagrangianBasicIntegrationModel* IntegrationModel;
393   vtkInitialValueProblemSolver* Integrator;
394 
395   int CellLengthComputationMode;
396   double StepFactor;
397   double StepFactorMin;
398   double StepFactorMax;
399   int MaximumNumberOfSteps;
400   double MaximumIntegrationTime;
401   bool AdaptiveStepReintegration;
402   bool UseParticlePathsRenderingThreshold;
403   bool GeneratePolyVertexInteractionOutput;
404   int ParticlePathsRenderingPointsThreshold;
405   vtkIdType ParticleCounter;
406 
407   // internal parameters use for step computation
408   double MinimumVelocityMagnitude;
409   double MinimumReductionFactor;
410 
411   // Cache related parameters
412   vtkDataObject* FlowCache;
413   vtkMTimeType FlowTime;
414   vtkBoundingBox FlowBoundsCache;
415   vtkDataObject* SurfacesCache;
416   vtkMTimeType SurfacesTime;
417 
418 private:
419   vtkLagrangianParticleTracker(const vtkLagrangianParticleTracker&) = delete;
420   void operator=(const vtkLagrangianParticleTracker&) = delete;
421 };
422 
423 #endif
424