TTK
Loading...
Searching...
No Matches
ttkTriangulationManager.cpp
Go to the documentation of this file.
2
3#include <vtkDataObject.h> // For port information
4#include <vtkObjectFactory.h> // for new macro
5
6#include <vtkCellData.h>
7#include <vtkCommand.h>
8#include <vtkDataArray.h>
9#include <vtkDataSet.h>
10#include <vtkInformation.h>
11#include <vtkIntArray.h>
12#include <vtkPointData.h>
13#include <vtkPointSet.h>
14#include <vtkSmartPointer.h>
15
17#include <Triangulation.h>
18#include <ttkUtils.h>
19#include <vtkUnstructuredGrid.h>
20
22
24 this->setDebugMsgPrefix("TriangulationManager");
25 this->SetNumberOfInputPorts(1);
26 this->SetNumberOfOutputPorts(1);
27 // ensure that modifying the selection re-triggers the filter
28 // (c.f. vtkPassSelectedArrays.cxx)
29 this->ArraySelection = vtkSmartPointer<vtkDataArraySelection>::New();
30 this->ArraySelection->AddObserver(
31 vtkCommand::ModifiedEvent, this, &ttkTriangulationManager::Modified);
32#ifdef TTK_ENABLE_MPI
33 hasMPISupport_ = true;
34#endif
35}
36
38 vtkInformation *info) {
39 if(port == 0) {
40 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
41 return 1;
42 }
43 return 0;
44}
45
47 vtkInformation *info) {
48 if(port == 0) {
50 return 1;
51 }
52 return 0;
53}
54#ifdef TTK_ENABLE_MPI
56 vtkInformation *request,
57 vtkInformationVector **inputVector,
58 vtkInformationVector *outputVector) {
59 if(Periodicity && ttk::isRunningWithMPI()) {
60 return this->periodicGhostGenerator->RequestUpdateExtent(
61 request, inputVector, outputVector);
62 }
63 return 1;
64}
66 vtkInformation *request,
67 vtkInformationVector **inputVectors,
68 vtkInformationVector *outputVector) {
69 if(Periodicity && ttk::isRunningWithMPI()) {
70 return this->periodicGhostGenerator->RequestInformation(
71 request, inputVectors, outputVector);
72 }
73 return 1;
74}
75#endif
76
77static void
78 switchPeriodicity(ttk::Triangulation &triangulation,
79 const bool periodic,
80 const ttk::Debug &dbg
81#ifdef TTK_ENABLE_MPI
82 ,
83 vtkImageData *imageIn,
84 vtkImageData *imageOut,
85 ttkPeriodicGhostsGeneration *periodicGhostGenerator,
86 int debugLevel,
87 float cacheSize
88#endif
89 ) {
90 const bool prevPeriodic = triangulation.hasPeriodicBoundaries();
91
92 if(prevPeriodic != periodic) {
93#ifdef TTK_ENABLE_MPI
94 if(periodic) {
95 if(ttk::isRunningWithMPI()) {
96 periodicGhostGenerator->MPIPeriodicGhostPipelinePreconditioning(
97 imageIn, imageOut);
98 triangulation.setIsMPIValid(false);
99 auto newTriangulation = ttkTriangulationFactory::GetTriangulation(
100 debugLevel, cacheSize, imageOut);
101 newTriangulation->setPeriodicBoundaryConditions(periodic);
102 // Retrieve neighbors from the PeriodicGhostGenerator
103 std::vector<int> &neighbors = newTriangulation->getNeighborRanks();
104 std::map<int, int> &neighborsToId
105 = newTriangulation->getNeighborsToId();
106 neighbors = periodicGhostGenerator->getNeighbors();
107 neighborsToId = periodicGhostGenerator->getNeighborsToId();
108 newTriangulation->setIsBoundaryPeriodic(
109 periodicGhostGenerator->getIsBoundaryPeriodic());
110 }
111 }
112#endif
113 triangulation.setPeriodicBoundaryConditions(periodic);
114 dbg.printMsg("Switching regular grid periodicity from "
115 + (prevPeriodic ? std::string("ON") : std::string("OFF"))
116 + " to "
117 + (periodic ? std::string("ON") : std::string("OFF")));
118 }
119}
120
121static void switchPreconditions(ttk::Triangulation &triangulation,
122 const ttk::Triangulation::STRATEGY precStrategy,
123 const ttk::Debug &dbg) {
124 const bool prevPreconditions = triangulation.hasImplicitPreconditions();
126 && !prevPreconditions)
128 && prevPreconditions)) {
129 return;
130 }
131
132 triangulation.setImplicitPreconditions(precStrategy);
133 const auto newPreconditions = triangulation.hasImplicitPreconditions();
134 if(prevPreconditions != newPreconditions) {
135 dbg.printMsg("Switching regular grid preconditions from "
136 + (prevPreconditions ? std::string("ON") : std::string("OFF"))
137 + " to "
138 + (newPreconditions ? std::string("ON") : std::string("OFF")));
139 }
140}
141
143#ifdef TTK_ENABLE_MPI
144 ,
145 vtkImageData *imageIn,
146 vtkImageData *imageOut
147#endif
148) {
149
150 switchPeriodicity(triangulation, this->Periodicity, *this
151#ifdef TTK_ENABLE_MPI
152 ,
153 imageIn, imageOut, this->periodicGhostGenerator,
155#endif
156 );
157 switchPreconditions(triangulation, this->PreconditioningStrategy, *this);
158}
159
161 vtkUnstructuredGrid *const output,
162 vtkPointSet *const input,
163 ttk::Triangulation &triangulation) const {
164
165 if(output == nullptr || input == nullptr) {
166 this->printErr("Empty data-sets");
167 return 0;
168 }
169 ttk::Timer tm{};
170
171#ifdef TTK_ENABLE_MPI
172 if((ttk::hasInitializedMPI()) && (ttk::isRunningWithMPI())) {
173 this->printWrn("Compact triangulation not supported with MPI!");
174 this->printWrn("Keeping the Explicit triangulation.");
175 output->ShallowCopy(input);
176 return 1;
177 }
178#endif // TTK_ENABLE_MPI
179
180 // If all checks pass then log which array is going to be processed.
181 this->printMsg("Compact explicit triangulation...");
182 int status = 0; // this integer checks if the base code returns an error
185 triangulation.getType(),
186 (status = worker.execute(
187 static_cast<TTK_TT *>(triangulation.getData()), this->Threshold)));
188
189 // On error cancel filter execution
190 if(status != 1)
191 return 0;
192
193 // Get input data array selection
194 std::vector<vtkDataArray *> pointDataArrays{};
195 std::vector<vtkDataArray *> cellDataArrays{};
196
197 vtkPointData *inPointData = input->GetPointData();
198 for(int i = 0; i < inPointData->GetNumberOfArrays(); i++) {
199 vtkDataArray *curArray = inPointData->GetArray(i);
200 if(curArray != nullptr && curArray->GetName() != nullptr
201 && ArraySelection->ArrayIsEnabled(curArray->GetName())) {
202 pointDataArrays.emplace_back(curArray);
203 }
204 }
205
206 vtkCellData *inCellData = input->GetCellData();
207 for(int i = 0; i < inCellData->GetNumberOfArrays(); i++) {
208 vtkDataArray *curArray = inCellData->GetArray(i);
209 if(curArray != nullptr && curArray->GetName() != nullptr
210 && ArraySelection->ArrayIsEnabled(curArray->GetName())) {
211 cellDataArrays.emplace_back(curArray);
212 }
213 }
214
215 output->Initialize();
216
217 const auto &vertices{worker.getVertices()};
218 const auto &nodes{worker.getNodes()};
219 const auto &cells{worker.getCells()};
220 std::vector<ttk::SimplexId> vertexMap(vertices.size());
221
222 vtkNew<vtkPoints> points{};
223 vtkNew<vtkIntArray> indices{};
224
225 indices->SetNumberOfComponents(1);
226 indices->SetName(ttk::compactTriangulationIndex);
227
228 // insert vertices in the output mesh
229 for(size_t i = 0; i < vertices.size(); i++) {
230 float x, y, z;
231 triangulation.getVertexPoint(vertices[i], x, y, z);
232 points->InsertNextPoint(x, y, z);
233 vertexMap[vertices[i]] = i;
234 indices->InsertNextTuple1(nodes[i]);
235 }
236 output->SetPoints(points);
237
238 output->GetPointData()->AddArray(indices);
239
240 // insert cells in the output mesh
241 output->Allocate(cells.size());
242 const size_t dimension = triangulation.getCellVertexNumber(0);
243 if(dimension > 4 || dimension < 2) {
244 this->printErr("Dimension not supported");
245 return 0;
246 }
247
248 for(unsigned int i = 0; i < cells.size(); i++) {
249 std::array<vtkIdType, 4> cell{};
250 for(size_t j = 0; j < dimension; j++) {
251 ttk::SimplexId vertexId;
252 triangulation.getCellVertex(cells[i], j, vertexId);
253 cell[j] = vertexMap[vertexId];
254 }
255 std::sort(cell.begin(), cell.begin() + dimension);
256 if(dimension == 2) {
257 output->InsertNextCell(VTK_LINE, 2, cell.data());
258 } else if(dimension == 3) {
259 output->InsertNextCell(VTK_TRIANGLE, 3, cell.data());
260 } else if(dimension == 4) {
261 output->InsertNextCell(VTK_TETRA, 4, cell.data());
262 } else {
263 this->printErr("Should not get here!");
264 }
265 }
266
267 // Modify the selected point data arrays with new indices
268 for(vtkDataArray *scalarArray : pointDataArrays) {
269 vtkSmartPointer<vtkDataArray> const updatedField(
270 scalarArray->NewInstance());
271 updatedField->SetName(scalarArray->GetName());
272 for(size_t j = 0; j < vertices.size(); j++) {
273 updatedField->InsertTuple(j, scalarArray->GetTuple(vertices[j]));
274 }
275
276 output->GetPointData()->AddArray(updatedField);
277 }
278
279 // Modify the selected cell data arrays with new indices
280 for(vtkDataArray *scalarArray : cellDataArrays) {
281 vtkSmartPointer<vtkDataArray> const updatedField(
282 scalarArray->NewInstance());
283 updatedField->SetName(scalarArray->GetName());
284 for(size_t j = 0; j < cells.size(); j++) {
285 updatedField->InsertTuple(j, scalarArray->GetTuple(cells[j]));
286 }
287
288 output->GetCellData()->AddArray(updatedField);
289 }
290
291 this->printMsg("Done!", 1.0, tm.getElapsedTime(), 1);
292
293 // return success
294 return 1;
295}
296
298 vtkInformationVector **inputVector,
299 vtkInformationVector *outputVector) {
300
301 auto *inputDataSet = vtkDataSet::GetData(inputVector[0]);
302 auto *triangulation = ttkAlgorithm::GetTriangulation(inputDataSet);
303
304 if(triangulation == nullptr) {
305 this->printErr("Triangulation is NULL");
306 return 0;
307 }
308
309 if(inputDataSet->IsA("vtkImageData")) {
310#ifdef TTK_ENABLE_MPI
311 vtkImageData *imageIn = vtkImageData::GetData(inputVector[0]);
312 vtkImageData *imageOut = vtkImageData::GetData(outputVector);
313 imageOut->ShallowCopy(imageIn);
314 this->processImplicit(*triangulation, imageIn, imageOut);
315#else
316 this->processImplicit(*triangulation);
317 auto *outputDataSet = vtkDataSet::GetData(outputVector, 0);
318 outputDataSet->ShallowCopy(inputDataSet);
319#endif
320 return 1;
321 } else if(inputDataSet->IsA("vtkUnstructuredGrid")
322 || inputDataSet->IsA("vtkPolyData")) {
323 return this->processExplicit(vtkUnstructuredGrid::GetData(outputVector, 0),
324 vtkPointSet::SafeDownCast(inputDataSet),
325 *triangulation);
326 }
327
328 return 1;
329}
#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
static vtkInformationIntegerKey * SAME_DATA_TYPE_AS_INPUT_PORT()
float CompactTriangulationCacheSize
virtual int RequestInformation(vtkInformation *ttkNotUsed(request), vtkInformationVector **ttkNotUsed(inputVectors), vtkInformationVector *ttkNotUsed(outputVector))
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
virtual int RequestUpdateExtent(vtkInformation *ttkNotUsed(request), vtkInformationVector **ttkNotUsed(inputVectors), vtkInformationVector *ttkNotUsed(outputVector))
TTK VTK-filter that generates an outside ghost layer for periodic implicit grids when used in a distr...
static ttk::Triangulation * GetTriangulation(int debugLevel, float cacheRatio, vtkDataSet *object)
TTK VTK-filter that manages ttk::Triangulation options.
void processImplicit(ttk::Triangulation &triangulation)
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int processExplicit(vtkUnstructuredGrid *const output, vtkPointSet *const input, ttk::Triangulation &triangulation) const
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
bool hasPeriodicBoundaries() const
Returns true if the grid uses period boundary conditions.
TTK processing package for mesh preprocessing before using TopoCluster.
Minimalist debugging class.
Definition Debug.h:88
int debugLevel_
Definition Debug.h:379
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
Definition Debug.h:118
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
AbstractTriangulation * getData()
bool hasImplicitPreconditions() const
Returns true if the grid uses preconditions.
Triangulation::Type getType() const
int getCellVertex(const SimplexId &cellId, const int &localVertexId, SimplexId &vertexId) const override
SimplexId getCellVertexNumber(const SimplexId &cellId) const override
int getVertexPoint(const SimplexId &vertexId, float &x, float &y, float &z) const override
void setPeriodicBoundaryConditions(const bool &usePeriodicBoundaries)
void setImplicitPreconditions(const STRATEGY strategy)
Set the input grid preconditioning strategy.
const char compactTriangulationIndex[]
Definition DataTypes.h:77
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkTriangulationManager)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)