diff --git a/etc/caseDicts/meshQualityDict b/etc/caseDicts/meshQualityDict index ada9935597eacb8ef0ed6474c5f30b9064b3bd67..b1e007fe1c0fafdd12fa05626dc11a81af4a9e84 100644 --- a/etc/caseDicts/meshQualityDict +++ b/etc/caseDicts/meshQualityDict @@ -67,12 +67,14 @@ minVolRatio 0.01; // for Fluent compatibility minTriangleTwist -1; - //- If >0 : preserve cells with all points on the surface if the // resulting volume after snapping (by approximation) is larger than // minVolCollapseRatio times old volume (i.e. not collapsed to flat cell). // If <0 : delete always. //minVolCollapseRatio 0.1; +//- Minimum edge length. Set to <0 to disable +minEdgeLength 0.001; + // ************************************************************************* // diff --git a/src/dynamicMesh/motionSmoother/motionSmootherAlgoCheck.C b/src/dynamicMesh/motionSmoother/motionSmootherAlgoCheck.C index 85c7a72d81f628d21d14f4bc01664f738f3022a9..1b3a8701021d0e5ba304bce5175c48485f0f01b7 100644 --- a/src/dynamicMesh/motionSmoother/motionSmootherAlgoCheck.C +++ b/src/dynamicMesh/motionSmoother/motionSmootherAlgoCheck.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020,2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,6 +29,7 @@ License #include "motionSmootherAlgo.H" #include "polyMeshGeometry.H" #include "IOmanip.H" +#include "pointSet.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // @@ -127,6 +128,13 @@ bool Foam::motionSmootherAlgo::checkMesh ( get<scalar>(dict, "minDeterminant", dryRun, keyType::REGEX_RECURSIVE) ); + const scalar minEdgeLength + ( + dict.getOrDefault<scalar> + ( + "minEdgeLength", -1, keyType::REGEX_RECURSIVE + ) + ); if (dryRun) @@ -452,6 +460,40 @@ bool Foam::motionSmootherAlgo::checkMesh nWrongFaces = nNewWrongFaces; } + if (minEdgeLength >= 0) + { + pointSet edgePoints(mesh, "smallEdgePoints", mesh.nPoints()/1000); + polyMeshGeometry::checkEdgeLength + ( + report, + minEdgeLength, + mesh, + checkFaces, + &edgePoints + ); + + const auto& pointFaces = mesh.pointFaces(); + + label nNewWrongFaces = 0; + for (const label pointi : edgePoints) + { + const auto& pFaces = pointFaces[pointi]; + for (const label facei : pFaces) + { + if (wrongFaces.insert(facei)) + { + nNewWrongFaces++; + } + } + } + + Info<< " faces with edge length < " + << setw(5) << minEdgeLength << " : " + << returnReduce(nNewWrongFaces, sumOp<label>()) << endl; + + nWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>()); + } + //Pout.setf(ios_base::right); return nWrongFaces > 0; @@ -539,11 +581,23 @@ bool Foam::motionSmootherAlgo::checkMesh ); const scalar maxIntSkew ( - get<scalar>(dict, "maxInternalSkewness", dryRun, keyType::REGEX_RECURSIVE) + get<scalar> + ( + dict, + "maxInternalSkewness", + dryRun, + keyType::REGEX_RECURSIVE + ) ); const scalar maxBounSkew ( - get<scalar>(dict, "maxBoundarySkewness", dryRun, keyType::REGEX_RECURSIVE) + get<scalar> + ( + dict, + "maxBoundarySkewness", + dryRun, + keyType::REGEX_RECURSIVE + ) ); const scalar minWeight ( @@ -572,6 +626,13 @@ bool Foam::motionSmootherAlgo::checkMesh ( get<scalar>(dict, "minDeterminant", dryRun, keyType::REGEX_RECURSIVE) ); + const scalar minEdgeLength + ( + dict.getOrDefault<scalar> + ( + "minEdgeLength", -1, keyType::REGEX_RECURSIVE + ) + ); if (dryRun) { @@ -865,6 +926,44 @@ bool Foam::motionSmootherAlgo::checkMesh nWrongFaces = nNewWrongFaces; } + if (minEdgeLength >= 0) + { + pointSet edgePoints + ( + meshGeom.mesh(), + "smallEdgePoints", + meshGeom.mesh().nPoints()/1000 + ); + meshGeom.checkEdgeLength + ( + report, + minEdgeLength, + checkFaces, + &edgePoints + ); + + const auto& pointFaces = meshGeom.mesh().pointFaces(); + + label nNewWrongFaces = 0; + for (const label pointi : edgePoints) + { + const auto& pFaces = pointFaces[pointi]; + for (const label facei : pFaces) + { + if (wrongFaces.insert(facei)) + { + nNewWrongFaces++; + } + } + } + + Info<< " faces with edge length < " + << setw(5) << minEdgeLength << " : " + << returnReduce(nNewWrongFaces, sumOp<label>()) << endl; + + nWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>()); + } + //Pout.setf(ios_base::right); return nWrongFaces > 0; diff --git a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C index 77e655392ab59c5d46eba0e6f1fcd298dfa016da..8113c2262dcceacc6df8e8dc481640b988698a36 100644 --- a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C +++ b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.C @@ -2085,6 +2085,75 @@ bool Foam::polyMeshGeometry::checkCellDeterminant } +bool Foam::polyMeshGeometry::checkEdgeLength +( + const bool report, + const scalar minEdgeLength, + const polyMesh& mesh, + const labelList& checkFaces, + labelHashSet* setPtr +) +{ + const scalar reportLenSqr(Foam::sqr(minEdgeLength)); + + const pointField& points = mesh.points(); + const faceList& faces = mesh.faces(); + + scalar minLenSqr = sqr(GREAT); + scalar maxLenSqr = -sqr(GREAT); + + label nSmall = 0; + + for (const label facei : checkFaces) + { + const face& f = faces[facei]; + + forAll(f, fp) + { + label fp1 = f.fcIndex(fp); + + scalar magSqrE = magSqr(points[f[fp]] - points[f[fp1]]); + + if (setPtr && magSqrE < reportLenSqr) + { + if (setPtr->insert(f[fp]) || setPtr->insert(f[fp1])) + { + nSmall++; + } + } + + minLenSqr = min(minLenSqr, magSqrE); + maxLenSqr = max(maxLenSqr, magSqrE); + } + } + + reduce(minLenSqr, minOp<scalar>()); + reduce(maxLenSqr, maxOp<scalar>()); + + reduce(nSmall, sumOp<label>()); + + if (nSmall > 0) + { + if (report) + { + Info<< " *Edges too small, min/max edge length = " + << sqrt(minLenSqr) << " " << sqrt(maxLenSqr) + << ", number too small: " << nSmall << endl; + } + + return true; + } + + if (report) + { + Info<< " Min/max edge length = " + << sqrt(minLenSqr) << " " << sqrt(maxLenSqr) << " OK." << endl; + } + + return false; +} + + bool Foam::polyMeshGeometry::checkFaceDotProduct ( const bool report, @@ -2363,4 +2432,23 @@ bool Foam::polyMeshGeometry::checkCellDeterminant } +bool Foam::polyMeshGeometry::checkEdgeLength +( + const bool report, + const scalar minEdgeLength, + const labelList& checkFaces, + labelHashSet* setPtr +) const +{ + return checkEdgeLength + ( + report, + minEdgeLength, + mesh_, + checkFaces, + setPtr + ); +} + + // ************************************************************************* // diff --git a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H index 242c925e0900367909cac8b418216efb1fe75244..e8115e6c9d52b46384629df1c9467a52e2324307 100644 --- a/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H +++ b/src/dynamicMesh/motionSmoother/polyMeshGeometry/polyMeshGeometry.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020,2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -343,6 +343,16 @@ public: labelHashSet* setPtr ); + //- Small edges. Optionally collects points of small edges + static bool checkEdgeLength + ( + const bool report, + const scalar minEdgeLength, + const polyMesh& mesh, + const labelList& checkFaces, + labelHashSet* pointSetPtr + ); + // Checking of selected faces with local geometry. Uses above static // functions. Parallel aware. @@ -446,6 +456,14 @@ public: const labelList& affectedCells, labelHashSet* setPtr ) const; + + bool checkEdgeLength + ( + const bool report, + const scalar minEdgeLength, + const labelList& checkFaces, + labelHashSet* pointSetPtr + ) const; }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //