1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Copyright held by the original author
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "polyMeshGenChecks.H"
27 #include "polyMeshGenAddressing.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 namespace polyMeshGenChecks
47 const polyMeshGen& mesh,
52 label nFaceErrors = 0;
53 label nCellErrors = 0;
55 const VRWGraph& pf = mesh.addressingData().pointFaces();
59 if( pf.sizeOfRow(pointI) == 0 )
64 "(const polyMeshGen&, const bool, labelHashSet*)"
65 ) << "Point " << pointI << " not used by any faces." << endl;
68 setPtr->insert(pointI);
74 const VRWGraph& pc = mesh.addressingData().pointCells();
78 if( pc.sizeOfRow(pointI) == 0 )
83 "(const polyMeshGen&, const bool, labelHashSet*)"
84 ) << "Point " << pointI << " not used by any cells." << endl;
87 setPtr->insert(pointI);
93 reduce(nFaceErrors, sumOp<label>());
94 reduce(nCellErrors, sumOp<label>());
96 if( nFaceErrors > 0 || nCellErrors > 0 )
101 "(const polyMeshGen&, const bool, labelHashSet*)"
102 ) << "Error in point usage detected: " << nFaceErrors
103 << " unused points found in the mesh. This mesh is invalid."
111 Info << "Point usage check OK.\n" << endl;
117 bool checkUpperTriangular
119 const polyMeshGen& mesh,
124 // Check whether internal faces are ordered in the upper triangular order
125 const labelList& own = mesh.owner();
126 const labelList& nei = mesh.neighbour();
128 const cellListPMG& cells = mesh.cells();
129 const VRWGraph& cc = mesh.addressingData().cellCells();
131 const label internal = mesh.nInternalFaces();
133 labelList checkInternalFaces(internal, -1);
139 // Loop through faceCells once more and make sure that for internal cell
140 // the first label is smaller
141 for(label faceI=0;faceI<internal;++faceI)
143 if( own[faceI] >= nei[faceI] )
147 Pout<< "bool checkUpperTriangular(const polyMeshGen&, "
148 << "const bool, labelHashSet*) : " << endl
150 << " has the owner label greater than neighbour:" << endl
151 << own[faceI] << tab << nei[faceI] << endl;
155 setPtr->insert(faceI);
161 // Loop through all cells. For each cell, find the face that is internal and
162 // add it to the check list (upper triangular order).
163 // Once the list is completed, check it against the faceCell list
166 const labelList& curFaces = cells[cellI];
168 // Using the fact that cell neighbour always appear
169 // in the increasing order
170 boolList usedNbr(cc.sizeOfRow(cellI), false);
172 for(label nSweeps=0;nSweeps<usedNbr.size();++nSweeps)
174 // Find the lowest neighbour which is still valid
176 label minNei = cells.size();
178 forAllRow(cc, cellI, nbrI)
180 const label neiI = cc(cellI, nbrI);
181 if( (neiI > cellI) && !usedNbr[nbrI] && (neiI < minNei) )
190 // Mark this neighbour as used
191 usedNbr[nextNei] = true;
193 forAll(curFaces, faceI)
195 if( curFaces[faceI] < internal )
197 if( nei[curFaces[faceI]] == cc(cellI, nextNei) )
199 checkInternalFaces[nChecks] = curFaces[faceI];
210 // Check list created. If everything is OK, the face label is equal to index
211 forAll(checkInternalFaces, faceI)
213 if( checkInternalFaces[faceI] != faceI )
217 Pout<< "bool checkUpperTriangular(const polyMeshGen&, const bool"
218 << ", labelHashSet*) : " << endl
219 << "face " << faceI << " out of position. Markup label: "
220 << checkInternalFaces[faceI] << ". All subsequent faces will "
221 << "also be out of position. Please check the mesh manually."
225 setPtr->insert(faceI);
231 reduce(error, orOp<bool>());
237 "bool checkUpperTriangular(const polyMeshGen&, const bool"
239 ) << "Error in face ordering: faces not in upper triangular order!"
247 Info<< "Upper triangular ordering OK.\n" << endl;
255 const polyMeshGen& mesh,
260 label nOpenCells = 0;
262 const faceListPMG& faces = mesh.faces();
263 const cellListPMG& cells = mesh.cells();
266 # pragma omp parallel for schedule(guided) reduction(+ : nOpenCells)
270 const labelList& c = cells[cellI];
272 DynList<edge> cellEdges;
273 DynList<label> edgeUsage;
277 const face& f = faces[c[faceI]];
281 const edge e = f.faceEdge(eI);
283 const label pos = cellEdges.containsAtPosition(e);
297 DynList<edge> singleEdges;
299 forAll(edgeUsage, edgeI)
301 if( edgeUsage[edgeI] == 1 )
303 singleEdges.append(cellEdges[edgeI]);
305 else if( edgeUsage[edgeI] != 2 )
309 "bool checkCellsZipUp(const polyMeshGen&,"
310 "const bool, labelHashSet*)"
311 ) << "edge " << cellEdges[edgeI] << " in cell " << cellI
312 << " used " << edgeUsage[edgeI] << " times. " << endl
313 << "Should be 1 or 2 - serious error in mesh structure"
319 # pragma omp critical
321 setPtr->insert(cellI);
326 if( singleEdges.size() > 0 )
330 Pout<< "bool checkCellsZipUp(const polyMeshGen&, const bool"
331 << ", labelHashSet*) : " << endl
332 << "Cell " << cellI << " has got " << singleEdges.size()
333 << " unmatched edges: " << singleEdges << endl;
339 # pragma omp critical
341 setPtr->insert(cellI);
348 reduce(nOpenCells, sumOp<label>());
354 "bool checkCellsZipUp(const polyMeshGen&,"
355 " const bool, labelHashSet*)"
357 << " open cells found. Please use the mesh zip-up tool. "
365 Info<< "Topological cell zip-up check OK.\n" << endl;
371 // Vertices of face within point range and unique.
372 bool checkFaceVertices
374 const polyMeshGen& mesh,
379 // Check that all vertex labels are valid
380 const faceListPMG& faces = mesh.faces();
382 label nErrorFaces = 0;
383 const label nPoints = mesh.points().size();
387 const face& curFace = faces[fI];
389 if( min(curFace) < 0 || max(curFace) > nPoints )
393 "bool checkFaceVertices("
394 "const polyMesgGen&, const bool, labelHashSet*)"
395 ) << "Face " << fI << " contains vertex labels out of range: "
396 << curFace << " Max point index = " << nPoints-1 << endl;
404 // Uniqueness of vertices
405 labelHashSet facePoints(2*curFace.size());
409 bool inserted = facePoints.insert(curFace[fp]);
415 "bool checkFaceVertices("
416 "const polyMeshGen&, const bool, labelHashSet*)"
417 ) << "Face " << fI << " contains duplicate vertex labels: "
428 reduce(nErrorFaces, sumOp<label>());
430 if( nErrorFaces > 0 )
434 "bool checkFaceVertices("
435 "const polyMeshGen&, const bool, labelHashSet*)"
436 ) << "const bool, labelHashSet*) const: "
437 << nErrorFaces << " faces with invalid vertex labels found"
445 Info<< "Face vertices OK.\n" << endl;
451 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
453 } // End namespace polyMeshGenChecks
455 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
457 } // End namespace Foam
459 // ************************************************************************* //