checkIrregularSurfaceConnectionsFunctions.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
29 #include "polyMeshGenAddressing.H"
30 #include "helperFunctionsPar.H"
31 #include "sortEdgesIntoChains.H"
32 
33 # ifdef USE_OMP
34 #include <omp.h>
35 # endif
36 
37 //#define DEBUGCheck
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 
47 (
48  labelHashSet& badVertices,
49  const bool removeConnections
50 )
51 {
52  Info << "Checking cells connected to surface vertices" << endl;
53 
54  const meshSurfaceEngine& mse = surfaceEngine();
55  const labelList& bPoints = mse.boundaryPoints();
56 
57  polyMeshGenModifier meshModifier(mesh_);
58  pointFieldPMG& points = meshModifier.pointsAccess();
59  faceListPMG& faces = meshModifier.facesAccess();
60  cellListPMG& cells = meshModifier.cellsAccess();
61 
62  const VRWGraph& cellCells = mesh_.addressingData().cellCells();
63  const VRWGraph& pointCells = mesh_.addressingData().pointCells();
64 
65  boolList parallelBndNode(bPoints.size(), false);
66  if( Pstream::parRun() )
67  {
68  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
69 
70  forAllConstIter(Map<label>, globalToLocal, it)
71  parallelBndNode[it()] = true;
72  }
73 
74  //- check cells connected to surface nodes
75  //- cells connected to a vertex must create a single loop when cells
76  //- are visited over faces from to the other
77  label nBadVertices(0);
78  DynList<label> frontCells;
79 
80  const label size = bPoints.size();
81  # ifdef USE_OMP
82  # pragma omp parallel for private(frontCells) schedule(dynamic, 1000)
83  # endif
84  for(label bpI=0;bpI<size;++bpI)
85  {
86  if( parallelBndNode[bpI] )
87  continue;
88 
89  const label pointI = bPoints[bpI];
90 
91  Map<label> cellGroup(pointCells.sizeOfRow(pointI));
92 
93  label nGroup(0);
94 
95  forAllRow(pointCells, pointI, cI)
96  {
97  const label cellI = pointCells(pointI, cI);
98 
99  if( cellGroup.found(cellI) )
100  continue;
101 
102  cellGroup.insert(cellI, nGroup);
103  frontCells.clear();
104  frontCells.append(cellI);
105 
106  while( frontCells.size() != 0 )
107  {
108  const label cLabel = frontCells.removeLastElement();
109 
110  forAllRow(cellCells, cLabel, nI)
111  {
112  const label neiCell = cellCells(cLabel, nI);
113 
114  if( cellGroup.found(neiCell) )
115  continue;
116 
117  if( pointCells.contains(pointI, neiCell) )
118  {
119  cellGroup.insert(neiCell, nGroup);
120  frontCells.append(neiCell);
121  }
122  }
123 
124  }
125 
126  ++nGroup;
127  }
128 
129  if( nGroup != 1 )
130  {
131  # ifdef USE_OMP
132  # pragma omp critical
133  # endif
134  {
135  ++nBadVertices;
136  badVertices.insert(pointI);
137 
138  if( removeConnections )
139  {
140  const label nPoints = points.size();
141  forAllRow(pointCells, pointI, pcI)
142  {
143  const label cellI = pointCells(pointI, pcI);
144 
145  if( cellGroup[cellI] != 0 )
146  {
147  const cell& c = cells[cellI];
148 
149  forAll(c, fI)
150  {
151  face& f = faces[c[fI]];
152 
153  const label pos = f.which(pointI);
154 
155  if( pos > -1 )
156  f[pos] = nPoints + cellGroup[cellI] - 1;
157  }
158  }
159  }
160 
161  for(label i=1;i<nGroup;++i)
162  {
163  const point p = points[pointI];
164  points.append(p);
165  }
166  }
167  }
168  }
169  }
170 
171  if( Pstream::parRun() )
172  {
173  //- check if the vertices at processor boundaries
174  //- are connected correctly
175  const labelList& bp = mse.bp();
176  const label origNumVertices = bp.size();
177 
178  const labelList& owner = mesh_.owner();
179  const labelList& neighbour = mesh_.neighbour();
180  const PtrList<processorBoundaryPatch>& procBoundaries =
181  mesh_.procBoundaries();
182 
183  const labelLongList& globalCellLabel =
184  mesh_.addressingData().globalCellLabel();
185 
186  std::map<label, DynList<edge> > dualEdgesForPoint;
187  std::map<label, DynList<edge> >::iterator bpIter;
188  forAll(parallelBndNode, bpI)
189  {
190  if( !parallelBndNode[bpI] )
191  continue;
192 
193  dualEdgesForPoint.insert
194  (
195  std::make_pair(bpI, DynList<edge>())
196  );
197  }
198 
199  //- fill-in dualEdgesForPoint with local data
200  for(label faceI=0;faceI<mesh_.nInternalFaces();++faceI)
201  {
202  const face& f = faces[faceI];
203 
204  forAll(f, pI)
205  {
206  if( f[pI] >= origNumVertices )
207  continue;
208 
209  bpIter = dualEdgesForPoint.find(bp[f[pI]]);
210  if( bpIter != dualEdgesForPoint.end() )
211  {
212  const label cOwn = globalCellLabel[owner[faceI]];
213  const label cNei = globalCellLabel[neighbour[faceI]];
214 
215  //- store the edge
216  bpIter->second.append(edge(cOwn, cNei));
217  }
218  }
219  }
220 
221  //- fill-in with data at processor boundaries. Store edges
222  //- on the processor with the lower label not to duplicate the data
223  forAll(procBoundaries, patchI)
224  {
225  if( procBoundaries[patchI].owner() )
226  continue;
227 
228  const label start = procBoundaries[patchI].patchStart();
229  labelList globalLabels(procBoundaries[patchI].patchSize());
230  forAll(globalLabels, fI)
231  globalLabels[fI] = globalCellLabel[owner[start+fI]];
232 
233  OPstream toOtherProc
234  (
236  procBoundaries[patchI].neiProcNo(),
237  globalLabels.byteSize()
238  );
239 
240  toOtherProc << globalLabels;
241  }
242 
243  forAll(procBoundaries, patchI)
244  {
245  if( !procBoundaries[patchI].owner() )
246  continue;
247 
248  labelList receivedData;
249  IPstream fromOtherProc
250  (
252  procBoundaries[patchI].neiProcNo()
253  );
254 
255  fromOtherProc >> receivedData;
256 
257  const label start = procBoundaries[patchI].patchStart();
258 
259  forAll(receivedData, i)
260  {
261  const face& f = faces[start+i];
262 
263  forAll(f, pI)
264  {
265  bpIter = dualEdgesForPoint.find(bp[f[pI]]);
266  if( bpIter != dualEdgesForPoint.end() )
267  {
268  const label cOwn = globalCellLabel[owner[start+i]];
269  const label cNei = receivedData[i];
270  bpIter->second.append(edge(cOwn, cNei));
271  }
272  }
273  }
274  }
275 
276  //- exchange data with other processors
277  //- this step supplies all processors with all necessary data
278  const VRWGraph& bpAtProcs = mse.bpAtProcs();
279  const labelList& globalPointLabel = mse.globalBoundaryPointLabel();
280  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
281  std::map<label, labelLongList> exchangeData;
282  for
283  (
284  bpIter=dualEdgesForPoint.begin();
285  bpIter!=dualEdgesForPoint.end();
286  ++bpIter
287  )
288  {
289  const label bpI = bpIter->first;
290 
291  forAllRow(bpAtProcs, bpI, i)
292  {
293  const label neiProc = bpAtProcs(bpI, i);
294  if( neiProc == Pstream::myProcNo() )
295  continue;
296 
297  //- edges are sent to other processors as follows
298  //- 1. global point label
299  //- 2. number of edges at node
300  //- 3. labels of edges
301  labelLongList& dts = exchangeData[neiProc];
302  const DynList<edge>& edges = bpIter->second;
303  dts.append(globalPointLabel[bpI]);
304  dts.append(edges.size());
305  forAll(edges, eI)
306  {
307  dts.append(edges[eI].start());
308  dts.append(edges[eI].end());
309  }
310  }
311  }
312 
313  labelLongList receivedData;
314  help::exchangeMap(exchangeData, receivedData);
315 
316  label counter = 0;
317  while( counter < receivedData.size() )
318  {
319  const label bpI = globalToLocal[receivedData[counter++]];
320  const label nEdges = receivedData[counter++];
321 
322  for(label i=0;i<nEdges;++i)
323  {
324  const label s = receivedData[counter++];
325  const label e = receivedData[counter++];
326  dualEdgesForPoint[bpI].append(edge(s, e));
327  }
328  }
329 
330  # ifdef DEBUGCheck
331  for(label i=0;i<Pstream::nProcs();++i)
332  {
333  if( i == Pstream::myProcNo() )
334  {
335  for
336  (
337  bpIter=dualEdgesForPoint.begin();
338  bpIter!=dualEdgesForPoint.end();
339  ++bpIter
340  )
341  {
342  const DynList<edge>& pEdges = bpIter->second;
343  Pout << "Global point label " << globalPointLabel[bpIter->first]
344  << " point cells " << pointCells[bPoints[bpIter->first]]
345  << " dual edges " << pEdges << endl;
346  }
347  }
348 
350  }
351  # endif
352 
353  //- Finally, check the number of dual loops processor vertices
354  for
355  (
356  bpIter=dualEdgesForPoint.begin();
357  bpIter!=dualEdgesForPoint.end();
358  ++bpIter
359  )
360  {
361  const DynList<edge>& pEdges = bpIter->second;
362  std::map<label, DynList<label> > bpEdges;
363  forAll(pEdges, eI)
364  {
365  forAll(pEdges[eI], i)
366  bpEdges[pEdges[eI][i]].append(eI);
367  }
368 
369  //- check if all points can be visited via edges
370  counter = 0;
371  Map<label> cellGroup(pEdges.size());
372  for
373  (
374  std::map<label, DynList<label> >::iterator it=bpEdges.begin();
375  it!=bpEdges.end();
376  ++it
377  )
378  {
379  if( cellGroup.found(it->first) )
380  continue;
381 
382  cellGroup.insert(it->first, counter);
383  frontCells.clear();
384  frontCells.append(it->first);
385 
386  while( frontCells.size() != 0 )
387  {
388  const label cLabel = frontCells.removeLastElement();
389 
390  const DynList<label>& attachedEdges = bpEdges[cLabel];
391  forAll(attachedEdges, aeI)
392  {
393  const label oCell =
394  pEdges[attachedEdges[aeI]].otherVertex(cLabel);
395 
396  if( cellGroup.found(oCell) )
397  continue;
398 
399  frontCells.append(oCell);
400  cellGroup.insert(oCell, counter);
401  }
402  }
403 
404  ++counter;
405  }
406 
407  if( counter != 1 )
408  {
409  ++nBadVertices;
410  badVertices.insert(bPoints[bpIter->first]);
411 
412  if( !removeConnections )
413  continue;
414 
415  const label pointI = bPoints[bpIter->first];
416  const label nPoints = points.size();
417  forAllRow(pointCells, pointI, pcI)
418  {
419  const label cellI = pointCells(pointI, pcI);
420 
421  if( cellGroup[globalCellLabel[cellI]] == 0 )
422  continue;
423 
424  const cell& c = cells[cellI];
425 
426  forAll(c, fI)
427  {
428  face& f = faces[c[fI]];
429 
430  const label pos = f.which(pointI);
431 
432  if( pos > -1 )
433  f[pos] =
434  nPoints + cellGroup[globalCellLabel[cellI]] - 1;
435  }
436  }
437 
438  for(label i=1;i<counter;++i)
439  {
440  const point p = points[pointI];
441  points.append(p);
442  }
443  }
444  }
445  }
446 
447  reduce(nBadVertices, sumOp<label>());
448 
449  Info << "Found " << nBadVertices << " problematic vertices" << endl;
450  Info << "Finished checking cells connected to surface vertices" << endl;
451 
452  if( nBadVertices != 0 )
453  {
454  clearMeshEngine();
455  mesh_.clearAddressingData();
456 
457  return true;
458  }
459 
460  return false;
461 }
462 
464 (
465  labelHashSet& badVertices,
466  const bool removeCells
467 )
468 {
469  Info << "Checking for non-manifold surface edges" << endl;
470 
471  const meshSurfaceEngine& mse = surfaceEngine();
472  const labelList& bp = mse.bp();
473  const edgeList& edges = mse.edges();
474  const VRWGraph& edgeFaces = mse.edgeFaces();
475  const VRWGraph& pointEdges = mse.boundaryPointEdges();
476 
477  labelHashSet badEdges;
478 
479  forAll(edgeFaces, edgeI)
480  if( edgeFaces.sizeOfRow(edgeI) > 2 )
481  {
482  badVertices.insert(edges[edgeI].start());
483  badVertices.insert(edges[edgeI].end());
484 
485  badEdges.insert(edgeI);
486  }
487 
488  if( Pstream::parRun() )
489  {
490  //- boundary edges at processor boundaries
491  Map<label> numFacesAtEdge;
492  const labelList& globalEdgeLabel = mse.globalBoundaryEdgeLabel();
493  const Map<label>& globalToLocalEdgeLabel =
495  const VRWGraph& edgesAtProcs = mse.beAtProcs();
496 
497  const DynList<label>& neiProcs = mse.beNeiProcs();
498  std::map<label, labelLongList> exchangeData;
499  forAll(neiProcs, procI)
500  exchangeData.insert
501  (
502  std::make_pair(neiProcs[procI], labelLongList())
503  );
504  std::map<label, labelLongList>::iterator eIter;
505 
506  forAll(edgeFaces, eI)
507  {
508  if( edgesAtProcs.sizeOfRow(eI) > 0 )
509  {
510  numFacesAtEdge.insert
511  (
512  globalEdgeLabel[eI],
513  edgeFaces.sizeOfRow(eI)
514  );
515 
516  forAllRow(edgesAtProcs, eI, procI)
517  {
518  const label neiProc = edgesAtProcs(eI, procI);
519 
520  if( neiProc == Pstream::myProcNo() )
521  continue;
522 
523  eIter = exchangeData.find(neiProc);
524  eIter->second.append(globalEdgeLabel[eI]);
525  eIter->second.append(edgeFaces.sizeOfRow(eI));
526  }
527  }
528  }
529 
530  //- send data to other processors
531  labelLongList receivedData;
532  help::exchangeMap(exchangeData, receivedData);
533 
534  label counter(0);
535  while( counter < receivedData.size() )
536  {
537  const label geI = receivedData[counter++];
538  const label nFaces = receivedData[counter++];
539 
540  numFacesAtEdge[geI] += nFaces;
541 
542  if( numFacesAtEdge[geI] > 2 )
543  {
544  const label edgeI = globalToLocalEdgeLabel[geI];
545  badVertices.insert(edges[edgeI].start());
546  badVertices.insert(edges[edgeI].end());
547 
548  badEdges.insert(edgeI);
549  }
550  }
551  }
552 
553  const label nBadEdges = returnReduce(badEdges.size(), sumOp<label>());
554  Info << "Found " << nBadEdges << " non-manifold edges" << endl;
555  Info << "Finished checking for non-manifold surface edges" << endl;
556 
557  if( nBadEdges != 0 && removeCells )
558  {
559  //- remove all cells connected to the selected edge
560  boolList removeCell(mesh_.cells().size(), false);
561 
562  const faceListPMG& faces = mesh_.faces();
563  const labelList& owner = mesh_.owner();
564  const labelList& neighbour = mesh_.neighbour();
565 
566  forAll(faces, faceI)
567  {
568  const face& f = faces[faceI];
569 
570  forAll(f, pI)
571  {
572  const edge e = f.faceEdge(pI);
573 
574  if( (bp[e[0]] != -1) && (bp[e[1]] != -1) )
575  {
576  const label bpI = bp[e[0]];
577 
578  forAllRow(pointEdges, bpI, peI)
579  {
580  const label edgeI = pointEdges(bpI, peI);
581  if( (edges[edgeI] == e) && badEdges.found(edgeI) )
582  {
583  removeCell[owner[faceI]] = true;
584  if( neighbour[faceI] < 0 )
585  continue;
586  removeCell[neighbour[faceI]] = true;
587  }
588  }
589  }
590  }
591  }
592 
593  polyMeshGenModifier(mesh_).removeCells(removeCell);
594  clearMeshEngine();
595 
596  return true;
597  }
598 
599  return false;
600 }
601 
603 (
604  labelHashSet& badVertices,
605  const bool removeCells
606 )
607 {
608  Info << "Checking faces connections to surface vertices" << endl;
609 
610  labelHashSet invalidVertices(100);
611 
612  const meshSurfaceEngine& mse = surfaceEngine();
613 
614  const labelList& bPoints = mse.boundaryPoints();
615  const VRWGraph& pointFaces = mse.pointFaces();
616  const VRWGraph& faceFaces = mse.faceFaces();
617 
618  boolList parallelBndPoint(bPoints.size(), false);
619  if( Pstream::parRun() )
620  {
621  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
622 
623  forAllConstIter(Map<label>, globalToLocal, it)
624  parallelBndPoint[it()] = true;
625  }
626 
627  //- check number of face groups
628  DynList<label> front;
629  const label size = pointFaces.size();
630  # ifdef USE_OMP
631  # pragma omp parallel for private(front) schedule(dynamic)
632  # endif
633  for(label bpI=0;bpI<size;++bpI)
634  {
635  if( parallelBndPoint[bpI] )
636  continue;
637 
638  Map<label> faceGroup(pointFaces.sizeOfRow(bpI));
639  label nGroup(0);
640 
641  forAllRow(pointFaces, bpI, pfI)
642  {
643  const label fI = pointFaces(bpI, pfI);
644 
645  if( faceGroup.found(fI) )
646  continue;
647 
648  front.clear();
649  front.append(fI);
650  faceGroup.insert(fI, nGroup);
651 
652  while( front.size() != 0 )
653  {
654  const label fLabel = front.removeLastElement();
655 
656  forAllRow(faceFaces, fLabel, ffI)
657  {
658  const label neiFace = faceFaces(fLabel, ffI);
659 
660  if( faceGroup.found(neiFace) )
661  continue;
662 
663  if( pointFaces.contains(bpI, neiFace) )
664  {
665  front.append(neiFace);
666  faceGroup.insert(neiFace, nGroup);
667  }
668  }
669  }
670 
671  ++nGroup;
672  }
673 
674  if( nGroup != 1 )
675  {
676  const label pointI = bPoints[bpI];
677  # ifdef USE_OMP
678  # pragma omp critical
679  # endif
680  {
681  badVertices.insert(pointI);
682  invalidVertices.insert(pointI);
683  }
684  }
685  }
686 
687  if( Pstream::parRun() )
688  {
689  //- check connections at parallel vertices
690  //- a connection of two faces over an edge can be represented
691  //- as an edge. A list of edges at a bnd vertex must be connected
692  //- into a single loop, otherwise the surface is ill-connected.
693 
694  const labelList& globalPointLabel = mse.globalBoundaryPointLabel();
695  const Map<label>& globalToLocal = mse.globalToLocalBndPointAddressing();
696  const VRWGraph& bpAtProcs = mse.bpAtProcs();
697  const labelList& bp = mse.bp();
698 
699  const edgeList& edges = mse.edges();
700  const VRWGraph& pointEdges = mse.boundaryPointEdges();
701  const VRWGraph& edgeFaces = mse.edgeFaces();
702 
703  const labelList& globalFaceLabel = mse.globalBoundaryFaceLabel();
704 
705  const labelList& globalEdgeLabel = mse.globalBoundaryEdgeLabel();
706  const Map<label>& globalToLocalEdge =
708  const Map<label>& otherFaceAtProc = mse.otherEdgeFaceAtProc();
709  const DynList<label>& beNeiProcs = mse.beNeiProcs();
710 
711  //- create map of dual edges for boundary points at processor boundaries
712  std::map<label, DynList<edge> > dualEdgesForPoint;
713  std::map<label, DynList<edge> >::iterator bpIter;
714  forAll(parallelBndPoint, bpI)
715  {
716  if( !parallelBndPoint[bpI] )
717  continue;
718 
719  dualEdgesForPoint.insert(std::make_pair(bpI, DynList<edge>()));
720 
721  forAllRow(pointEdges, bpI, peI)
722  {
723  const label edgeI = pointEdges(bpI, peI);
724 
725  if( edgeFaces.sizeOfRow(edgeI) == 2 )
726  {
727  //- add local edge
728  edge e
729  (
730  globalFaceLabel[edgeFaces(edgeI, 0)],
731  globalFaceLabel[edgeFaces(edgeI, 1)]
732  );
733 
734  dualEdgesForPoint[bpI].append(e);
735  }
736  }
737  }
738 
739  std::map<label, labelLongList> exchangeData;
740  //- collect connections over processor edges on the processor with
741  //- the lowest label to avoid duplication of data
742  forAll(beNeiProcs, i)
743  exchangeData.insert(std::make_pair(beNeiProcs[i], labelLongList()));
744  forAllConstIter(Map<label>, otherFaceAtProc, it)
745  {
746  const label beI = it.key();
747 
748  if( it() < Pstream::myProcNo() )
749  {
750  //- the data is sent as follows:
751  //- 1. global edge label
752  //- 2. global face label
753  exchangeData[it()].append(globalEdgeLabel[beI]);
754  exchangeData[it()].append(globalFaceLabel[edgeFaces(beI, 0)]);
755  }
756  }
757 
758  labelLongList receivedData;
759  help::exchangeMap(exchangeData, receivedData);
760 
761  label counter(0);
762  while( counter < receivedData.size() )
763  {
764  const label beI = globalToLocalEdge[receivedData[counter++]];
765  const label fLabel = receivedData[counter++];
766 
767  const edge& e = edges[beI];
768  forAll(e, i)
769  {
770  const label bpI = bp[e[i]];
771 
772  const label fLocal = globalFaceLabel[edgeFaces(beI, 0)];
773  dualEdgesForPoint[bpI].append(edge(fLabel, fLocal));
774  }
775  }
776 
777  //- exchange data with other processors
778  //- this step supplies all processors with all necessary data
779  exchangeData.clear();
780  for
781  (
782  bpIter=dualEdgesForPoint.begin();
783  bpIter!=dualEdgesForPoint.end();
784  ++bpIter
785  )
786  {
787  const label bpI = bpIter->first;
788 
789  forAllRow(bpAtProcs, bpI, i)
790  {
791  const label neiProc = bpAtProcs(bpI, i);
792  if( neiProc == Pstream::myProcNo() )
793  continue;
794 
795  //- edges are sent to other processors as follows
796  //- 1. global point label
797  //- 2. number of edges at node
798  //- 3. labels of edges
799  labelLongList& dts = exchangeData[neiProc];
800  const DynList<edge>& edges = bpIter->second;
801  dts.append(globalPointLabel[bpI]);
802  dts.append(edges.size());
803  forAll(edges, eI)
804  {
805  dts.append(edges[eI].start());
806  dts.append(edges[eI].end());
807  }
808  }
809  }
810 
811  receivedData.clear();
812  help::exchangeMap(exchangeData, receivedData);
813 
814  counter = 0;
815  while( counter < receivedData.size() )
816  {
817  const label bpI = globalToLocal[receivedData[counter++]];
818  const label nEdges = receivedData[counter++];
819  for(label i=0;i<nEdges;++i)
820  {
821  const label s = receivedData[counter++];
822  const label e = receivedData[counter++];
823  dualEdgesForPoint[bpI].append(edge(s, e));
824  }
825  }
826 
827  # ifdef DEBUGCheck
828  for(label i=0;i<Pstream::nProcs();++i)
829  {
830  if( i == Pstream::myProcNo() )
831  {
832  for
833  (
834  bpIter=dualEdgesForPoint.begin();
835  bpIter!=dualEdgesForPoint.end();
836  ++bpIter
837  )
838  {
839  const DynList<edge>& pEdges = bpIter->second;
840  Pout << "Global point label "
841  << globalPointLabel[bpIter->first]
842  << " dual edges " << pEdges << endl;
843  }
844  }
845 
847  }
848  # endif
849 
850  //- Finally, check the number of dual loops processor vertices
851  for
852  (
853  bpIter=dualEdgesForPoint.begin();
854  bpIter!=dualEdgesForPoint.end();
855  ++bpIter
856  )
857  {
858  const DynList<edge>& pEdges = bpIter->second;
859 
860  std::map<label, DynList<label> > bpEdges;
861  forAll(pEdges, eI)
862  {
863  forAll(pEdges[eI], i)
864  bpEdges[pEdges[eI][i]].append(eI);
865  }
866 
867  //- check if all points can be visited via edges
868  counter = 0;
869  Map<label> cellGroup(pEdges.size());
870  for
871  (
872  std::map<label, DynList<label> >::iterator it=bpEdges.begin();
873  it!=bpEdges.end();
874  ++it
875  )
876  {
877  if( cellGroup.found(it->first) )
878  continue;
879 
880  cellGroup.insert(it->first, counter);
881  front.clear();
882  front.append(it->first);
883 
884  while( front.size() != 0 )
885  {
886  const label cLabel = front.removeLastElement();
887 
888  const DynList<label>& attachedEdges = bpEdges[cLabel];
889  forAll(attachedEdges, aeI)
890  {
891  const label oCell =
892  pEdges[attachedEdges[aeI]].otherVertex(cLabel);
893 
894  if( cellGroup.found(oCell) )
895  continue;
896 
897  front.append(oCell);
898  cellGroup.insert(oCell, counter);
899  }
900  }
901 
902  ++counter;
903  }
904 
905  if( counter != 1 )
906  {
907  invalidVertices.insert(bPoints[bpIter->first]);
908  badVertices.insert(bPoints[bpIter->first]);
909  }
910  }
911  }
912 
913  const label nBadVertices =
914  returnReduce(invalidVertices.size(), sumOp<label>());
915  Info << "Found " << nBadVertices << " invalid connections" << endl;
916  Info << "Finished checking faces connections to surface vertices" << endl;
917 
918  if( nBadVertices != 0 && removeCells )
919  {
920  const VRWGraph& pointCells = mesh_.addressingData().pointCells();
921 
922  boolList removeCell(mesh_.cells().size(), false);
923 
924  forAllConstIter(labelHashSet, invalidVertices, it)
925  {
926  forAllRow(pointCells, it.key(), pcI)
927  removeCell[pointCells(it.key(), pcI)] = true;
928  }
929 
930  polyMeshGenModifier(mesh_).removeCells(removeCell);
931  clearMeshEngine();
932 
933  return true;
934  }
935 
936  return false;
937 }
938 
939 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
940 
941 } // End namespace Foam
942 
943 // ************************************************************************* //
Foam::meshSurfaceEngine::boundaryPointEdges
const VRWGraph & boundaryPointEdges() const
Definition: meshSurfaceEngineI.H:315
Foam::meshSurfaceEngine::bpAtProcs
const VRWGraph & bpAtProcs() const
processors which contain the vertex
Definition: meshSurfaceEngineI.H:451
Foam::meshSurfaceEngine::beAtProcs
const VRWGraph & beAtProcs() const
processors which contain the edges
Definition: meshSurfaceEngineI.H:530
Foam::meshSurfaceEngine::bp
const labelList & bp() const
Definition: meshSurfaceEngineI.H:64
Foam::LongList::append
void append(const T &e)
Append an element at the end of the list.
Definition: LongListI.H:265
p
p
Definition: pEqn.H:62
Foam::meshSurfaceEngine::globalToLocalBndEdgeAddressing
const Map< label > & globalToLocalBndEdgeAddressing() const
global boundary edge label to local label. Only for processor edges
Definition: meshSurfaceEngineI.H:510
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::meshSurfaceEngine::globalBoundaryEdgeLabel
const labelList & globalBoundaryEdgeLabel() const
global boundary edge label
Definition: meshSurfaceEngineI.H:489
helperFunctionsPar.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::meshSurfaceEngine::globalBoundaryPointLabel
const labelList & globalBoundaryPointLabel() const
global boundary point label
Definition: meshSurfaceEngineI.H:410
Foam::removeCells
Given list of cells to remove insert all the topology changes.
Definition: removeCells.H:59
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:50
checkIrregularSurfaceConnections.H
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:387
Foam::LongList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: LongListI.H:230
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::meshSurfaceEngine::globalBoundaryFaceLabel
const labelList & globalBoundaryFaceLabel() const
global boundary face label
Definition: meshSurfaceEngineI.H:608
Foam::meshSurfaceEngine::pointFaces
const VRWGraph & pointFaces() const
Definition: meshSurfaceEngineI.H:162
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::checkIrregularSurfaceConnections::checkEdgeFaceConnections
bool checkEdgeFaceConnections(labelHashSet &badVertices, const bool removeCells=false)
Definition: checkIrregularSurfaceConnectionsFunctions.C:464
Foam::Map< label >
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::LongList::size
label size() const
Size of the active part of the list.
Definition: LongListI.H:203
Foam::cellListPMG
Definition: cellListPMG.H:49
Foam::HashSet< label, Hash< label > >
Foam::DynList::removeLastElement
T removeLastElement()
Return and remove the last element.
Definition: DynListI.H:384
Foam::VRWGraph::contains
bool contains(const label rowI, const label e) const
check if the element is in the given row (takes linear time)
Definition: VRWGraphI.H:511
Foam::meshSurfaceEngine::faceFaces
const VRWGraph & faceFaces() const
Definition: meshSurfaceEngineI.H:391
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::LongList< label >
Foam::UPstream::blocking
@ blocking
Definition: UPstream.H:66
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::polyMeshGenModifier::cellsAccess
cellListPMG & cellsAccess()
access to cells
Definition: polyMeshGenModifier.H:119
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::Info
messageStream Info
Foam::meshSurfaceEngine::otherEdgeFaceAtProc
const Map< label > & otherEdgeFaceAtProc() const
Definition: meshSurfaceEngineI.H:568
Foam::meshSurfaceEngine::beNeiProcs
const DynList< label > & beNeiProcs() const
communication matrix for sending edge data
Definition: meshSurfaceEngineI.H:549
Foam::VRWGraph::size
label size() const
Returns the number of rows.
Definition: VRWGraphI.H:122
Foam::checkIrregularSurfaceConnections::checkAndFixCellGroupsAtBndVertices
bool checkAndFixCellGroupsAtBndVertices(labelHashSet &badVertices, const bool removeConnections=false)
Definition: checkIrregularSurfaceConnectionsFunctions.C:47
sortEdgesIntoChains.H
Foam::PtrList
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
Foam::VRWGraph::sizeOfRow
label sizeOfRow(const label rowI) const
Returns the number of elements in the given row.
Definition: VRWGraphI.H:127
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::polyMeshGenModifier::pointsAccess
pointFieldPMG & pointsAccess()
access to mesh points
Definition: polyMeshGenModifier.H:107
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam::meshSurfaceEngine::edgeFaces
const VRWGraph & edgeFaces() const
Definition: meshSurfaceEngineI.H:334
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::DynList< label >
Foam::meshSurfaceEngine::edges
const edgeList & edges() const
Definition: meshSurfaceEngineI.H:296
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::polyMeshGenModifier
Definition: polyMeshGenModifier.H:52
Foam::sumOp
Definition: ops.H:162
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
f
labelList f(nPoints)
Foam::checkIrregularSurfaceConnections::checkFaceGroupsAtBndVertices
bool checkFaceGroupsAtBndVertices(labelHashSet &badVertices, const bool removeCells=false)
Definition: checkIrregularSurfaceConnectionsFunctions.C:603
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::help::exchangeMap
void exchangeMap(const std::map< label, ListType > &m, LongList< T > &data, const Pstream::commsTypes commsType)
Definition: helperFunctionsPar.C:129
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::meshSurfaceEngine::boundaryPoints
const labelList & boundaryPoints() const
Definition: meshSurfaceEngineI.H:84
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:50
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::DynList::size
label size() const
Definition: DynListI.H:235
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::meshSurfaceEngine::globalToLocalBndPointAddressing
const Map< label > & globalToLocalBndPointAddressing() const
global point label to local label. Only for processors points
Definition: meshSurfaceEngineI.H:431
Foam::polyMeshGenModifier::facesAccess
faceListPMG & facesAccess()
access to mesh faces
Definition: polyMeshGenModifier.H:113
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::faceListPMG
Definition: faceListPMG.H:50
Foam::pointFieldPMG
Definition: pointFieldPMG.H:50
Foam::VRWGraph
Definition: VRWGraph.H:101
Foam::labelLongList
LongList< label > labelLongList
Definition: labelLongList.H:46
polyMeshGenAddressing.H
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::DynList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: DynListI.H:279
Foam::meshSurfaceEngine
Definition: meshSurfaceEngine.H:54
Foam::polyMeshGenModifier::removeCells
void removeCells(const boolList &removeCell, const bool removeProcFaces=true)
remove cells
Definition: polyMeshGenModifierRemoveCells.C:41
Foam::DynList::append
void append(const T &e)
Append an element at the end of the list.
Definition: DynListI.H:304
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190