vtkLegacyParticleTracerBase.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
16 #ifndef vtkLegacyParticleTracerBase_h
17 #define vtkLegacyParticleTracerBase_h
18 
19 #include "vtkDeprecation.h" // For VTK_DEPRECATED_IN_9_2_0
20 #include "vtkPVVTKExtensionsFiltersGeneralMPIModule.h" // For export macro
21 #include "vtkPolyDataAlgorithm.h"
22 #include "vtkSmartPointer.h" // For vtkSmartPointer
23 
24 #include <list> // STL Header
25 #include <mutex> // STL Header
26 #include <vector> // STL Header
27 
29 class vtkCellArray;
31 class vtkDataArray;
32 class vtkDataSet;
33 class vtkDoubleArray;
34 class vtkFloatArray;
35 class vtkGenericCell;
37 class vtkIntArray;
40 class vtkPointData;
41 class vtkPoints;
42 class vtkPolyData;
43 class vtkSignedCharArray;
45 
47 {
48 struct Position_t
49 {
50  double x[4];
51 };
52 using Position = struct Position_t;
53 
55 {
56  // These are used during iteration
58  int CachedDataSetId[2];
59  vtkIdType CachedCellId[2];
61  // These are computed scalars we might display
62  int SourceID;
63  int TimeStepAge; // amount of time steps the particle has advanced
65  int InjectedStepId; // time step the particle was injected
68  // These are useful to track for debugging etc
69  int ErrorCode;
70  float age;
71  // these are needed across time steps to compute vorticity
72  float rotation;
73  float angularVel;
74  float time;
75  float speed;
76  // once the particle is added, PointId is valid and is the tuple location
77  // in ProtoPD.
79  // if PointId is negative then in parallel this particle was just
80  // received and we need to get the tuple value from vtkPParticleTracerBase::Tail.
82 };
84 
85 typedef std::vector<ParticleInformation> ParticleVector;
86 typedef ParticleVector::iterator ParticleIterator;
87 typedef std::list<ParticleInformation> ParticleDataList;
88 typedef ParticleDataList::iterator ParticleListIterator;
89 struct ParticleTracerFunctor;
90 }
91 
93  : public vtkPolyDataAlgorithm
94 {
95 public:
96  friend struct vtkLegacyParticleTracerBaseNamespace::ParticleTracerFunctor;
97  enum Solvers
98  {
103  UNKNOWN
104  };
105 
107  void PrintSelf(ostream& os, vtkIndent indent) override;
108  void PrintParticleHistories();
109 
111 
116  vtkGetMacro(ComputeVorticity, bool);
117  void SetComputeVorticity(bool);
119 
121 
124  vtkGetMacro(TerminalSpeed, double);
125  void SetTerminalSpeed(double);
127 
129 
133  vtkGetMacro(RotationScale, double);
134  void SetRotationScale(double);
136 
138 
142  vtkSetMacro(IgnorePipelineTime, vtkTypeBool);
143  vtkGetMacro(IgnorePipelineTime, vtkTypeBool);
144  vtkBooleanMacro(IgnorePipelineTime, vtkTypeBool);
146 
148 
157  vtkGetMacro(ForceReinjectionEveryNSteps, int);
158  void SetForceReinjectionEveryNSteps(int);
160 
162 
168  void SetTerminationTime(double t);
169  vtkGetMacro(TerminationTime, double);
171 
172  void SetIntegrator(vtkInitialValueProblemSolver*);
173  vtkGetObjectMacro(Integrator, vtkInitialValueProblemSolver);
174 
175  void SetIntegratorType(int type);
176  int GetIntegratorType();
177 
179 
183  vtkGetMacro(StartTime, double);
184  void SetStartTime(double t);
186 
188 
197  vtkSetMacro(StaticSeeds, vtkTypeBool);
198  vtkGetMacro(StaticSeeds, vtkTypeBool);
200 
205  {
206  DIFFERENT = 0,
207  STATIC = 1,
208  LINEAR_TRANSFORMATION = 2,
209  SAME_TOPOLOGY = 3
210  };
211 
213  /*
214  * Set/Get the type of variance of the mesh over time.
215  *
216  * DIFFERENT = 0,
217  * STATIC = 1,
218  * LINEAR_TRANSFORMATION = 2
219  * SAME_TOPOLOGY = 3
220  */
221  virtual void SetMeshOverTime(int meshOverTime);
222  virtual int GetMeshOverTimeMinValue() { return DIFFERENT; }
223  virtual int GetMeshOverTimeMaxValue() { return SAME_TOPOLOGY; }
224  void SetMeshOverTimeToDifferent() { this->SetMeshOverTime(DIFFERENT); }
225  void SetMeshOverTimeToStatic() { this->SetMeshOverTime(STATIC); }
226  void SetMeshOverTimeToLinearTransformation() { this->SetMeshOverTime(LINEAR_TRANSFORMATION); }
227  void SetMeshOverTimeToSameTopology() { this->SetMeshOverTime(SAME_TOPOLOGY); }
228  vtkGetMacro(MeshOverTime, int);
230 
232 
241  VTK_DEPRECATED_IN_9_2_0("Use SetMeshOverTime instead")
242  virtual void SetStaticMesh(vtkTypeBool staticMesh)
243  {
244  this->SetMeshOverTime(staticMesh ? STATIC : DIFFERENT);
245  }
246  VTK_DEPRECATED_IN_9_2_0("Use GetMeshOverTime instead")
247  virtual vtkTypeBool GetStaticMesh() { return this->MeshOverTime == STATIC; }
249 
250  enum
251  {
253  INTERPOLATOR_WITH_CELL_LOCATOR
254  };
255 
267  void SetInterpolatorType(int interpolatorType);
268 
276  void SetInterpolatorTypeToDataSetPointLocator();
277 
284  void SetInterpolatorTypeToCellLocator();
285 
287 
293  virtual void SetParticleWriter(vtkAbstractParticleWriter* pw);
294  vtkGetObjectMacro(ParticleWriter, vtkAbstractParticleWriter);
296 
298 
302  vtkSetFilePathMacro(ParticleFileName);
303  vtkGetFilePathMacro(ParticleFileName);
305 
307 
311  vtkSetMacro(EnableParticleWriting, vtkTypeBool);
312  vtkGetMacro(EnableParticleWriting, vtkTypeBool);
313  vtkBooleanMacro(EnableParticleWriting, vtkTypeBool);
315 
317 
322  vtkSetMacro(DisableResetCache, vtkTypeBool);
323  vtkGetMacro(DisableResetCache, vtkTypeBool);
324  vtkBooleanMacro(DisableResetCache, vtkTypeBool);
326 
328 
331  void AddSourceConnection(vtkAlgorithmOutput* input);
332  void RemoveAllSources();
334 
336 
340  vtkGetMacro(ForceSerialExecution, bool);
341  vtkSetMacro(ForceSerialExecution, bool);
342  vtkBooleanMacro(ForceSerialExecution, bool);
344 protected:
345  vtkSmartPointer<vtkPolyData> Output; // managed by child classes
347 
352  vtkIdType UniqueIdCounter; // global Id counter used to give particles a stamp
354  vtkSmartPointer<vtkPointData> ParticlePointData; // the current particle point data consistent
355  // with particle history
356  // Everything related to time
357  vtkTypeBool IgnorePipelineTime; // whether to use the pipeline time for termination
358  vtkTypeBool DisableResetCache; // whether to enable ResetCache() method
360 
361  // Control execution as serial or threaded
363 
365  ~vtkLegacyParticleTracerBase() override;
366 
367  //
368  // Make sure the pipeline knows what type we expect as input
369  //
370  int FillInputPortInformation(int port, vtkInformation* info) override;
371 
372  //
373  // The usual suspects
374  //
375  vtkTypeBool ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector,
376  vtkInformationVector* outputVector) override;
377 
378  //
379  // Store any information we need in the output and fetch what we can
380  // from the input
381  //
382  int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector,
383  vtkInformationVector* outputVector) override;
384 
385  //
386  // Compute input time steps given the output step
387  //
388  int RequestUpdateExtent(vtkInformation* request, vtkInformationVector** inputVector,
389  vtkInformationVector* outputVector) override;
390 
391  //
392  // what the pipeline calls for each time step
393  //
394  int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
395  vtkInformationVector* outputVector) override;
396 
397  //
398  // these routines are internally called to actually generate the output
399  //
400  virtual int ProcessInput(vtkInformationVector** inputVector);
401 
402  // This is the main part of the algorithm:
403  // * move all the particles one step
404  // * Reinject particles (by adding them to this->ParticleHistories)
405  // either at the beginning or at the end of each step (modulo
406  // this->ForceReinjectionEveryNSteps)
407  // * Output a polydata representing the moved particles
408  // Note that if the starting and the ending time coincide, the polydata is still valid.
409  virtual vtkPolyData* Execute(vtkInformationVector** inputVector);
410 
411  // the RequestData will call these methods in turn
412  virtual void Initialize() {} // the first iteration
413  virtual int OutputParticles(vtkPolyData* poly) = 0; // every iteration
414  virtual void Finalize() {} // the last iteration
415 
420  virtual std::vector<vtkDataSet*> GetSeedSources(vtkInformationVector* inputVector, int timeStep);
421 
422  // Initialization of input (vector-field) geometry
423  int InitializeInterpolator();
424  int UpdateDataCache(vtkDataObject* td);
425 
430  void TestParticles(vtkLegacyParticleTracerBaseNamespace::ParticleVector& candidates,
432 
433  void TestParticles(
434  vtkLegacyParticleTracerBaseNamespace::ParticleVector& candidates, std::vector<int>& passed);
435 
442  virtual void AssignSeedsToProcessors(double time, vtkDataSet* source, int sourceID, int ptId,
443  vtkLegacyParticleTracerBaseNamespace::ParticleVector& localSeedPoints, int& localAssignedCount);
444 
449  virtual void AssignUniqueIds(
451 
456  void UpdateParticleList(vtkLegacyParticleTracerBaseNamespace::ParticleVector& candidates);
457 
463  virtual bool UpdateParticleListFromOtherProcesses() { return false; }
464 
469  double currentTime, double targetTime, vtkInitialValueProblemSolver* integrator,
470  vtkTemporalInterpolatedVelocityField* interpolator, vtkDoubleArray* cellVectors,
471  std::atomic<vtkIdType>& particleCount, std::mutex& eraseMutex, bool sequential);
472 
473  // if the particle is added to send list, then returns value is 1,
474  // if it is kept on this process after a retry return value is 0
478  {
479  return true;
480  }
481 
488  bool ComputeDomainExitLocation(
489  double pos[4], double p2[4], double intersection[4], vtkGenericCell* cell);
490 
491  //
492  // Scalar arrays that are generated as each particle is updated
493  //
494  void CreateProtoPD(vtkDataObject* input);
495 
496  vtkFloatArray* GetParticleAge(vtkPointData*);
497  vtkIntArray* GetParticleIds(vtkPointData*);
498  vtkSignedCharArray* GetParticleSourceIds(vtkPointData*);
499  vtkIntArray* GetInjectedPointIds(vtkPointData*);
500  vtkIntArray* GetInjectedStepIds(vtkPointData*);
501  vtkIntArray* GetErrorCodeArr(vtkPointData*);
502  vtkFloatArray* GetParticleVorticity(vtkPointData*);
503  vtkFloatArray* GetParticleRotation(vtkPointData*);
504  vtkFloatArray* GetParticleAngularVel(vtkPointData*);
505 
506  // utility function we use to test if a point is inside any of our local datasets
507  bool InsideBounds(double point[]);
508 
509  void CalculateVorticity(
510  vtkGenericCell* cell, double pcoords[3], vtkDoubleArray* cellVectors, double vorticity[3]);
511 
512  //------------------------------------------------------
513 
514  double GetCacheDataTime(int i);
515  double GetCacheDataTime();
516 
517  virtual void ResetCache();
519  double* velocity, vtkTemporalInterpolatedVelocityField* interpolator, vtkIdType particleId,
520  vtkDoubleArray* cellVectors);
521 
523 
528  virtual bool IsPointDataValid(vtkDataObject* input);
529  bool IsPointDataValid(vtkCompositeDataSet* input, std::vector<std::string>& arrayNames);
530  void GetPointDataArrayNames(vtkDataSet* input, std::vector<std::string>& names);
532 
533  vtkGetMacro(ReinjectionCounter, int);
534  vtkGetMacro(CurrentTimeValue, double);
535 
536  void ResizeArrays(vtkIdType numTuples);
537 
542  virtual void InitializeExtraPointDataArrays(vtkPointData* vtkNotUsed(outputPD)) {}
543 
546  {
547  }
548 
549  vtkTemporalInterpolatedVelocityField* GetInterpolator();
550 
555  virtual void AddRestartSeeds(vtkInformationVector** /*inputVector*/) {}
556 
561  virtual void RenameGhostArray(vtkPointData* pd);
562 
563 private:
574  double* point1, double delT, int subSteps, vtkTemporalInterpolatedVelocityField* interpolator);
575 
576  bool SetTerminationTimeNoModify(double t);
577 
578  // Parameters of tracing
579  vtkInitialValueProblemSolver* Integrator;
580  double IntegrationStep;
581  double MaximumError;
582  bool ComputeVorticity;
583  double RotationScale;
584  double TerminalSpeed;
585 
586  // A counter to keep track of how many times we reinjected
587  int ReinjectionCounter;
588 
589  // Important for Caching of Cells/Ids/Weights etc
590  vtkTypeBool AllFixedGeometry;
591  int MeshOverTime;
592  vtkTypeBool StaticSeeds;
593 
594  std::vector<double> InputTimeValues;
595  double StartTime;
596  double TerminationTime;
597  double CurrentTimeValue;
598 
599  int StartTimeStep; // InputTimeValues[StartTimeStep] <= StartTime <=
600  // InputTimeValues[StartTimeStep+1]
601  int CurrentTimeStep;
602  int TerminationTimeStep; // computed from start time
603  bool FirstIteration;
604 
605  // Innjection parameters
606  int ForceReinjectionEveryNSteps;
607  vtkTimeStamp ParticleInjectionTime;
608  bool HasCache;
609 
610  // Particle writing to disk
611  vtkAbstractParticleWriter* ParticleWriter;
612  char* ParticleFileName;
613  vtkTypeBool EnableParticleWriting;
614 
615  // The main lists which are held during operation- between time step updates
617 
618  // The velocity interpolator
620 
621  // Data for time step CurrentTimeStep-1 and CurrentTimeStep
623 
624  // Cache bounds info for each dataset we will use repeatedly
625  struct bounds_t
626  {
627  double b[6];
628  };
629  using bounds = struct bounds_t;
630  std::vector<bounds> CachedBounds[2];
631 
632  // variables used by Execute() to produce output
633 
634  vtkSmartPointer<vtkDataSet> DataReferenceT[2];
635 
636  vtkSmartPointer<vtkPoints> OutputCoordinates;
637  vtkSmartPointer<vtkIdTypeArray> ParticleCellsConnectivity;
638  vtkSmartPointer<vtkIdTypeArray> ParticleCellsOffsets;
639  vtkSmartPointer<vtkCellArray> ParticleCells;
640 
641  vtkSmartPointer<vtkFloatArray> ParticleAge;
642  vtkSmartPointer<vtkIntArray> ParticleIds;
643  vtkSmartPointer<vtkSignedCharArray> ParticleSourceIds;
644  vtkSmartPointer<vtkIntArray> InjectedPointIds;
645  vtkSmartPointer<vtkIntArray> InjectedStepIds;
646  vtkSmartPointer<vtkIntArray> ErrorCodeArray;
647  vtkSmartPointer<vtkFloatArray> ParticleVorticity;
648  vtkSmartPointer<vtkFloatArray> ParticleRotation;
649  vtkSmartPointer<vtkFloatArray> ParticleAngularVel;
650  vtkSmartPointer<vtkPointData> OutputPointData;
651 
652  // temp array
654 
656  void operator=(const vtkLegacyParticleTracerBase&) = delete;
657  vtkTimeStamp ExecuteTime;
658 
659  unsigned int NumberOfParticles();
660 
662 
663  static const double Epsilon;
664 };
665 
666 #endif
A particle tracer for vector fields.
std::list< ParticleInformation > ParticleDataList
virtual void AddRestartSeeds(vtkInformationVector **)
For restarts of particle paths, we add in the ability to add in particles from a previous computation...
vtkTypeBool IgnorePipelineTime
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...
MeshOverTimeTypes
Types of Variance of Mesh over time.
info
int vtkIdType
vtkLegacyParticleTracerBaseNamespace::ParticleDataList ParticleHistories
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...
vtkSmartPointer< vtkPolyData > Output
vtkIdType UniqueIdCounter
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...
vtkSmartPointer< vtkPointData > ProtoPD
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...
int vtkTypeBool
vtkTypeBool DisableResetCache
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...
time
source
A Parallel Particle tracer for unsteady vector fields.
std::vector< ParticleInformation > ParticleVector
virtual bool SendParticleToAnotherProcess(vtkLegacyParticleTracerBaseNamespace::ParticleInformation &, vtkLegacyParticleTracerBaseNamespace::ParticleInformation &, vtkPointData *)
virtual bool UpdateParticleListFromOtherProcesses()
this is used during classification of seed points and also between iterations of the main loop as par...
virtual void SetToExtraPointDataArrays(vtkIdType, vtkLegacyParticleTracerBaseNamespace::ParticleInformation &)
point
virtual void InitializeExtraPointDataArrays(vtkPointData *vtkNotUsed(outputPD))
Methods to append values to existing point data arrays that may only be desired on specific concrete ...
#define VTKPVVTKEXTENSIONSFILTERSGENERALMPI_EXPORT
vtkSmartPointer< vtkPointData > ParticlePointData
ProtoPD is used just to keep track of the input array names and number of components for copy allocat...