/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | cfMesh: A library for mesh generation \\ / O peration | \\ / A nd | Copyright held by the origina author \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of cfMesh. cfMesh is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. cfMesh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cfMesh. If not, see . \*---------------------------------------------------------------------------*/ #include "polyMeshGenChecks.H" #include "polyMeshGenAddressing.H" #include "pyramidPointFaceRef.H" #include "tetrahedron.H" # ifdef USE_OMP #include # endif // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace polyMeshGenChecks { bool checkClosedBoundary(const polyMeshGen& mesh, const bool report) { // Loop through all boundary faces and sum up the face area vectors. // For a closed boundary, this should be zero in all vector components vector sumClosed(vector::zero); scalar sumMagClosedBoundary = 0; const vectorField& areas = mesh.addressingData().faceAreas(); for(label faceI = mesh.nInternalFaces();faceI()); reduce(maxOpen, maxOp()); if( maxOpen > SMALL*max(1.0, sumMagClosedBoundary) ) { SeriousErrorIn ( "bool checkClosedBoundary(const polyMeshGen&, const bool report)" ) << "Possible hole in boundary description" << endl; Info<< "Boundary openness in x-direction = " << sumClosed.component(vector::X) << endl; Info<< "Boundary openness in y-direction = " << sumClosed.component(vector::Y) << endl; Info<< "Boundary openness in z-direction = " << sumClosed.component(vector::Z) << endl; return true; } else { if( report ) { Info<< "Boundary openness in x-direction = " << sumClosed.component(vector::X) << endl; Info<< "Boundary openness in y-direction = " << sumClosed.component(vector::Y) << endl; Info<< "Boundary openness in z-direction = " << sumClosed.component(vector::Z) << endl; Info<< "Boundary closed (OK)." << endl; } return false; } } bool checkClosedCells ( const polyMeshGen& mesh, const bool report, const scalar aspectWarn, labelHashSet* setPtr ) { // Check that all cells labels are valid const cellListPMG& cells = mesh.cells(); const label nFaces = mesh.faces().size(); label nErrorClosed = 0; # ifdef USE_OMP # pragma omp parallel for schedule(guided) reduction(+ : nErrorClosed) # endif forAll(cells, cI) { const cell& curCell = cells[cI]; if( min(curCell) < 0 || max(curCell) > nFaces ) { WarningIn ( "bool checkClosedCells(" "const polyMeshGen&, const bool, const scalar, labelHashSet*)" ) << "Cell " << cI << " contains face labels out of range: " << curCell << " Max face index = " << nFaces << endl; if( setPtr ) { # ifdef USE_OMP # pragma omp critical # endif setPtr->insert(cI); } ++nErrorClosed; } } if( nErrorClosed > 0 ) { SeriousErrorIn ( "bool checkClosedCells(" "const polyMeshGen&, const bool, const scalar, labelHashSet*)" ) << nErrorClosed << " cells with invalid face labels found" << endl; return true; } // Loop through cell faces and sum up the face area vectors for each cell. // This should be zero in all vector components vectorField sumClosed(cells.size(), vector::zero); scalarField sumMagClosed(cells.size(), 0.0); const labelList& own = mesh.owner(); const labelList& nei = mesh.neighbour(); const vectorField& areas = mesh.addressingData().faceAreas(); forAll(own, faceI) { // Add to owner sumClosed[own[faceI]] += areas[faceI]; sumMagClosed[own[faceI]] += mag(areas[faceI]); if( nei[faceI] == -1 ) continue; // Subtract from neighbour sumClosed[nei[faceI]] -= areas[faceI]; sumMagClosed[nei[faceI]] += mag(areas[faceI]); } label nOpen = 0; scalar maxOpenCell = 0; label nAspect = 0; scalar maxAspectRatio = 0; const scalarField& vols = mesh.addressingData().cellVolumes(); // Check the sums forAll(sumClosed, cellI) { scalar maxOpen = max ( sumClosed[cellI].component(vector::X), max ( sumClosed[cellI].component(vector::Y), sumClosed[cellI].component(vector::Z) ) ); maxOpenCell = max(maxOpenCell, maxOpen); if( maxOpen > SMALL*max(1.0, sumMagClosed[cellI]) ) { if( report ) { Pout<< "Cell " << cellI << " is not closed. " << "Face area vectors sum up to " << mag(sumClosed[cellI]) << " directionwise " << sumClosed[cellI] << " or " << mag(sumClosed[cellI]) /(mag(sumMagClosed[cellI]) + VSMALL) << " of the area of all faces of the cell. " << endl << " Area magnitudes sum up to " << sumMagClosed[cellI] << endl; } if( setPtr ) { setPtr->insert(cellI); } ++nOpen; } scalar aspectRatio = 1.0/6.0*sumMagClosed[cellI]/pow(vols[cellI], 2.0/3.0); maxAspectRatio = max(maxAspectRatio, aspectRatio); if( aspectRatio > aspectWarn ) { if( report ) { Pout<< "High aspect ratio for cell " << cellI << ": " << aspectRatio << endl; } ++nAspect; } } reduce(nOpen, sumOp