/*========================================================================= Program: Visualization Toolkit Module: vtkTemporalInterpolatedVelocityField.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 vtkTemporalInterpolatedVelocityField * @brief A helper class for interpolating between times during particle tracing * * vtkTemporalInterpolatedVelocityField is a general purpose * helper for the temporal particle tracing code (vtkParticleTracerBase) * * It maintains two copies of vtkCompositeInterpolatedVelocityField internally * and uses them to obtain velocity values at time T0 and T1. * * In fact the class does quite a bit more than this because when the geometry * of the datasets is the same at T0 and T1, we can re-use cached cell Ids and * weights used in the cell interpolation routines. * Additionally, the same weights can be used when interpolating (point) scalar * values and computing vorticity etc. * * @warning * vtkTemporalInterpolatedVelocityField is not thread safe. * A new instance should be created by each thread. * * @warning * Datasets are added in lists. The list for T1 must be identical to that for T0 * in structure/topology and dataset order, and any datasets marked as static, * must remain so for all T - changing a dataset from static to dynamic * between time steps will result in undefined behaviour (=crash probably) * * * @sa * vtkCompositeInterpolatedVelocityField vtkParticleTracerBase * vtkParticleTracer vtkParticlePathFilter vtkStreaklineFilter */ #ifndef vtkTemporalInterpolatedVelocityField_h #define vtkTemporalInterpolatedVelocityField_h #include "vtkDeprecation.h" // For VTK_DEPRECATED_IN_9_2_0 #include "vtkFiltersFlowPathsModule.h" // For export macro #include "vtkFunctionSet.h" #include "vtkSmartPointer.h" // For vtkSmartPointer #include // For internal structures class vtkAbstractCellLinks; class vtkCompositeDataSet; class vtkCompositeInterpolatedVelocityField; class vtkDataArray; class vtkDataSet; class vtkDoubleArray; class vtkFindCellStrategy; class vtkGenericCell; class vtkLocator; class vtkPointData; class VTKFILTERSFLOWPATHS_EXPORT vtkTemporalInterpolatedVelocityField : public vtkFunctionSet { public: vtkTypeMacro(vtkTemporalInterpolatedVelocityField, vtkFunctionSet); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Construct a vtkTemporalInterpolatedVelocityField with no initial data set. * Caching is on. LastCellId is set to -1. */ static vtkTemporalInterpolatedVelocityField* New(); /** * States that define where the cell id are */ enum IDStates { INSIDE_ALL = 0, OUTSIDE_ALL = 1, OUTSIDE_T0 = 2, OUTSIDE_T1 = 3 }; /** * Types of Variance of Mesh over time */ enum MeshOverTimeTypes { DIFFERENT = 0, STATIC = 1, LINEAR_TRANSFORMATION = 2, SAME_TOPOLOGY = 3 }; ///@{ /* * Set/Get the type of variance of the mesh over time. * * DIFFERENT = 0, * STATIC = 1, * LINEAR_TRANSFORMATION = 2 * SAME_TOPOLOGY = 3 */ vtkSetClampMacro(MeshOverTime, int, DIFFERENT, SAME_TOPOLOGY); void SetMeshOverTimeToDifferent() { this->SetMeshOverTime(DIFFERENT); } void SetMeshOverTimeToStatic() { this->SetMeshOverTime(STATIC); } void SetMeshOverTimeToLinearTransformation() { this->SetMeshOverTime(LINEAR_TRANSFORMATION); } void SetMeshOverTimeToSameTopology() { this->SetMeshOverTime(SAME_TOPOLOGY); } vtkGetMacro(MeshOverTime, int); ///@} /** * The Initialize() method is used to build and cache supporting structures * (such as locators) which are used when operating on the interpolated * velocity field. This method is needed mainly to deal with thread safety * issues; i.e., these supporting structures must be built at the right * time to avoid race conditions. */ void Initialize(vtkCompositeDataSet* t0, vtkCompositeDataSet* t1); /** * Copy essential parameters between instances of this class. This * generally is used to copy from instance prototype to another, or to copy * interpolators between thread instances. Sub-classes can contribute to * the parameter copying process via chaining. */ virtual void CopyParameters(vtkTemporalInterpolatedVelocityField* from); using Superclass::FunctionValues; ///@{ /** * Evaluate the velocity field, f, at (x, y, z, t). * For now, t is ignored. */ int FunctionValues(double* x, double* u) override; int FunctionValuesAtT(int T, double* x, double* u); ///@} /** * If you want to work with an arbitrary vector array, then set its name * here. By default this is nullptr and the filter will use the active vector * array. */ void SelectVectors(const char* fieldName) { this->SetVectorsSelection(fieldName); } ///@{ /** * In order to use this class, two sets of data must be supplied, * corresponding to times T1 and T2. Data is added via * this function. */ void AddDataSetAtTime(int N, double T, vtkDataSet* dataset); VTK_DEPRECATED_IN_9_2_0("Use AddDataSetAtTime and SetMeshOverTime instead") void SetDataSetAtTime(int, int, double, vtkDataSet*, bool) {} ///@} ///@{ /** * Between iterations of the Particle Tracer, Id's of the Cell * are stored and then at the start of the next particle the * Ids are set to 'pre-fill' the cache. */ bool GetCachedCellIds(vtkIdType id[2], int ds[2]); void SetCachedCellIds(vtkIdType id[2], int ds[2]); ///@} /** * Set the last cell id to -1 so that the next search does not * start from the previous cell */ void ClearCache(); ///@{ /** * A utility function which evaluates the point at T1, T2 to see * if it is inside the data at both times or only one. */ int TestPoint(double* x); int QuickTestPoint(double* x); ///@} ///@{ /** * If an interpolation was successful, we can retrieve the last computed * value from here. Initial value is (0.0,0.0,0.0) */ vtkGetVector3Macro(LastGoodVelocity, double); ///@} ///@{ /** * Get the most recent weight between 0->1 from T1->T2. Initial value is 0. */ vtkGetMacro(CurrentWeight, double); ///@} bool InterpolatePoint(vtkPointData* outPD1, vtkPointData* outPD2, vtkIdType outIndex); bool InterpolatePoint(int T, vtkPointData* outPD1, vtkIdType outIndex); bool GetVorticityData( int T, double pcoords[3], double* weights, vtkGenericCell*& cell, vtkDoubleArray* cellVectors); void ShowCacheResults(); VTK_DEPRECATED_IN_9_2_0("Use GetMeshOverTime() instead.") bool IsStatic(int) { return this->MeshOverTime == STATIC; } void AdvanceOneTimeStep(); ///@{ /** * Set / get the strategy used to perform the FindCell() operation. This * strategy is used when operating on vtkPointSet subclasses. Note if the * input is a composite dataset then the strategy will be used to clone * one strategy per leaf dataset. */ virtual void SetFindCellStrategy(vtkFindCellStrategy*); vtkGetObjectMacro(FindCellStrategy, vtkFindCellStrategy); ///@} protected: vtkTemporalInterpolatedVelocityField(); ~vtkTemporalInterpolatedVelocityField() override; virtual void SetVectorsSelection(const char* v); int MeshOverTime = MeshOverTimeTypes::DIFFERENT; void InitializeWithLocators(vtkCompositeInterpolatedVelocityField* ivf, const std::vector& datasets, vtkFindCellStrategy* strategy, const std::vector>& locators, const std::vector>& links); void CreateLocators(const std::vector& datasets, vtkFindCellStrategy* strategy, std::vector>& locators); void CreateLinks(const std::vector& datasets, std::vector>& links); void CreateLinearTransformCellLocators(const std::vector>& locators, std::vector>& linearCellLocators); double Vals1[3]; double Vals2[3]; double Times[2]; double LastGoodVelocity[3]; static const double WEIGHT_TO_TOLERANCE; // The weight (0.0->1.0) of the value of T between the two available // time values for the current computation double CurrentWeight; // One minus the CurrentWeight double OneMinusWeight; // A scaling factor used when calculating the CurrentWeight { 1.0/(T2-T1) } double ScaleCoeff; vtkSmartPointer IVF[2]; std::vector> Locators[2]; std::vector> InitialCellLocators; std::vector> Links[2]; std::vector MaxCellSizes[2]; vtkFindCellStrategy* FindCellStrategy; private: // Hide this since we need multiple time steps and are using a different // function prototype virtual void AddDataSet(vtkDataSet*) {} private: vtkTemporalInterpolatedVelocityField(const vtkTemporalInterpolatedVelocityField&) = delete; void operator=(const vtkTemporalInterpolatedVelocityField&) = delete; }; #endif