98 const int &sourceGlobalId,
99 const int &destinationGlobalId,
101 vtkIdType &sourcePointId,
102 vtkIdType &destinationPointId) {
104 vtkIdList *pointIds = block->GetCell(cellId_1)->GetPointIds();
105 int id_0 = pointIds->GetId(0);
106 int id_1 = pointIds->GetId(1);
107 pointIds = block->GetCell(cellId_2)->GetPointIds();
108 int id_2 = pointIds->GetId(0);
109 int id_3 = pointIds->GetId(1);
113 if((
int)cellId->GetValue(id_0) == sourceGlobalId)
114 sourcePointId = id_0;
115 else if((
int)cellId->GetValue(id_1) == sourceGlobalId)
116 sourcePointId = id_1;
117 else if((
int)cellId->GetValue(id_2) == sourceGlobalId)
118 sourcePointId = id_2;
119 else if((
int)cellId->GetValue(id_3) == sourceGlobalId)
120 sourcePointId = id_3;
122 if((
int)cellId->GetValue(id_0) == destinationGlobalId)
123 destinationPointId = id_0;
124 else if((
int)cellId->GetValue(id_1) == destinationGlobalId)
125 destinationPointId = id_1;
126 else if((
int)cellId->GetValue(id_2) == destinationGlobalId)
127 destinationPointId = id_2;
128 else if((
int)cellId->GetValue(id_3) == destinationGlobalId)
129 destinationPointId = id_3;
146 std::vector<int> &localToGlobal,
148 std::vector<std::array<double, 3>> &coordsSource,
149 std::vector<std::array<double, 3>> &coordsDestination,
150 std::vector<double> &scalarsSource,
151 std::vector<double> &scalarsDestination,
153 std::vector<int> &globalSourcePointId,
154 std::vector<int> &globalDestinationPointId) {
156 vtkPoints *points = block->GetPoints();
158 vtkCellData *cellData = block->GetCellData();
159 vtkSignedCharArray *separatrixTypes = vtkSignedCharArray::SafeDownCast(
167 vtkDoubleArray *separatrixSourceScalars;
168 vtkDoubleArray *separatrixDestinationScalars;
169 if(*(separatrixTypes->GetTuple(0)) == 0) {
170 separatrixDestinationScalars = vtkDoubleArray::SafeDownCast(
172 separatrixSourceScalars = vtkDoubleArray::SafeDownCast(
175 separatrixDestinationScalars = vtkDoubleArray::SafeDownCast(
177 separatrixSourceScalars = vtkDoubleArray::SafeDownCast(
181 int n_cells = block->GetNumberOfCells();
183 std::vector<int> sourceLocalToGlobal;
184 std::vector<int> destinationLocalToGlobal;
187 int separatrixLocalId = -1;
189 while(cellId_1 < n_cells) {
190 int separatrixId = separatrixIds->GetValue(cellId_1);
191 int cellId_2 = cellId_1 + 1;
192 int nextSeparatrixId = separatrixIds->GetValue(cellId_2);
193 while(nextSeparatrixId == separatrixId && cellId_2 < n_cells) {
194 nextSeparatrixId = separatrixIds->GetValue(++cellId_2);
198 int sourceGlobalId = sourceIds->GetValue(cellId_1);
199 int destinationGlobalId = destinationIds->GetValue(cellId_2);
200 int destinationLocalId = -1;
201 int sourceLocalId = -1;
202 vtkIdType sourcePointId;
203 vtkIdType destinationPointId;
205 computePointIds(cellId_1, cellId_2, sourceGlobalId, destinationGlobalId,
206 block, sourcePointId, destinationPointId);
209 sourceGlobalId, sourceLocalToGlobal, sourceLocalId);
211 destinationGlobalId, destinationLocalToGlobal, destinationLocalId);
212 if(!foundDestination) {
213 double destinationScalar
214 = *(separatrixDestinationScalars->GetTuple(cellId_1));
215 appendPoint(points, destinationPointId, destinationScalar,
216 coordsDestination, scalarsDestination);
217 globalDestinationPointId.push_back(destinationPointId);
219 if(!foundSource && !MergeEdgesOnSaddles) {
220 double sourceScalar = *(separatrixSourceScalars->GetTuple(cellId_1));
222 points, sourcePointId, sourceScalar, coordsSource, scalarsSource);
223 globalSourcePointId.push_back(sourcePointId);
226 adjacencyMatrixFull);
227 cellId_1 = cellId_2 + 1;
230 n_separatrices = separatrixLocalId + 1;
231 localToGlobal = std::move(destinationLocalToGlobal);
237 vtkMultiBlockDataSet *&multiBlock1_Separatrices,
238 vtkMultiBlockDataSet *&output1_Separatrices) {
241 int n_blocks = multiBlock1_Separatrices->GetNumberOfBlocks();
242 std::vector<std::vector<int>> LocalToGlobal(n_blocks);
243 std::vector<GraphMatrixFull> adjacencyMatricesFull(n_blocks);
244 std::vector<std::vector<std::array<double, 3>>> coordsDestination(n_blocks);
245 std::vector<std::vector<std::array<double, 3>>> coordsSource(n_blocks);
246 std::vector<std::vector<double>> scalarsDestination(n_blocks);
247 std::vector<std::vector<double>> scalarsSource(n_blocks);
248 std::vector<int> separatrixCountForEachBlock(n_blocks);
249 std::vector<std::vector<int>> edgeOccurrenceForEachBlock(n_blocks);
250 std::vector<std::vector<bool>> isomorphismsForEachBlock(n_blocks);
251 std::vector<std::vector<std::vector<int>>> matchingArrayForEachBlockSource(
253 std::vector<std::vector<std::vector<int>>>
254 matchingArrayForEachBlockDestination(n_blocks);
255 std::vector<std::vector<std::vector<int>>>
256 matchingArraySeparatrixForEachBlock(n_blocks);
257 std::vector<std::vector<int>> globalSourcePointIdForEachBlock(n_blocks);
258 std::vector<std::vector<int>> globalDestinationPointIdForEachBlock(n_blocks);
260#ifdef TTK_ENABLE_OPENMP
261#pragma omp parallel for num_threads(threadNumber_)
263 for(
int i = 0; i < n_blocks; i++) {
265 = vtkDataSet::SafeDownCast(multiBlock1_Separatrices->GetBlock(i));
268 block, LocalToGlobal[i], adjacencyMatricesFull[i], coordsSource[i],
269 coordsDestination[i], scalarsSource[i], scalarsDestination[i],
270 separatrixCountForEachBlock[i], globalSourcePointIdForEachBlock[i],
271 globalDestinationPointIdForEachBlock[i]);
277 for(
int i = 0; i < n_blocks; i++) {
278 std::string destinationSizeString
279 = std::to_string(globalDestinationPointIdForEachBlock[i].size());
280 std::string sourceSizeString
281 = std::to_string(globalSourcePointIdForEachBlock[i].size());
282 std::string blockIdString = std::to_string(i);
284 std::string msg1 =
"Number of critical points (min-max) for block ";
285 msg1 += blockIdString;
287 msg1 += destinationSizeString;
290 if(!MergeEdgesOnSaddles) {
291 std::string msg2 =
"Number of critical points (1sad-2sad) for block ";
292 msg2 += blockIdString;
294 msg2 += sourceSizeString;
300 adjacencyMatricesFull, separatrixCountForEachBlock, coordsSource,
301 coordsDestination, scalarsSource, scalarsDestination, MergeEdgesOnSaddles,
302 edgeOccurrenceForEachBlock, isomorphismsForEachBlock,
303 matchingArrayForEachBlockSource, matchingArrayForEachBlockDestination,
304 matchingArraySeparatrixForEachBlock);
309 std::vector<int> classId(n_blocks, -1);
312 for(
int i = 0; i < n_blocks; i++) {
315 classId[i] = idCount;
316 for(
int j = 0; j < n_blocks; j++) {
317 if(isomorphismsForEachBlock[i][j]) {
318 classId[j] = idCount;
324 for(
int i = 0; i < n_blocks; i++) {
325 for(
int j = 0; j < n_blocks; j++) {
326 assert(globalDestinationPointIdForEachBlock[i].size()
327 == matchingArrayForEachBlockDestination[j][i].size());
328 assert(globalSourcePointIdForEachBlock[i].size()
329 == matchingArrayForEachBlockSource[j][i].size());
333#ifdef TTK_ENABLE_OPENMP
334#pragma omp parallel for num_threads(threadNumber_)
336 for(
int i = 0; i < n_blocks; i++) {
339 = vtkDataSet::SafeDownCast(output1_Separatrices->GetBlock(i));
340 int cellNumber = block->GetNumberOfCells();
344 vtkNew<vtkFloatArray> occurrenceCount;
345 occurrenceCount->SetNumberOfComponents(1);
348 vtkNew<vtkIntArray> isomorphismClassId;
349 isomorphismClassId->SetNumberOfComponents(1);
352 vtkIdType currentCellId = 0;
353 int currentSeparatrixId = separatrixIds->GetValue(currentCellId);
354 int separatrixCount = 0;
356 = (float)edgeOccurrenceForEachBlock[i][separatrixCount] / n_blocks;
358 occurrenceCount->InsertNextValue(newValue);
360 for(
int j = 1; j < cellNumber; j++) {
361 if(separatrixIds->GetValue(j) != currentSeparatrixId) {
362 currentSeparatrixId = separatrixIds->GetValue(j);
365 = (float)edgeOccurrenceForEachBlock[i][separatrixCount] / n_blocks;
367 occurrenceCount->InsertNextValue(newValue);
370 block->GetCellData()->AddArray(occurrenceCount);
372 isomorphismClassId->InsertNextValue(classId[i]);
374 block->GetFieldData()->AddArray(isomorphismClassId);
376 for(
int j = 0; j < n_blocks; j++) {
378 vtkNew<vtkIntArray> matchingIdForSeparatrix_j;
379 matchingIdForSeparatrix_j->SetNumberOfComponents(1);
380 std::string tmp_string_1
384 const char *indexedArrayNameSeparatrix = tmp_string_1.c_str();
385 matchingIdForSeparatrix_j->SetName(indexedArrayNameSeparatrix);
387 int currentSeparatrixIdBis = separatrixIds->GetValue(0);
388 int separatrixCountBis = 0;
389 int newId = matchingArraySeparatrixForEachBlock[j][i][separatrixCountBis];
390 matchingIdForSeparatrix_j->InsertNextValue(newId);
392 for(
int k = 1; k < cellNumber; k++) {
393 if(separatrixIds->GetValue(k) != currentSeparatrixIdBis) {
394 currentSeparatrixIdBis = separatrixIds->GetValue(k);
395 separatrixCountBis++;
396 newId = matchingArraySeparatrixForEachBlock[j][i][separatrixCountBis];
398 matchingIdForSeparatrix_j->InsertNextValue(newId);
400 block->GetCellData()->AddArray(matchingIdForSeparatrix_j);
402 vtkNew<vtkIntArray> matchingIdForCriticalPoints_j;
403 matchingIdForCriticalPoints_j->SetNumberOfComponents(1);
404 std::string tmp_string_2
408 const char *indexedArrayNameMatchingsId = tmp_string_2.c_str();
409 matchingIdForCriticalPoints_j->SetName(indexedArrayNameMatchingsId);
410 vtkPoints *points = block->GetPoints();
412 for(
int k = 0; k < points->GetNumberOfPoints(); k++) {
413 matchingIdForCriticalPoints_j->InsertNextValue(-2);
416 for(
unsigned int k = 0;
417 k < globalDestinationPointIdForEachBlock[i].size(); k++) {
418 int globalPointIdThisBlock = globalDestinationPointIdForEachBlock[i][k];
419 int matchingIdOtherBlock
420 = matchingArrayForEachBlockDestination[j][i][k];
421 matchingIdForCriticalPoints_j->SetValue(
422 globalPointIdThisBlock, matchingIdOtherBlock);
424 if(!MergeEdgesOnSaddles) {
425 for(
unsigned int k = 0; k < globalSourcePointIdForEachBlock[i].size();
427 int globalPointIdThisBlock = globalSourcePointIdForEachBlock[i][k];
428 int matchingIdOtherBlock = matchingArrayForEachBlockSource[j][i][k];
429 matchingIdForCriticalPoints_j->SetValue(
430 globalPointIdThisBlock, matchingIdOtherBlock);
433 block->GetPointData()->AddArray(matchingIdForCriticalPoints_j);