FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

checkTopology.C

Go to the documentation of this file.
00001 #include "checkTopology.H"
00002 #include <OpenFOAM/polyMesh.H>
00003 #include <OpenFOAM/Time.H>
00004 #include <meshTools/regionSplit.H>
00005 #include <meshTools/cellSet.H>
00006 #include <meshTools/faceSet.H>
00007 #include <meshTools/pointSet.H>
00008 #include <OpenFOAM/IOmanip.H>
00009 
00010 bool Foam::checkSync(const wordList& names)
00011 {
00012     List<wordList> allNames(Pstream::nProcs());
00013     allNames[Pstream::myProcNo()] = names;
00014     Pstream::gatherList(allNames);
00015     Pstream::scatterList(allNames);
00016 
00017     bool hasError = false;
00018 
00019     for (label procI = 1; procI < allNames.size(); procI++)
00020     {
00021         if (allNames[procI] != allNames[0])
00022         {
00023             hasError = true;
00024 
00025             Info<< " ***Inconsistent zones across processors, "
00026                    "processor 0 has zones:" << allNames[0]
00027                 << ", processor " << procI << " has zones:"
00028                 << allNames[procI]
00029                 << endl;
00030         }
00031     }
00032     return hasError;
00033 }
00034 
00035 
00036 Foam::label Foam::checkTopology
00037 (
00038     const polyMesh& mesh,
00039     const bool allTopology,
00040     const bool allGeometry
00041 )
00042 {
00043     label noFailedChecks = 0;
00044 
00045     Info<< "Checking topology..." << endl;
00046 
00047     // Check if the boundary definition is unique
00048     mesh.boundaryMesh().checkDefinition(true);
00049 
00050     // Check if the boundary processor patches are correct
00051     mesh.boundaryMesh().checkParallelSync(true);
00052 
00053     // Check names of zones are equal
00054     if (checkSync(mesh.cellZones().names()))
00055     {
00056         noFailedChecks++;
00057     }
00058     if (checkSync(mesh.faceZones().names()))
00059     {
00060         noFailedChecks++;
00061     }
00062     if (checkSync(mesh.pointZones().names()))
00063     {
00064         noFailedChecks++;
00065     }
00066 
00067     // Check contents of faceZones consistent
00068     {
00069         forAll(mesh.faceZones(), zoneI)
00070         {
00071             if (mesh.faceZones()[zoneI].checkParallelSync(false))
00072             {
00073                 Info<< " ***FaceZone " << mesh.faceZones()[zoneI].name()
00074                     << " is not correctly synchronised"
00075                     << " across coupled boundaries."
00076                     << " (coupled faces are either not both "
00077                     << " present in set or have same flipmap)" << endl;
00078                 noFailedChecks++;
00079             }
00080         }
00081     }
00082 
00083     {
00084         pointSet points(mesh, "unusedPoints", mesh.nPoints()/100);
00085         if (mesh.checkPoints(true, &points))
00086         {
00087             noFailedChecks++;
00088 
00089             label nPoints = returnReduce(points.size(), sumOp<label>());
00090 
00091             Info<< "  <<Writing " << nPoints
00092                 << " unused points to set " << points.name() << endl;
00093             points.write();
00094         }
00095     }
00096 
00097     {
00098         faceSet faces(mesh, "upperTriangularFace", mesh.nFaces()/100);
00099         if (mesh.checkUpperTriangular(true, &faces))
00100         {
00101             noFailedChecks++;
00102         }
00103 
00104         label nFaces = returnReduce(faces.size(), sumOp<label>());
00105 
00106         if (nFaces > 0)
00107         {
00108             Info<< "  <<Writing " << nFaces
00109                 << " unordered faces to set " << faces.name() << endl;
00110             faces.write();
00111         }
00112     }
00113 
00114     if (allTopology)
00115     {
00116         cellSet cells(mesh, "zipUpCells", mesh.nCells()/100);
00117         if (mesh.checkCellsZipUp(true, &cells))
00118         {
00119             noFailedChecks++;
00120 
00121             label nCells = returnReduce(cells.size(), sumOp<label>());
00122 
00123             Info<< "  <<Writing " << nCells
00124                 << " cells with over used edges to set " << cells.name()
00125                 << endl;
00126             cells.write();
00127         }
00128     }
00129 
00130     {
00131         faceSet faces(mesh, "outOfRangeFaces", mesh.nFaces()/100);
00132         if (mesh.checkFaceVertices(true, &faces))
00133         {
00134             noFailedChecks++;
00135 
00136             label nFaces = returnReduce(faces.size(), sumOp<label>());
00137 
00138             Info<< "  <<Writing " << nFaces
00139                 << " faces with out-of-range or duplicate vertices to set "
00140                 << faces.name() << endl;
00141             faces.write();
00142         }
00143     }
00144 
00145     if (allTopology)
00146     {
00147         faceSet faces(mesh, "edgeFaces", mesh.nFaces()/100);
00148         if (mesh.checkFaceFaces(true, &faces))
00149         {
00150             noFailedChecks++;
00151 
00152             label nFaces = returnReduce(faces.size(), sumOp<label>());
00153 
00154             Info<< "  <<Writing " << nFaces
00155                 << " faces with incorrect edges to set " << faces.name()
00156                 << endl;
00157             faces.write();
00158         }
00159     }
00160 
00161     if (allTopology)
00162     {
00163         labelList nInternalFaces(mesh.nCells(), 0);
00164 
00165         for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
00166         {
00167             nInternalFaces[mesh.faceOwner()[faceI]]++;
00168             nInternalFaces[mesh.faceNeighbour()[faceI]]++;
00169         }
00170         const polyBoundaryMesh& patches = mesh.boundaryMesh();
00171         forAll(patches, patchI)
00172         {
00173             if (patches[patchI].coupled())
00174             {
00175                 const unallocLabelList& owners = patches[patchI].faceCells();
00176 
00177                 forAll(owners, i)
00178                 {
00179                     nInternalFaces[owners[i]]++;
00180                 }
00181             }
00182         }
00183 
00184         cellSet oneCells(mesh, "oneInternalFaceCells", mesh.nCells()/100);
00185         cellSet twoCells(mesh, "twoInternalFacesCells", mesh.nCells()/100);
00186 
00187         forAll(nInternalFaces, cellI)
00188         {
00189             if (nInternalFaces[cellI] <= 1)
00190             {
00191                 oneCells.insert(cellI);
00192             }
00193             else if (nInternalFaces[cellI] == 2)
00194             {
00195                 twoCells.insert(cellI);
00196             }
00197         }
00198 
00199         label nOneCells = returnReduce(oneCells.size(), sumOp<label>());
00200 
00201         if (nOneCells > 0)
00202         {
00203             Info<< "  <<Writing " << nOneCells
00204                 << " cells with with single non-boundary face to set "
00205                 << oneCells.name()
00206                 << endl;
00207             oneCells.write();
00208         }
00209 
00210         label nTwoCells = returnReduce(twoCells.size(), sumOp<label>());
00211 
00212         if (nTwoCells > 0)
00213         {
00214             Info<< "  <<Writing " << nTwoCells
00215                 << " cells with with single non-boundary face to set "
00216                 << twoCells.name()
00217                 << endl;
00218             twoCells.write();
00219         }
00220     }
00221 
00222     {
00223         regionSplit rs(mesh);
00224 
00225         if (rs.nRegions() == 1)
00226         {
00227             Info<< "    Number of regions: " << rs.nRegions() << " (OK)."
00228                 << endl;
00229 
00230         }
00231         else
00232         {
00233             Info<< "   *Number of regions: " << rs.nRegions() << endl;
00234 
00235             Info<< "    The mesh has multiple regions which are not connected "
00236                    "by any face." << endl
00237                 << "  <<Writing region information to "
00238                 << mesh.time().timeName()/"cellToRegion"
00239                 << endl;
00240 
00241             labelIOList ctr
00242             (
00243                 IOobject
00244                 (
00245                     "cellToRegion",
00246                     mesh.time().timeName(),
00247                     mesh,
00248                     IOobject::NO_READ,
00249                     IOobject::NO_WRITE
00250                 ),
00251                 rs
00252             );
00253             ctr.write();
00254         }
00255     }
00256 
00257     if (!Pstream::parRun())
00258     {
00259         Pout<< "\nChecking patch topology for multiply connected surfaces ..."
00260             << endl;
00261 
00262         const polyBoundaryMesh& patches = mesh.boundaryMesh();
00263 
00264         // Non-manifold points
00265         pointSet points
00266         (
00267             mesh,
00268             "nonManifoldPoints",
00269             mesh.nPoints()/100
00270         );
00271 
00272         Pout.setf(ios_base::left);
00273 
00274         Pout<< "    "
00275             << setw(20) << "Patch"
00276             << setw(9) << "Faces"
00277             << setw(9) << "Points"
00278             << setw(34) << "Surface topology";
00279         if (allGeometry)
00280         {
00281             Pout<< " Bounding box";
00282         }
00283         Pout<< endl;
00284 
00285         forAll(patches, patchI)
00286         {
00287             const polyPatch& pp = patches[patchI];
00288 
00289                 Pout<< "    "
00290                     << setw(20) << pp.name()
00291                     << setw(9) << pp.size()
00292                     << setw(9) << pp.nPoints();
00293 
00294 
00295             primitivePatch::surfaceTopo pTyp = pp.surfaceType();
00296 
00297             if (pp.empty())
00298             {
00299                 Pout<< setw(34) << "ok (empty)";
00300             }
00301             else if (pTyp == primitivePatch::MANIFOLD)
00302             {
00303                 if (pp.checkPointManifold(true, &points))
00304                 {
00305                     Pout<< setw(34) << "multiply connected (shared point)";
00306                 }
00307                 else
00308                 {
00309                     Pout<< setw(34) << "ok (closed singly connected)";
00310                 }
00311 
00312                 // Add points on non-manifold edges to make set complete
00313                 pp.checkTopology(false, &points);
00314             }
00315             else
00316             {
00317                 pp.checkTopology(false, &points);
00318 
00319                 if (pTyp == primitivePatch::OPEN)
00320                 {
00321                     Pout<< setw(34) << "ok (non-closed singly connected)";
00322                 }
00323                 else
00324                 {
00325                     Pout<< setw(34) << "multiply connected (shared edge)";
00326                 }
00327             }
00328 
00329             if (allGeometry)
00330             {
00331                 const pointField& pts = pp.points();
00332                 const labelList& mp = pp.meshPoints();
00333 
00334                 if (returnReduce(mp.size(), sumOp<label>()) > 0)
00335                 {
00336                     boundBox bb(point::max, point::min);
00337                     forAll(mp, i)
00338                     {
00339                         bb.min() = min(bb.min(), pts[mp[i]]);
00340                         bb.max() = max(bb.max(), pts[mp[i]]);
00341                     }
00342                     reduce(bb.min(), minOp<vector>());
00343                     reduce(bb.max(), maxOp<vector>());
00344                     Pout<< ' ' << bb;
00345                 }
00346             }
00347             Pout<< endl;
00348         }
00349 
00350         if (points.size())
00351         {
00352             Pout<< "  <<Writing " << points.size()
00353                 << " conflicting points to set "
00354                 << points.name() << endl;
00355 
00356             points.write();
00357         }
00358 
00359         //Pout.setf(ios_base::right);
00360     }
00361 
00362     // Force creation of all addressing if requested.
00363     // Errors will be reported as required
00364     if (allTopology)
00365     {
00366         mesh.cells();
00367         mesh.faces();
00368         mesh.edges();
00369         mesh.points();
00370         mesh.faceOwner();
00371         mesh.faceNeighbour();
00372         mesh.cellCells();
00373         mesh.edgeCells();
00374         mesh.pointCells();
00375         mesh.edgeFaces();
00376         mesh.pointFaces();
00377         mesh.cellEdges();
00378         mesh.faceEdges();
00379         mesh.pointEdges();
00380     }
00381 
00382     return noFailedChecks;
00383 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines