TTK
Loading...
Searching...
No Matches
DiscreteGradient.cpp
Go to the documentation of this file.
1#include <DiscreteGradient.h>
2
3using namespace std;
4using namespace ttk;
5using namespace dcg;
6
10
14
15void DiscreteGradient::initMemory(const AbstractTriangulation &triangulation) {
16
17 Timer tm{};
18 const int numberOfDimensions = this->getNumberOfDimensions();
19
20 // init number of cells by dimension
21 std::vector<SimplexId> numberOfCells(numberOfDimensions);
22 for(int i = 0; i < numberOfDimensions; ++i) {
23 numberOfCells[i] = this->getNumberOfCells(i, triangulation);
24 }
25
26 // clear & init gradient memory
27#ifdef TTK_ENABLE_OPENMP
28#pragma omp parallel master num_threads(threadNumber_)
29#endif
30 {
31 for(int i = 0; i < dimensionality_; ++i) {
32#ifdef TTK_ENABLE_OPENMP
33#pragma omp task
34#endif
35 {
36 (*gradient_)[2 * i].clear();
37 (*gradient_)[2 * i].resize(numberOfCells[i], -1);
38 }
39#ifdef TTK_ENABLE_OPENMP
40#pragma omp task
41#endif
42 {
43 (*gradient_)[2 * i + 1].clear();
44 (*gradient_)[2 * i + 1].resize(numberOfCells[i + 1], -1);
45 }
46 }
47 }
48
49 std::vector<std::vector<std::string>> rows{
50 {"#Vertices", std::to_string(numberOfCells[0])},
51 {"#Edges", std::to_string(numberOfCells[1])},
52 };
53
54 if(dimensionality_ >= 2) {
55 rows.emplace_back(
56 std::vector<std::string>{"#Triangles", std::to_string(numberOfCells[2])});
57 }
58
59 if(dimensionality_ == 3) {
60 rows.emplace_back(
61 std::vector<std::string>{"#Tetras", std::to_string(numberOfCells[3])});
62 }
63
64 this->printMsg(rows);
65 this->printMsg("Initialized discrete gradient memory", 1.0,
66 tm.getElapsedTime(), this->threadNumber_);
67}
68
69std::pair<size_t, SimplexId>
70 DiscreteGradient::numUnpairedFaces(const CellExt &c,
71 const lowerStarType &ls) const {
72 // c.dim_ cannot be <= 1
73 if(c.dim_ == 2) {
74 return numUnpairedFacesTriangle(c, ls);
75 } else if(c.dim_ == 3) {
76 return numUnpairedFacesTetra(c, ls);
77 }
78
79 return {0, -1};
80}
81
82std::pair<size_t, SimplexId>
83 DiscreteGradient::numUnpairedFacesTriangle(const CellExt &c,
84 const lowerStarType &ls) const {
85 // number of unpaired faces
86 std::pair<size_t, SimplexId> res{0, -1};
87
88 // loop over edge faces of triangle
89 // (2 edges per triangle in lower star)
90 for(size_t i = 0; i < 2; ++i) {
91 if(!ls[1][c.faces_[i]].paired_) {
92 res.first++;
93 res.second = c.faces_[i];
94 }
95 }
96
97 return res;
98}
99
100std::pair<size_t, SimplexId>
101 DiscreteGradient::numUnpairedFacesTetra(const CellExt &c,
102 const lowerStarType &ls) const {
103 // number of unpaired faces
104 std::pair<size_t, SimplexId> res{0, -1};
105
106 // loop over triangle faces of tetra
107 for(const auto f : c.faces_) {
108 if(!ls[2][f].paired_) {
109 res.first++;
110 res.second = f;
111 }
112 }
113
114 return res;
115}
116
118 DiscreteGradient::criticalTypeFromCellDimension(const int dim) const {
119 if(dim == 0) {
121 } else if(dim == 1) {
123 } else if(dim == 2 && dimensionality_ == 3) {
125 } else if(dim == dimensionality_) {
127 } else {
129 }
130}
131
132bool DiscreteGradient::isMinimum(const Cell &cell) const {
133 if(cell.dim_ == 0) {
134 return ((*gradient_)[0][cell.id_] == -1);
135 }
136
137 return false;
138}
139
140bool DiscreteGradient::isSaddle1(const Cell &cell) const {
141 if(cell.dim_ == 1) {
142 return ((*gradient_)[1][cell.id_] == -1
143 and (*gradient_)[2][cell.id_] == -1);
144 }
145
146 return false;
147}
148
149bool DiscreteGradient::isSaddle2(const Cell &cell) const {
150 if(dimensionality_ == 3 and cell.dim_ == 2) {
151 return ((*gradient_)[3][cell.id_] == -1
152 and (*gradient_)[4][cell.id_] == -1);
153 }
154
155 return false;
156}
157
158bool DiscreteGradient::isMaximum(const Cell &cell) const {
159 if(dimensionality_ == 1 and cell.dim_ == 1) {
160 return ((*gradient_)[1][cell.id_] == -1);
161 }
162
163 if(dimensionality_ == 2 and cell.dim_ == 2) {
164 return ((*gradient_)[3][cell.id_] == -1);
165 }
166
167 if(dimensionality_ == 3 and cell.dim_ == 3) {
168 return ((*gradient_)[5][cell.id_] == -1);
169 }
170
171 return false;
172}
173
174bool DiscreteGradient::isCellCritical(const int cellDim,
175 const SimplexId cellId) const {
176
177 if(cellDim > this->dimensionality_) {
178 return false;
179 }
180
181 if(cellDim == 0) {
182 return ((*gradient_)[0][cellId] == NULL_GRADIENT);
183 }
184
185 if(cellDim == 1) {
186 return (
187 (*gradient_)[1][cellId] == NULL_GRADIENT
188 && (dimensionality_ == 1 || (*gradient_)[2][cellId] == NULL_GRADIENT));
189 }
190
191 if(cellDim == 2) {
192 return (
193 (*gradient_)[3][cellId] == NULL_GRADIENT
194 && (dimensionality_ == 2 || (*gradient_)[4][cellId] == NULL_GRADIENT));
195 }
196
197 if(cellDim == 3) {
198 return ((*gradient_)[5][cellId] == NULL_GRADIENT);
199 }
200
201 return false;
202}
203
204bool DiscreteGradient::isCellCritical(const Cell &cell) const {
205 return isCellCritical(cell.dim_, cell.id_);
206}
207
209 const std::array<std::vector<SimplexId>, 4> &criticalCellsByDim,
210 const SimplexId *const ascendingManifold,
211 const SimplexId *const descendingManifold,
212 std::vector<SimplexId> &manifoldSize) const {
213
214 const auto nCritPoints{
215 criticalCellsByDim[0].size() + criticalCellsByDim[1].size()
216 + criticalCellsByDim[2].size() + criticalCellsByDim[3].size()};
217
218 const auto dim{this->dimensionality_};
219
220 if(nCritPoints == 0
221 || (criticalCellsByDim[0].empty() && criticalCellsByDim[dim].empty())) {
222 // no critical points || no extrema
223 return 0;
224 }
225
226 manifoldSize.resize(nCritPoints, 0);
227
228 // descending manifold cells size
229 if(!criticalCellsByDim[0].empty()) {
230 for(SimplexId i = 0; i < numberOfVertices_; ++i) {
231 if(descendingManifold[i] != -1) {
232 manifoldSize[descendingManifold[i]]++;
233 }
234 }
235 }
236
237 if(!criticalCellsByDim[dim].empty()) {
238 // index of first maximum in critical points array
239 const auto nFirstMaximum{nCritPoints - criticalCellsByDim[dim].size()};
240
241 // ascending manifold cells size
242 for(SimplexId i = 0; i < numberOfVertices_; ++i) {
243 if(ascendingManifold[i] != -1) {
244 manifoldSize[ascendingManifold[i] + nFirstMaximum]++;
245 }
246 }
247 }
248
249 return 0;
250}
251
252#ifdef TTK_ENABLE_MPI
253void DiscreteGradient::setCellToGhost(const int cellDim,
254 const SimplexId cellId) {
255 if(cellDim == 0) {
256 (*gradient_)[0][cellId] = GHOST_GRADIENT;
257 }
258
259 if(cellDim == 1) {
260 (*gradient_)[1][cellId] = GHOST_GRADIENT;
261 (*gradient_)[2][cellId] = GHOST_GRADIENT;
262 }
263
264 if(cellDim == 2) {
265 (*gradient_)[3][cellId] = GHOST_GRADIENT;
266 (*gradient_)[4][cellId] = GHOST_GRADIENT;
267 }
268
269 if(cellDim == 3) {
270 (*gradient_)[5][cellId] = GHOST_GRADIENT;
271 }
272}
273#endif
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
bool isMinimum(const Cell &cell) const
bool isCellCritical(const Cell &cell) const
bool isSaddle1(const Cell &cell) const
bool isMaximum(const Cell &cell) const
bool isSaddle2(const Cell &cell) const
int setManifoldSize(const std::array< std::vector< SimplexId >, 4 > &criticalCellsByDim, const SimplexId *const ascendingManifold, const SimplexId *const descendingManifold, std::vector< SimplexId > &manifoldSize) const
SimplexId getNumberOfCells(const int dimension, const triangulationType &triangulation) const
bool isCellCritical(const int cellDim, const SimplexId cellId) const
AbstractTriangulation::gradientType * gradient_
std::string to_string(__int128)
Definition ripserpy.cpp:99
The Topology ToolKit.
CriticalType
default value for critical index
Definition DataTypes.h:80
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
Extended Cell structure for processLowerStars.
const std::array< uint8_t, 3 > faces_
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)