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