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

checkGeometry.C

Go to the documentation of this file.
00001 #include "checkGeometry.H"
00002 #include <OpenFOAM/polyMesh.H>
00003 #include <meshTools/cellSet.H>
00004 #include <meshTools/faceSet.H>
00005 #include <meshTools/pointSet.H>
00006 #include <OpenFOAM/EdgeMap.H>
00007 #include <OpenFOAM/wedgePolyPatch.H>
00008 #include <OpenFOAM/mathematicalConstants.H>
00009 
00010 
00011 // Find wedge with opposite orientation. Note: does not actually check that
00012 // it is opposite, only that it has opposite normal and same axis
00013 Foam::label Foam::findOppositeWedge
00014 (
00015     const polyMesh& mesh,
00016     const wedgePolyPatch& wpp
00017 )
00018 {
00019     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00020 
00021     scalar wppCosAngle = wpp.centreNormal()&wpp.patchNormal();
00022 
00023     forAll(patches, patchI)
00024     {
00025         if
00026         (
00027             patchI != wpp.index()
00028          && patches[patchI].size()
00029          && isA<wedgePolyPatch>(patches[patchI])
00030         )
00031         {
00032             const wedgePolyPatch& pp = refCast<const wedgePolyPatch>
00033             (
00034                 patches[patchI]
00035             );
00036 
00037             // Calculate (cos of) angle to wpp (not pp!) centre normal
00038             scalar ppCosAngle = wpp.centreNormal()&pp.patchNormal();
00039 
00040             if
00041             (
00042                 pp.size() == wpp.size()
00043              && mag(pp.axis() & wpp.axis()) >= (1-1E-3)
00044              && mag(ppCosAngle - wppCosAngle) >= 1E-3
00045             )
00046             {
00047                 return patchI;
00048             }
00049         }
00050     }
00051     return -1;
00052 }
00053 
00054 
00055 bool Foam::checkWedges
00056 (
00057     const polyMesh& mesh,
00058     const bool report,
00059     const Vector<label>& directions,
00060     labelHashSet* setPtr
00061 )
00062 {
00063     // To mark edges without calculating edge addressing
00064     EdgeMap<label> edgesInError;
00065 
00066     const pointField& p = mesh.points();
00067     const faceList& fcs = mesh.faces();
00068 
00069 
00070     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00071     forAll(patches, patchI)
00072     {
00073         if (patches[patchI].size() && isA<wedgePolyPatch>(patches[patchI]))
00074         {
00075             const wedgePolyPatch& pp = refCast<const wedgePolyPatch>
00076             (
00077                 patches[patchI]
00078             );
00079 
00080             scalar wedgeAngle = acos(pp.centreNormal()&pp.patchNormal());
00081 
00082             if (report)
00083             {
00084                 Info<< "    Wedge " << pp.name() << " with angle "
00085                     << 180/mathematicalConstant::pi*wedgeAngle << " degrees"
00086                     << endl;                
00087             }
00088 
00089             // Find opposite
00090             label oppositePatchI = findOppositeWedge(mesh, pp);
00091 
00092             if (oppositePatchI == -1)
00093             {
00094                 if (report)
00095                 {
00096                     Info<< " ***Cannot find opposite wedge for wedge "
00097                         << pp.name() << endl;
00098                 }
00099                 return true;
00100             }
00101 
00102             const wedgePolyPatch& opp = refCast<const wedgePolyPatch>
00103             (
00104                 patches[oppositePatchI]
00105             );
00106 
00107 
00108             if (mag(opp.axis() & pp.axis()) < (1-1E-3))
00109             {
00110                 if (report)
00111                 {
00112                     Info<< " ***Wedges do not have the same axis."
00113                         << " Encountered " << pp.axis()
00114                         << " on patch " << pp.name()
00115                         << " which differs from " << opp.axis()
00116                         << " on opposite wedge patch" << opp.axis()
00117                         << endl;
00118                 }
00119                 return true;
00120             }
00121 
00122 
00123 
00124             // Mark edges on wedgePatches
00125             forAll(pp, i)
00126             {
00127                 const face& f = pp[i];
00128                 forAll(f, fp)
00129                 {
00130                     label p0 = f[fp];
00131                     label p1 = f.nextLabel(fp);
00132                     edgesInError.insert(edge(p0, p1), -1);  // non-error value
00133                 }
00134             }
00135 
00136 
00137             // Check that wedge patch is flat
00138             const point& p0 = p[pp.meshPoints()[0]];
00139             forAll(pp.meshPoints(), i)
00140             {
00141                 const point& pt = p[pp.meshPoints()[i]];
00142                 scalar d = mag((pt-p0) & pp.patchNormal());
00143 
00144                 if (d > sqrt(SMALL))
00145                 {
00146                     if (report)
00147                     {
00148                         Info<< " ***Wedge patch " << pp.name() << " not planar."
00149                             << " Point " << pt << " is not in patch plane by "
00150                             << d << " meter."
00151                             << endl;
00152                     }
00153                     return true;
00154                 }
00155             }
00156         }
00157     }
00158 
00159 
00160 
00161     // Check all non-wedge faces
00162     label nEdgesInError = 0;
00163 
00164     forAll(fcs, faceI)
00165     {
00166         const face& f = fcs[faceI];
00167 
00168         forAll(f, fp)
00169         {
00170             label p0 = f[fp];
00171             label p1 = f.nextLabel(fp);
00172             if (p0 < p1)
00173             {
00174                 vector d(p[p1]-p[p0]);
00175                 scalar magD = mag(d);
00176 
00177                 if (magD > ROOTVSMALL)
00178                 {
00179                     d /= magD;
00180 
00181                     // Check how many empty directions are used by the edge.
00182                     label nEmptyDirs = 0;
00183                     label nNonEmptyDirs = 0;
00184                     for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
00185                     {
00186                         if (mag(d[cmpt]) > 1e-6)
00187                         {
00188                             if (directions[cmpt] == 0)
00189                             {
00190                                 nEmptyDirs++;
00191                             }
00192                             else
00193                             {
00194                                 nNonEmptyDirs++;
00195                             }
00196                         }
00197                     }
00198 
00199                     if (nEmptyDirs == 0)
00200                     {
00201                         // Purely in ok directions.
00202                     }
00203                     else if (nEmptyDirs == 1)
00204                     {
00205                         // Ok if purely in empty directions.
00206                         if (nNonEmptyDirs > 0)
00207                         {
00208                             if (edgesInError.insert(edge(p0, p1), faceI))
00209                             {
00210                                 nEdgesInError++;
00211                             }
00212                         }
00213                     }
00214                     else if (nEmptyDirs > 1)
00215                     {
00216                         // Always an error
00217                         if (edgesInError.insert(edge(p0, p1), faceI))
00218                         {
00219                             nEdgesInError++;
00220                         }
00221                     }
00222                 }
00223             }
00224         }
00225     }
00226 
00227     label nErrorEdges = returnReduce(nEdgesInError, sumOp<label>());
00228 
00229     if (nErrorEdges > 0)
00230     {
00231         if (report)
00232         {
00233             Info<< " ***Number of edges not aligned with or perpendicular to "
00234                 << "non-empty directions: " << nErrorEdges << endl;
00235         }
00236 
00237         if (setPtr)
00238         {
00239             setPtr->resize(2*nEdgesInError);
00240             forAllConstIter(EdgeMap<label>, edgesInError, iter)
00241             {
00242                 if (iter() >= 0)
00243                 {
00244                     setPtr->insert(iter.key()[0]);
00245                     setPtr->insert(iter.key()[1]);
00246                 }
00247             }
00248         }
00249 
00250         return true;
00251     }
00252     else
00253     {
00254         if (report)
00255         {
00256             Info<< "    All edges aligned with or perpendicular to "
00257                 << "non-empty directions." << endl;
00258         }
00259         return false;
00260     }
00261 }
00262 
00263 
00264 Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry)
00265 {
00266     label noFailedChecks = 0;
00267 
00268     Info<< "\nChecking geometry..." << endl;
00269 
00270     // Get a small relative length from the bounding box
00271     const boundBox& globalBb = mesh.bounds();
00272 
00273     Info<< "    Overall domain bounding box "
00274         << globalBb.min() << " " << globalBb.max() << endl;
00275 
00276 
00277     // Min length
00278     scalar minDistSqr = magSqr(1e-6 * globalBb.span());
00279 
00280     // Non-empty directions
00281     const Vector<label> validDirs = (mesh.geometricD() + Vector<label>::one)/2;
00282     Info<< "    Mesh (non-empty, non-wedge) directions " << validDirs << endl;
00283 
00284     const Vector<label> solDirs = (mesh.solutionD() + Vector<label>::one)/2;
00285     Info<< "    Mesh (non-empty) directions " << solDirs << endl;
00286 
00287     if (mesh.nGeometricD() < 3)
00288     {
00289         pointSet nonAlignedPoints(mesh, "nonAlignedEdges", mesh.nPoints()/100);
00290 
00291         if
00292         (
00293             (
00294                 validDirs != solDirs
00295              && checkWedges(mesh, true, validDirs, &nonAlignedPoints)
00296             )
00297          || (
00298                 validDirs == solDirs
00299              && mesh.checkEdgeAlignment(true, validDirs, &nonAlignedPoints)
00300             )
00301         )
00302         {
00303             noFailedChecks++;
00304             label nNonAligned = returnReduce
00305             (
00306                 nonAlignedPoints.size(),
00307                 sumOp<label>()
00308             );
00309 
00310             if (nNonAligned > 0)
00311             {
00312                 Info<< "  <<Writing " << nNonAligned
00313                     << " points on non-aligned edges to set "
00314                     << nonAlignedPoints.name() << endl;
00315                 nonAlignedPoints.write();
00316             }
00317         }
00318     }
00319 
00320     if (mesh.checkClosedBoundary(true)) noFailedChecks++;
00321 
00322     {
00323         cellSet cells(mesh, "nonClosedCells", mesh.nCells()/100+1);
00324         cellSet aspectCells(mesh, "highAspectRatioCells", mesh.nCells()/100+1);
00325         if
00326         (
00327             mesh.checkClosedCells
00328             (
00329                 true,
00330                 &cells,
00331                 &aspectCells,
00332                 mesh.geometricD()
00333             )
00334         )
00335         {
00336             noFailedChecks++;
00337 
00338             label nNonClosed = returnReduce(cells.size(), sumOp<label>());
00339 
00340             if (nNonClosed > 0)
00341             {
00342                 Info<< "  <<Writing " << nNonClosed
00343                     << " non closed cells to set " << cells.name() << endl;
00344                 cells.write();
00345             }
00346         }
00347 
00348         label nHighAspect = returnReduce(aspectCells.size(), sumOp<label>());
00349 
00350         if (nHighAspect > 0)
00351         {
00352             Info<< "  <<Writing " << nHighAspect
00353                 << " cells with high aspect ratio to set "
00354                 << aspectCells.name() << endl;
00355             aspectCells.write();
00356         }
00357     }
00358 
00359     {
00360         faceSet faces(mesh, "zeroAreaFaces", mesh.nFaces()/100 + 1);
00361         if (mesh.checkFaceAreas(true, &faces))
00362         {
00363             noFailedChecks++;
00364 
00365             label nFaces = returnReduce(faces.size(), sumOp<label>());
00366 
00367             if (nFaces > 0)
00368             {
00369                 Info<< "  <<Writing " << nFaces
00370                     << " zero area faces to set " << faces.name() << endl;
00371                 faces.write();
00372             }
00373         }
00374     }
00375 
00376     {
00377         cellSet cells(mesh, "zeroVolumeCells", mesh.nCells()/100 + 1);
00378         if (mesh.checkCellVolumes(true, &cells))
00379         {
00380             noFailedChecks++;
00381 
00382             label nCells = returnReduce(cells.size(), sumOp<label>());
00383 
00384             if (nCells > 0)
00385             {
00386                 Info<< "  <<Writing " << nCells
00387                     << " zero volume cells to set " << cells.name() << endl;
00388                 cells.write();
00389             }
00390         }
00391     }
00392 
00393     {
00394         faceSet faces(mesh, "nonOrthoFaces", mesh.nFaces()/100 + 1);
00395         if (mesh.checkFaceOrthogonality(true, &faces))
00396         {
00397             noFailedChecks++;
00398         }
00399 
00400         label nFaces = returnReduce(faces.size(), sumOp<label>());
00401 
00402         if (nFaces > 0)
00403         {
00404             Info<< "  <<Writing " << nFaces
00405                 << " non-orthogonal faces to set " << faces.name() << endl;
00406             faces.write();
00407         }
00408     }
00409 
00410 
00411     {
00412         faceSet faces(mesh, "wrongOrientedFaces", mesh.nFaces()/100 + 1);
00413         if (mesh.checkFacePyramids(true, -SMALL, &faces))
00414         {
00415             noFailedChecks++;
00416 
00417             label nFaces = returnReduce(faces.size(), sumOp<label>());
00418 
00419             if (nFaces > 0)
00420             {
00421                 Info<< "  <<Writing " << nFaces
00422                     << " faces with incorrect orientation to set "
00423                     << faces.name() << endl;
00424                 faces.write();
00425             }
00426         }
00427     }
00428 
00429     {
00430         faceSet faces(mesh, "skewFaces", mesh.nFaces()/100 + 1);
00431         if (mesh.checkFaceSkewness(true, &faces))
00432         {
00433             noFailedChecks++;
00434 
00435             label nFaces = returnReduce(faces.size(), sumOp<label>());
00436 
00437             if (nFaces > 0)
00438             {
00439                 Info<< "  <<Writing " << nFaces
00440                     << " skew faces to set " << faces.name() << endl;
00441                 faces.write();
00442             }
00443         }
00444     }
00445 
00446     if (allGeometry)
00447     {
00448         // Note use of nPoints since don't want edge construction.
00449         pointSet points(mesh, "shortEdges", mesh.nPoints()/1000 + 1);
00450         if (mesh.checkEdgeLength(true, minDistSqr, &points))
00451         {
00452             //noFailedChecks++;
00453 
00454             label nPoints = returnReduce(points.size(), sumOp<label>());
00455 
00456             if (nPoints > 0)
00457             {
00458                 Info<< "  <<Writing " << nPoints
00459                     << " points on short edges to set " << points.name()
00460                     << endl;
00461                 points.write();
00462             }
00463         }
00464 
00465         label nEdgeClose = returnReduce(points.size(), sumOp<label>());
00466 
00467         if (mesh.checkPointNearness(false, minDistSqr, &points))
00468         {
00469             //noFailedChecks++;
00470 
00471             label nPoints = returnReduce(points.size(), sumOp<label>());
00472 
00473             if (nPoints > nEdgeClose)
00474             {
00475                 pointSet nearPoints(mesh, "nearPoints", points);
00476                 Info<< "  <<Writing " << nPoints
00477                     << " near (closer than " << Foam::sqrt(minDistSqr)
00478                     << " apart) points to set " << nearPoints.name() << endl;
00479                 nearPoints.write();
00480             }
00481         }
00482     }
00483 
00484     if (allGeometry)
00485     {
00486         faceSet faces(mesh, "concaveFaces", mesh.nFaces()/100 + 1);
00487         if (mesh.checkFaceAngles(true, 10, &faces))
00488         {
00489             //noFailedChecks++;
00490 
00491             label nFaces = returnReduce(faces.size(), sumOp<label>());
00492 
00493             if (nFaces > 0)
00494             {
00495                 Info<< "  <<Writing " << nFaces
00496                     << " faces with concave angles to set " << faces.name()
00497                     << endl;
00498                 faces.write();
00499             }
00500         }
00501     }
00502 
00503     if (allGeometry)
00504     {
00505         faceSet faces(mesh, "warpedFaces", mesh.nFaces()/100 + 1);
00506         if (mesh.checkFaceFlatness(true, 0.8, &faces))
00507         {
00508             //noFailedChecks++;
00509 
00510             label nFaces = returnReduce(faces.size(), sumOp<label>());
00511 
00512             if (nFaces > 0)
00513             {
00514                 Info<< "  <<Writing " << nFaces
00515                     << " warped faces to set " << faces.name() << endl;
00516                 faces.write();
00517             }
00518         }
00519     }
00520 
00521     if (allGeometry)
00522     {
00523         cellSet cells(mesh, "underdeterminedCells", mesh.nCells()/100);
00524         if (mesh.checkCellDeterminant(true, &cells, mesh.geometricD()))
00525         {
00526             noFailedChecks++;
00527 
00528             label nCells = returnReduce(cells.size(), sumOp<label>());
00529 
00530             Info<< "  <<Writing " << nCells
00531                 << " under-determined cells to set " << cells.name() << endl;
00532             cells.write();
00533         }
00534     }
00535 
00536 
00537     return noFailedChecks;
00538 }
00539 
00540 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines