You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
15 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkTemporalStreamTracer.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkTemporalStreamTracer
* @brief A Parallel Particle tracer for unsteady vector fields
*
* vtkTemporalStreamTracer is a filter that integrates a vector field to generate
*
*
* @sa
* vtkRibbonFilter vtkRuledSurfaceFilter vtkInitialValueProblemSolver
* vtkRungeKutta2 vtkRungeKutta4 vtkRungeKutta45 vtkStreamTracer
*
* This class is deprecated.
* Use instead one of the following classes: vtkParticleTracerBase
* vtkParticleTracer vtkParticlePathFilter vtkStreaklineFilter
* See https://blog.kitware.com/improvements-in-path-tracing-in-vtk/
*/
#ifndef vtkTemporalStreamTracer_h
#define vtkTemporalStreamTracer_h
#include "vtkConfigure.h" // For legacy defines
#include "vtkSetGet.h" // For legacy macros
#ifndef VTK_LEGACY_REMOVE
#include "vtkFiltersFlowPathsModule.h" // For export macro
#include "vtkSmartPointer.h" // For protected ivars.
#include "vtkStreamTracer.h"
#include <list> // STL Header
#include <vector> // STL Header
class vtkMultiProcessController;
class vtkMultiBlockDataSet;
class vtkDataArray;
class vtkDoubleArray;
class vtkGenericCell;
class vtkIntArray;
class vtkTemporalInterpolatedVelocityField;
class vtkPoints;
class vtkCellArray;
class vtkDoubleArray;
class vtkFloatArray;
class vtkIntArray;
class vtkCharArray;
class vtkAbstractParticleWriter;
namespace vtkTemporalStreamTracerNamespace
{
typedef struct
{
double x[4];
} Position;
typedef struct
{
// These are used during iteration
Position CurrentPosition;
int CachedDataSetId[2];
vtkIdType CachedCellId[2];
int LocationState;
// These are computed scalars we might display
int SourceID;
int TimeStepAge;
int InjectedPointId;
int InjectedStepId;
int UniqueParticleId;
// These are useful to track for debugging etc
int ErrorCode;
float age;
// these are needed across time steps to compute vorticity
float rotation;
float angularVel;
float time;
float speed;
} ParticleInformation;
typedef std::vector<ParticleInformation> ParticleVector;
typedef ParticleVector::iterator ParticleIterator;
typedef std::list<ParticleInformation> ParticleDataList;
typedef ParticleDataList::iterator ParticleListIterator;
};
class VTKFILTERSFLOWPATHS_EXPORT vtkTemporalStreamTracer : public vtkStreamTracer
{
public:
vtkTypeMacro(vtkTemporalStreamTracer, vtkStreamTracer);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Construct object using 2nd order Runge Kutta
*/
static vtkTemporalStreamTracer* New();
//@{
/**
* Set/Get the TimeStep. This is the primary means of advancing
* the particles. The TimeStep should be animated and this will drive
* the pipeline forcing timesteps to be fetched from upstream.
*/
vtkSetMacro(TimeStep, unsigned int);
vtkGetMacro(TimeStep, unsigned int);
//@}
//@{
/**
* To get around problems with the Paraview Animation controls
* we can just animate the time step and ignore the TIME_ requests
*/
vtkSetMacro(IgnorePipelineTime, vtkTypeBool);
vtkGetMacro(IgnorePipelineTime, vtkTypeBool);
vtkBooleanMacro(IgnorePipelineTime, vtkTypeBool);
//@}
//@{
/**
* If the data source does not have the correct time values
* present on each time step - setting this value to non unity can
* be used to adjust the time step size from 1s pre step to
* 1x_TimeStepResolution : Not functional in this version.
* Broke it @todo, put back time scaling
*/
vtkSetMacro(TimeStepResolution, double);
vtkGetMacro(TimeStepResolution, double);
//@}
//@{
/**
* When animating particles, it is nice to inject new ones every Nth step
* to produce a continuous flow. Setting ForceReinjectionEveryNSteps to a
* non zero value will cause the particle source to reinject particles
* every Nth step even if it is otherwise unchanged.
* Note that if the particle source is also animated, this flag will be
* redundant as the particles will be reinjected whenever the source changes
* anyway
*/
vtkSetMacro(ForceReinjectionEveryNSteps, int);
vtkGetMacro(ForceReinjectionEveryNSteps, int);
//@}
enum Units
{
TERMINATION_TIME_UNIT,
TERMINATION_STEP_UNIT
};
//@{
/**
* Setting TerminationTime to a positive value will cause particles
* to terminate when the time is reached. Use a vlue of zero to
* disable termination. The units of time should be consistent with the
* primary time variable.
*/
vtkSetMacro(TerminationTime, double);
vtkGetMacro(TerminationTime, double);
//@}
//@{
/**
* The units of TerminationTime may be actual 'Time' units as described
* by the data, or just TimeSteps of iteration.
*/
vtkSetMacro(TerminationTimeUnit, int);
vtkGetMacro(TerminationTimeUnit, int);
void SetTerminationTimeUnitToTimeUnit() { this->SetTerminationTimeUnit(TERMINATION_TIME_UNIT); }
void SetTerminationTimeUnitToStepUnit() { this->SetTerminationTimeUnit(TERMINATION_STEP_UNIT); }
//@}
//@{
/**
* if StaticSeeds is set and the mesh is static,
* then every time particles are injected we can re-use the same
* injection information. We classify particles according to
* processor just once before start.
* If StaticSeeds is set and a moving seed source is specified
* the motion will be ignored and results will not be as expected.
*/
vtkSetMacro(StaticSeeds, vtkTypeBool);
vtkGetMacro(StaticSeeds, vtkTypeBool);
vtkBooleanMacro(StaticSeeds, vtkTypeBool);
//@}
//@{
/**
* if StaticMesh is set, many optimizations for cell caching
* can be assumed. if StaticMesh is not set, the algorithm
* will attempt to find out if optimizations can be used, but
* setting it to true will force all optimizations.
* Do not Set StaticMesh to true if a dynamic mesh is being used
* as this will invalidate all results.
*/
vtkSetMacro(StaticMesh, vtkTypeBool);
vtkGetMacro(StaticMesh, vtkTypeBool);
vtkBooleanMacro(StaticMesh, vtkTypeBool);
//@}
//@{
/**
* Set/Get the Writer associated with this Particle Tracer
* Ideally a parallel IO capable vtkH5PartWriter should be used
* which will collect particles from all parallel processes
* and write them to a single HDF5 file.
*/
virtual void SetParticleWriter(vtkAbstractParticleWriter* pw);
vtkGetObjectMacro(ParticleWriter, vtkAbstractParticleWriter);
//@}
//@{
/**
* Set/Get the filename to be used with the particle writer when
* dumping particles to disk
*/
vtkSetStringMacro(ParticleFileName);
vtkGetStringMacro(ParticleFileName);
//@}
//@{
/**
* Set/Get the filename to be used with the particle writer when
* dumping particles to disk
*/
vtkSetMacro(EnableParticleWriting, vtkTypeBool);
vtkGetMacro(EnableParticleWriting, vtkTypeBool);
vtkBooleanMacro(EnableParticleWriting, vtkTypeBool);
//@}
//@{
/**
* Provide support for multiple see sources
*/
void AddSourceConnection(vtkAlgorithmOutput* input);
void RemoveAllSources();
//@}
protected:
VTK_LEGACY(vtkTemporalStreamTracer());
~vtkTemporalStreamTracer() override;
//
// Make sure the pipeline knows what type we expect as input
//
int FillInputPortInformation(int port, vtkInformation* info) override;
//
// The usual suspects
//
vtkTypeBool ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
//
// Store any information we need in the output and fetch what we can
// from the input
//
int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
//
// Compute input time steps given the output step
//
int RequestUpdateExtent(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
//
// what the pipeline calls for each time step
//
int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
//
// these routines are internally called to actually generate the output
//
virtual int ProcessInput(vtkInformationVector** inputVector);
virtual int GenerateOutput(
vtkInformationVector** inputVector, vtkInformationVector* outputVector);
//
// Initialization of input (vector-field) geometry
//
int InitializeInterpolator();
int SetTemporalInput(vtkDataObject* td, int index);
//
/**
* inside our data. Add good ones to passed list and set count to the
* number that passed
*/
void TestParticles(vtkTemporalStreamTracerNamespace::ParticleVector& candidates,
vtkTemporalStreamTracerNamespace::ParticleVector& passed, int& count);
/**
* all the injection/seed points according to which processor
* they belong to. This saves us retesting at every injection time
* providing 1) The volumes are static, 2) the seed points are static
* If either are non static, then this step is skipped.
*/
virtual void AssignSeedsToProcessors(vtkDataSet* source, int sourceID, int ptId,
vtkTemporalStreamTracerNamespace::ParticleVector& LocalSeedPoints, int& LocalAssignedCount);
/**
* give each one a unique ID. We need to use MPI to find out
* who is using which numbers.
*/
virtual void AssignUniqueIds(vtkTemporalStreamTracerNamespace::ParticleVector& LocalSeedPoints);
/**
* and sending between processors, into a list, which is used as the master
* list on this processor
*/
void UpdateParticleList(vtkTemporalStreamTracerNamespace::ParticleVector& candidates);
/**
* this is used during classification of seed points and also between iterations
* of the main loop as particles leave each processor domain
*/
virtual void TransmitReceiveParticles(
vtkTemporalStreamTracerNamespace::ParticleVector& outofdomain,
vtkTemporalStreamTracerNamespace::ParticleVector& received, bool removeself);
/**
* particle between the two times supplied.
*/
void IntegrateParticle(vtkTemporalStreamTracerNamespace::ParticleListIterator& it,
double currenttime, double terminationtime, vtkInitialValueProblemSolver* integrator);
/**
* and sent to the other processors for possible continuation.
* These routines manage the collection and sending after each main iteration.
* RetryWithPush adds a small pusj to aparticle along it's current velocity
* vector, this helps get over cracks in dynamic/rotating meshes
*/
bool RetryWithPush(
vtkTemporalStreamTracerNamespace::ParticleInformation& info, double velocity[3], double delT);
// if the particle is added to send list, then returns value is 1,
// if it is kept on this process after a retry return value is 0
bool SendParticleToAnotherProcess(
vtkTemporalStreamTracerNamespace::ParticleInformation& info, double point1[4], double delT);
void AddParticleToMPISendList(vtkTemporalStreamTracerNamespace::ParticleInformation& info);
/**
* In dnamic meshes, particles might leave the domain and need to be extrapolated across
* a gap between the meshes before they re-renter another domain
* dodgy rotating meshes need special care....
*/
bool ComputeDomainExitLocation(
double pos[4], double p2[4], double intersection[4], vtkGenericCell* cell);
//
//
// Track internally which round of RequestData it is--between 0 and 2
int RequestIndex;
// Track which process we are
int UpdatePieceId;
int UpdateNumPieces;
// Important for Caching of Cells/Ids/Weights etc
int AllFixedGeometry;
vtkTypeBool StaticMesh;
vtkTypeBool StaticSeeds;
// Support 'pipeline' time or manual SetTimeStep
unsigned int TimeStep;
unsigned int ActualTimeStep;
vtkTypeBool IgnorePipelineTime;
unsigned int NumberOfInputTimeSteps;
std::vector<double> InputTimeValues;
std::vector<double> OutputTimeValues;
// more time management
double EarliestTime;
double CurrentTimeSteps[2];
double TimeStepResolution;
// Particle termination after time
double TerminationTime;
int TerminationTimeUnit;
// Particle injection+Reinjection
int ForceReinjectionEveryNSteps;
bool ReinjectionFlag;
int ReinjectionCounter;
vtkTimeStamp ParticleInjectionTime;
// Particle writing to disk
vtkAbstractParticleWriter* ParticleWriter;
char* ParticleFileName;
vtkTypeBool EnableParticleWriting;
// The main lists which are held during operation- between time step updates
unsigned int NumberOfParticles;
vtkTemporalStreamTracerNamespace::ParticleDataList ParticleHistories;
vtkTemporalStreamTracerNamespace::ParticleVector LocalSeeds;
//
// Scalar arrays that are generated as each particle is updated
//
vtkSmartPointer<vtkFloatArray> ParticleAge;
vtkSmartPointer<vtkIntArray> ParticleIds;
vtkSmartPointer<vtkCharArray> ParticleSourceIds;
vtkSmartPointer<vtkIntArray> InjectedPointIds;
vtkSmartPointer<vtkIntArray> InjectedStepIds;
vtkSmartPointer<vtkIntArray> ErrorCodeArray;
vtkSmartPointer<vtkFloatArray> ParticleVorticity;
vtkSmartPointer<vtkFloatArray> ParticleRotation;
vtkSmartPointer<vtkFloatArray> ParticleAngularVel;
vtkSmartPointer<vtkDoubleArray> cellVectors;
vtkSmartPointer<vtkPointData> OutputPointData;
int InterpolationCount;
// The output geometry
vtkSmartPointer<vtkCellArray> ParticleCells;
vtkSmartPointer<vtkPoints> OutputCoordinates;
// List used for transmitting between processors during parallel operation
vtkTemporalStreamTracerNamespace::ParticleVector MPISendList;
// The velocity interpolator
vtkSmartPointer<vtkTemporalInterpolatedVelocityField> Interpolator;
// The input datasets which are stored by time step 0 and 1
vtkSmartPointer<vtkMultiBlockDataSet> InputDataT[2];
vtkSmartPointer<vtkDataSet> DataReferenceT[2];
// Cache bounds info for each dataset we will use repeatedly
typedef struct
{
double b[6];
} bounds;
std::vector<bounds> CachedBounds[2];
// utility function we use to test if a point is inside any of our local datasets
bool InsideBounds(double point[]);
// global Id counter used to give particles a stamp
vtkIdType UniqueIdCounter;
vtkIdType UniqueIdCounterMPI;
// for debugging only;
int substeps;
private:
/**
* Hide this because we require a new interpolator type
*/
void SetInterpolatorPrototype(vtkAbstractInterpolatedVelocityField*) {}
private:
vtkTemporalStreamTracer(const vtkTemporalStreamTracer&) = delete;
void operator=(const vtkTemporalStreamTracer&) = delete;
};
#endif // VTK_LEGACY_REMOVE
#endif