TTK
Loading...
Searching...
No Matches
ttkDiscreteVectorField.cpp
Go to the documentation of this file.
2#include <ttkMacros.h>
3#include <ttkUtils.h>
4
5#include <vtkCellData.h>
6#include <vtkIdTypeArray.h>
7#include <vtkInformation.h>
8#include <vtkIntArray.h>
9#include <vtkLine.h>
10#include <vtkPointData.h>
11#include <vtkPolyData.h>
12#include <vtkSignedCharArray.h>
13#include <vtkSmartPointer.h>
14
16
18 SetNumberOfInputPorts(1);
19 SetNumberOfOutputPorts(2);
20}
21
23 vtkInformation *info) {
24 if(port == 0) {
25 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
26 return 1;
27 }
28 return 0;
29}
30
32 vtkInformation *info) {
33 if(port == 0 || port == 1) {
34 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData");
35 return 1;
36 }
37 return 0;
38}
39
40template <typename scalarType, typename triangulationType>
41int ttkDiscreteVectorField::fillCriticalPoints(
42 vtkPolyData *outputCriticalPoints, const triangulationType &triangulation) {
43
44 ttk::Timer tm{};
45
46 // critical points
47 std::vector<std::array<float, 3>> critPoints_coords;
48 std::vector<char> critPoints_cellDimensions;
49 std::vector<SimplexId> critPoints_cellIds;
50 std::vector<char> critPoints_isOnBoundary;
51 std::vector<SimplexId> critPoints_PLVertexIdentifiers;
52
54 critPoints_coords, critPoints_cellDimensions, critPoints_cellIds,
55 critPoints_isOnBoundary, critPoints_PLVertexIdentifiers, triangulation);
56 const auto nPoints = critPoints_coords.size();
57
58 vtkNew<vtkPoints> points{};
59 points->SetNumberOfPoints(nPoints);
60
61 vtkNew<vtkSignedCharArray> cellDimensions{};
62 cellDimensions->SetNumberOfComponents(1);
63 cellDimensions->SetName("CellDimension");
64 cellDimensions->SetNumberOfTuples(nPoints);
65
66 vtkNew<ttkSimplexIdTypeArray> cellIds{};
67 cellIds->SetNumberOfComponents(1);
68 cellIds->SetName("CellId");
69 cellIds->SetNumberOfTuples(nPoints);
70
71 vtkNew<vtkSignedCharArray> isOnBoundary{};
72 isOnBoundary->SetNumberOfComponents(1);
73 isOnBoundary->SetName("IsOnBoundary");
74 isOnBoundary->SetNumberOfTuples(nPoints);
75
76 vtkNew<ttkSimplexIdTypeArray> PLVertexIdentifiers{};
77 PLVertexIdentifiers->SetNumberOfComponents(1);
78 PLVertexIdentifiers->SetName(ttk::VertexScalarFieldName);
79 PLVertexIdentifiers->SetNumberOfTuples(nPoints);
80
81#ifdef TTK_ENABLE_OPENMP
82#pragma omp parallel for num_threads(this->threadNumber_)
83#endif // TTK_ENABLE_OPENMP
84 for(size_t i = 0; i < nPoints; ++i) {
85 points->SetPoint(i, critPoints_coords[i].data());
86 cellDimensions->SetTuple1(i, critPoints_cellDimensions[i]);
87 cellIds->SetTuple1(i, critPoints_cellIds[i]);
88 isOnBoundary->SetTuple1(i, critPoints_isOnBoundary[i]);
89#ifdef TTK_ENABLE_MPI
90 if(ttk::hasInitializedMPI()) {
91 PLVertexIdentifiers->SetTuple1(
92 i, triangulation.getVertexGlobalId(critPoints_PLVertexIdentifiers[i]));
93 } else {
94 PLVertexIdentifiers->SetTuple1(i, critPoints_PLVertexIdentifiers[i]);
95 }
96#else
97 PLVertexIdentifiers->SetTuple1(i, critPoints_PLVertexIdentifiers[i]);
98#endif
99 }
100
101 ttkUtils::CellVertexFromPoints(outputCriticalPoints, points);
102
103 vtkPointData *pointData = outputCriticalPoints->GetPointData();
104#ifndef TTK_ENABLE_KAMIKAZE
105 if(!pointData) {
106 this->printErr("outputCriticalPoints has no point data");
107 return -1;
108 }
109#endif
110
111 pointData->SetScalars(cellDimensions);
112 pointData->AddArray(cellIds);
113 // pointData->AddArray(cellScalars);
114 pointData->AddArray(isOnBoundary);
115 pointData->AddArray(PLVertexIdentifiers);
116
117 this->printMsg(
118 "Extracted critical points", 1.0, tm.getElapsedTime(), this->threadNumber_);
119
120 return 0;
121}
122
123template <typename triangulationType>
124int ttkDiscreteVectorField::fillVectorGlyphs(
125 vtkPolyData *const outputVectorGlyphs,
126 const triangulationType &triangulation) {
127
128 ttk::Timer tm{};
129
130 std::vector<std::array<float, 3>> vectorGlyphs_points;
131 std::vector<char> vectorGlyphs_points_pairOrigins;
132 std::vector<char> vectorGlyphs_cells_pairTypes;
133 std::vector<SimplexId> vectorGlyphs_point_ids{};
134 std::vector<char> vectorGlyphs_point_dimensions{};
135
136 this->setVectorGlyphs(vectorGlyphs_points, vectorGlyphs_points_pairOrigins,
137 vectorGlyphs_cells_pairTypes, vectorGlyphs_point_ids,
138 vectorGlyphs_point_dimensions, triangulation);
139
140 const auto nPoints = vectorGlyphs_points.size();
141
142 vtkNew<vtkPoints> points{};
143 points->SetNumberOfPoints(nPoints);
144 vtkNew<vtkSignedCharArray> pairOrigins{};
145 pairOrigins->SetNumberOfComponents(1);
146 pairOrigins->SetName("PairOrigin");
147 pairOrigins->SetNumberOfTuples(nPoints);
148
149#ifdef TTK_ENABLE_OPENMP
150#pragma omp parallel for num_threads(this->threadNumber_)
151#endif // TTK_ENABLE_OPENMP
152 for(size_t i = 0; i < nPoints; ++i) {
153 points->SetPoint(i, vectorGlyphs_points[i].data());
154 pairOrigins->SetTuple1(i, vectorGlyphs_points_pairOrigins[i]);
155 }
156 outputVectorGlyphs->SetPoints(points);
157
158 const auto nCells = vectorGlyphs_cells_pairTypes.size();
159
160 vtkNew<vtkIdTypeArray> offsets{}, connectivity{};
161 offsets->SetNumberOfComponents(1);
162 offsets->SetNumberOfTuples(nCells + 1);
163 connectivity->SetNumberOfComponents(1);
164 connectivity->SetNumberOfTuples(2 * nCells);
165 vtkNew<vtkSignedCharArray> pairTypes{};
166 pairTypes->SetNumberOfComponents(1);
167 pairTypes->SetName("PairType");
168 pairTypes->SetNumberOfTuples(nCells);
169 vtkNew<ttkSimplexIdTypeArray> cellIds{};
170 cellIds->SetNumberOfComponents(1);
171 cellIds->SetName("CellId");
172 cellIds->SetNumberOfTuples(2 * nCells);
173 vtkNew<vtkSignedCharArray> cellDimensions{};
174 cellDimensions->SetNumberOfComponents(1);
175 cellDimensions->SetName("CellDimension");
176 cellDimensions->SetNumberOfTuples(2 * nCells);
177
178#ifdef TTK_ENABLE_OPENMP
179#pragma omp parallel for num_threads(this->threadNumber_)
180#endif // TTK_ENABLE_OPENMP
181 for(size_t i = 0; i < nCells; ++i) {
182 offsets->SetTuple1(i, 2 * i);
183 // each glyph/line has unique points
184 connectivity->SetTuple1(2 * i, 2 * i);
185 connectivity->SetTuple1(2 * i + 1, 2 * i + 1);
186 pairTypes->SetTuple1(i, vectorGlyphs_cells_pairTypes[i]);
187 cellIds->SetTuple1(2 * i + 0, vectorGlyphs_point_ids[2 * i + 0]);
188 cellIds->SetTuple1(2 * i + 1, vectorGlyphs_point_ids[2 * i + 1]);
189 cellDimensions->SetTuple1(
190 2 * i + 0, vectorGlyphs_point_dimensions[2 * i + 0]);
191 cellDimensions->SetTuple1(
192 2 * i + 1, vectorGlyphs_point_dimensions[2 * i + 1]);
193 }
194 offsets->SetTuple1(nCells, connectivity->GetNumberOfTuples());
195
196 vtkNew<vtkCellArray> cells{};
197 cells->SetData(offsets, connectivity);
198 outputVectorGlyphs->SetLines(cells);
199
200 vtkPointData *pointData = outputVectorGlyphs->GetPointData();
201 vtkCellData *cellData = outputVectorGlyphs->GetCellData();
202
203#ifndef TTK_ENABLE_KAMIKAZE
204 if(pointData == nullptr || cellData == nullptr) {
205 this->printErr("In outputVectorGlyphs point or cell data");
206 return -1;
207 }
208#endif
209
210 pointData->AddArray(pairOrigins);
211 pointData->AddArray(cellIds);
212 pointData->AddArray(cellDimensions);
213 cellData->SetScalars(pairTypes);
214
215 this->printMsg(
216 "Computed Vector Glyphs", 1.0, tm.getElapsedTime(), this->threadNumber_);
217
218 return 0;
219}
220
222 vtkInformationVector **inputVector,
223 vtkInformationVector *outputVector) {
224
225 auto input = vtkDataSet::GetData(inputVector[0]);
226 auto outputCriticalPoints = vtkPolyData::GetData(outputVector, 0);
227 auto outputVectorGlyphs = vtkPolyData::GetData(outputVector, 1);
228
229 auto triangulation = ttkAlgorithm::GetTriangulation(input);
230
231 int keepGoing = checkEmptyMPIInput<ttk::Triangulation>(triangulation);
232 if(keepGoing < 2) {
233 return keepGoing;
234 }
235#ifndef TTK_ENABLE_KAMIKAZE
236 if(!input) {
237 this->printErr("Input pointer is NULL.");
238 return -1;
239 }
240 if(!outputCriticalPoints or !outputVectorGlyphs) {
241 this->printErr("Output pointer is NULL.");
242 return -1;
243 }
244 if(!input->GetNumberOfPoints()) {
245 this->printErr("Input has no point.");
246 return -1;
247 }
248#endif
249
250 this->preconditionTriangulation(triangulation);
251
252 const auto inputVectors = this->GetInputArrayToProcess(0, input);
253
254 if(inputVectors == nullptr) {
255 this->printErr("Input vector array is NULL");
256 return 0;
257 }
258 if(this->GetInputArrayAssociation(0, inputVector) != 0) {
259 this->printErr("Input array needs to be a point data array.");
260 return 0;
261 }
262 if(inputVectors->GetNumberOfComponents() != 3) {
263 this->printErr("Input array needs to be a vector array(3D).");
264 return 0;
265 }
266
267 int ret{};
268
269 // baseCode processing
271 ttkUtils::GetVoidPointer(inputVectors), inputVectors->GetMTime());
272#ifdef TTK_ENABLE_MPI_TIME
273 ttk::Timer t_mpi;
274 ttk::startMPITimer(t_mpi, ttk::MPIrank_, ttk::MPIsize_);
275#endif
276 ttkVtkTemplateMacro(inputVectors->GetDataType(), triangulation->getType(),
277 (ret = this->buildField<VTK_TT, TTK_TT>(
278 *static_cast<TTK_TT *>(triangulation->getData()))));
279#ifdef TTK_ENABLE_MPI_TIME
280 double elapsedTime = ttk::endMPITimer(t_mpi, ttk::MPIrank_, ttk::MPIsize_);
281 if(ttk::MPIrank_ == 0) {
282 printMsg("Computation performed using " + std::to_string(ttk::MPIsize_)
283 + " MPI processes lasted :" + std::to_string(elapsedTime));
284 }
285#endif
286 if(ret != 0) {
287 this->printErr("DiscreteVectorField.buildField() error code: "
288 + std::to_string(ret));
289 return 0;
290 }
291
292 // critical points
294 inputVectors->GetDataType(), triangulation->getType(),
295 (fillCriticalPoints<VTK_TT, TTK_TT>(
296 outputCriticalPoints, *static_cast<TTK_TT *>(triangulation->getData()))));
297
298 // vector glyphs
299 if(ComputeVectorGlyphs) {
301 triangulation->getType(),
302 (fillVectorGlyphs<TTK_TT>(
303 outputVectorGlyphs, *static_cast<TTK_TT *>(triangulation->getData()))));
304 }
305
306 return 1;
307}
#define ttkTemplateMacro(triangulationType, call)
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
int checkEmptyMPIInput(inputType *input)
This method tests whether the input is a nullptr. If the computation is being done on multiple proces...
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
TTK VTK-filter that wraps the discreteVectorField processing package.
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillInputPortInformation(int port, vtkInformation *info) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:226
static int CellVertexFromPoints(vtkDataSet *const dataSet, vtkPoints *const points)
Definition ttkUtils.cpp:329
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
int setCriticalPoints(const std::array< std::vector< SimplexId >, 4 > &criticalCellsByDim, std::vector< std::array< float, 3 > > &points, std::vector< char > &cellDimensions, std::vector< SimplexId > &cellIds, std::vector< char > &isOnBoundary, std::vector< SimplexId > &PLVertexIdentifiers, const triangulationType &triangulation) const
int setVectorGlyphs(std::vector< std::array< float, 3 > > &points, std::vector< char > &points_pairOrigins, std::vector< char > &cells_pairTypes, std::vector< SimplexId > &cellsIds, std::vector< char > &cellsDimensions, const triangulationType &triangulation) const
void preconditionTriangulation(AbstractTriangulation *const data)
void setInputVectorField(const void *const data, const size_t mTime)
COMMON_EXPORTS int MPIsize_
Definition BaseClass.cpp:10
COMMON_EXPORTS int MPIrank_
Definition BaseClass.cpp:9
const char VertexScalarFieldName[]
default name for vertex scalar field
Definition DataTypes.h:35
vtkStandardNewMacro(ttkDiscreteVectorField)
#define ttkVtkTemplateMacro(dataType, triangulationType, call)
Definition ttkMacros.h:69
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)