26 #include "checkTopology.H"
37 #include "checkTools.H"
44 const bool allTopology,
45 const bool allGeometry,
46 const autoPtr<surfaceWriter>& writer
49 label noFailedChecks = 0;
51 Info<<
"Checking topology..." <<
endl;
54 mesh.boundaryMesh().checkDefinition(
true);
61 if (isA<emptyPolyPatch>(
mesh.boundaryMesh()[patchI]))
63 nEmpty +=
mesh.boundaryMesh()[patchI].size();
66 reduce(nEmpty, sumOp<label>());
70 if (nTotCells && (nEmpty % nTotCells))
72 Info<<
" ***Total number of faces on empty patches"
73 <<
" is not divisible by the number of cells in the mesh."
74 <<
" Hence this mesh is not 1D or 2D."
80 mesh.boundaryMesh().checkParallelSync(
true);
83 mesh.cellZones().checkDefinition(
true);
84 if (
mesh.cellZones().checkParallelSync(
true))
88 mesh.faceZones().checkDefinition(
true);
89 if (
mesh.faceZones().checkParallelSync(
true))
93 mesh.pointZones().checkDefinition(
true);
94 if (
mesh.pointZones().checkParallelSync(
true))
105 const cell& cFaces =
mesh.cells()[cellI];
107 if (cFaces.size() <= 3)
113 if (cFaces[i] < 0 || cFaces[i] >=
mesh.nFaces())
124 Info<<
" Illegal cells (less than 4 faces or out of range faces)"
125 <<
" found, number of cells: " << nCells <<
endl;
128 Info<<
" <<Writing " << nCells
129 <<
" illegal cells to set " <<
cells.name() <<
endl;
130 cells.instance() =
mesh.pointsInstance();
140 Info<<
" Cell to face addressing OK." <<
endl;
154 <<
" unused points to set " <<
points.name() <<
endl;
161 faceSet faces(
mesh,
"upperTriangularFace",
mesh.nFaces()/100);
162 if (
mesh.checkUpperTriangular(
true, &faces))
171 Info<<
" <<Writing " << nFaces
172 <<
" unordered faces to set " << faces.name() <<
endl;
173 faces.instance() =
mesh.pointsInstance();
183 faceSet faces(
mesh,
"outOfRangeFaces",
mesh.nFaces()/100);
184 if (
mesh.checkFaceVertices(
true, &faces))
190 Info<<
" <<Writing " << nFaces
191 <<
" faces with out-of-range or duplicate vertices to set "
192 << faces.name() <<
endl;
193 faces.instance() =
mesh.pointsInstance();
211 Info<<
" <<Writing " << nCells
212 <<
" cells with over used edges to set " <<
cells.name()
214 cells.instance() =
mesh.pointsInstance();
226 faceSet faces(
mesh,
"edgeFaces",
mesh.nFaces()/100);
227 if (
mesh.checkFaceFaces(
true, &faces))
235 Info<<
" <<Writing " << nFaces
236 <<
" faces with non-standard edge connectivity to set "
237 << faces.name() <<
endl;
238 faces.instance() =
mesh.pointsInstance();
251 for (
label faceI = 0; faceI <
mesh.nInternalFaces(); faceI++)
253 nInternalFaces[
mesh.faceOwner()[faceI]]++;
254 nInternalFaces[
mesh.faceNeighbour()[faceI]]++;
256 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
265 nInternalFaces[owners[i]]++;
270 cellSet oneCells(
mesh,
"oneInternalFaceCells",
mesh.nCells()/100);
271 cellSet twoCells(
mesh,
"twoInternalFacesCells",
mesh.nCells()/100);
273 forAll(nInternalFaces, cellI)
275 if (nInternalFaces[cellI] <= 1)
277 oneCells.insert(cellI);
279 else if (nInternalFaces[cellI] == 2)
281 twoCells.insert(cellI);
289 Info<<
" <<Writing " << nOneCells
290 <<
" cells with zero or one non-boundary face to set "
293 oneCells.instance() =
mesh.pointsInstance();
305 Info<<
" <<Writing " << nTwoCells
306 <<
" cells with two non-boundary faces to set "
309 twoCells.instance() =
mesh.pointsInstance();
319 regionSplit rs(
mesh);
321 if (rs.nRegions() <= 1)
323 Info<<
" Number of regions: " << rs.nRegions() <<
" (OK)."
329 Info<<
" *Number of regions: " << rs.nRegions() <<
endl;
331 Info<<
" The mesh has multiple regions which are not connected "
332 "by any face." <<
endl
333 <<
" <<Writing region information to "
334 <<
mesh.time().timeName()/
"cellToRegion"
342 mesh.time().timeName(),
354 boolList regionDisconnected(rs.nRegions(),
true);
365 faceI <
mesh.nFaces();
369 label regionI = rs[
mesh.faceOwner()[faceI]];
370 const face&
f =
mesh.faces()[faceI];
373 label& pRegion = pointToRegion[
f[fp]];
378 else if (pRegion == -2)
381 regionDisconnected[regionI] =
false;
383 else if (pRegion != regionI)
386 regionDisconnected[regionI] =
false;
387 regionDisconnected[pRegion] =
false;
393 Pstream::listCombineGather(regionDisconnected, andEqOp<bool>());
394 Pstream::listCombineScatter(regionDisconnected);
400 PtrList<cellSet> cellRegions(rs.nRegions());
401 for (
label i = 0; i < rs.nRegions(); i++)
417 cellRegions[rs[i]].insert(i);
420 for (
label i = 0; i < rs.nRegions(); i++)
422 Info<<
" <<Writing region " << i;
425 if (regionDisconnected[i])
427 Info<<
" (fully disconnected)";
431 Info<<
" (point connected)";
436 <<
" cells to cellSet " << cellRegions[i].name() <<
endl;
438 cellRegions[i].
write();
445 if (!Pstream::parRun())
447 Info<<
"\nChecking patch topology for multiply connected"
448 <<
" surfaces..." <<
endl;
452 Info<<
"\nChecking basic patch addressing..." <<
endl;
456 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
469 <<
setw(20) <<
"Patch"
470 <<
setw(9) <<
"Faces"
471 <<
setw(9) <<
"Points";
472 if (!Pstream::parRun())
474 Info<<
setw(34) <<
"Surface topology";
478 Info<<
" Bounding box";
484 const polyPatch& pp =
patches[patchI];
486 if (!isA<processorPolyPatch>(pp))
489 <<
setw(20) << pp.name()
493 if (!Pstream::parRun())
495 primitivePatch::surfaceTopo pTyp = pp.surfaceType();
501 else if (pTyp == primitivePatch::MANIFOLD)
503 if (pp.checkPointManifold(
true, &
points))
506 <<
"multiply connected (shared point)";
510 Info<<
setw(34) <<
"ok (closed singly connected)";
514 pp.checkTopology(
false, &
points);
518 pp.checkTopology(
false, &
points);
520 if (pTyp == primitivePatch::OPEN)
523 <<
"ok (non-closed singly connected)";
528 <<
"multiply connected (shared edge)";
543 bb.min() =
min(bb.min(), pts[
mp[i]]);
544 bb.max() =
max(bb.max(), pts[
mp[i]]);
546 reduce(bb.min(), minOp<vector>());
547 reduce(bb.max(), maxOp<vector>());
558 <<
" conflicting points to set "
577 mesh.faceNeighbour();
588 return noFailedChecks;