diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C index 92038cca30..3c938cadb8 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C @@ -5,7 +5,7 @@ \\ / A nd | \\/ M anipulation | ------------------------------------------------------------------------------- - | Copyright (C) 2011-2017 OpenFOAM Foundation + | Copyright (C) 2011-2019 OpenFOAM Foundation ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,6 +37,59 @@ const Foam::scalar Foam::polyMeshTetDecomposition::minTetQuality = sqr(SMALL); // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // +Foam::scalar Foam::polyMeshTetDecomposition::minQuality +( + const polyMesh& mesh, + const point& cC, + const label fI, + const bool isOwner, + const label faceBasePtI +) +{ + // Does fan decomposition of face (starting at faceBasePti) and determines + // min quality over all resulting tets. + + const pointField& pPts = mesh.points(); + const face& f = mesh.faces()[fI]; + const point& tetBasePt = pPts[f[faceBasePtI]]; + + scalar thisBaseMinTetQuality = vGreat; + + for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++) + { + label facePtI = (tetPtI + faceBasePtI) % f.size(); + label otherFacePtI = f.fcIndex(facePtI); + + label ptAI = -1; + label ptBI = -1; + + if (isOwner) + { + ptAI = f[facePtI]; + ptBI = f[otherFacePtI]; + } + else + { + ptAI = f[otherFacePtI]; + ptBI = f[facePtI]; + } + + const point& pA = pPts[ptAI]; + const point& pB = pPts[ptBI]; + + tetPointRef tet(cC, tetBasePt, pA, pB); + + scalar tetQuality = tet.quality(); + + if (tetQuality < thisBaseMinTetQuality) + { + thisBaseMinTetQuality = tetQuality; + } + } + return thisBaseMinTetQuality; +} + + Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint ( const polyMesh& mesh, @@ -47,7 +100,6 @@ Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint ) { const faceList& pFaces = mesh.faces(); - const pointField& pPts = mesh.points(); const vectorField& pC = mesh.cellCentres(); const labelList& pOwner = mesh.faceOwner(); @@ -57,52 +109,12 @@ Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint const point& oCc = pC[oCI]; - List tetQualities(2, Zero); - forAll(f, faceBasePtI) { - scalar thisBaseMinTetQuality = VGREAT; + scalar minQ = minQuality(mesh, oCc, fI, true, faceBasePtI); + minQ = min(minQ, minQuality(mesh, nCc, fI, false, faceBasePtI)); - const point& tetBasePt = pPts[f[faceBasePtI]]; - - for (label tetPtI = 1; tetPtI < f.size() - 1; ++tetPtI) - { - label facePtI = (tetPtI + faceBasePtI) % f.size(); - label otherFacePtI = f.fcIndex(facePtI); - - { - // owner cell tet - label ptAI = f[facePtI]; - label ptBI = f[otherFacePtI]; - - const point& pA = pPts[ptAI]; - const point& pB = pPts[ptBI]; - - tetPointRef tet(oCc, tetBasePt, pA, pB); - - tetQualities[0] = tet.quality(); - } - - { - // neighbour cell tet - label ptAI = f[otherFacePtI]; - label ptBI = f[facePtI]; - - const point& pA = pPts[ptAI]; - const point& pB = pPts[ptBI]; - - tetPointRef tet(nCc, tetBasePt, pA, pB); - - tetQualities[1] = tet.quality(); - } - - if (min(tetQualities) < thisBaseMinTetQuality) - { - thisBaseMinTetQuality = min(tetQualities); - } - } - - if (thisBaseMinTetQuality > tol) + if (minQ > tol) { return faceBasePtI; } @@ -142,7 +154,6 @@ Foam::label Foam::polyMeshTetDecomposition::findBasePoint ) { const faceList& pFaces = mesh.faces(); - const pointField& pPts = mesh.points(); const vectorField& pC = mesh.cellCentres(); const labelList& pOwner = mesh.faceOwner(); @@ -156,43 +167,9 @@ Foam::label Foam::polyMeshTetDecomposition::findBasePoint forAll(f, faceBasePtI) { - scalar thisBaseMinTetQuality = VGREAT; + scalar quality = minQuality(mesh, cC, fI, own, faceBasePtI); - const point& tetBasePt = pPts[f[faceBasePtI]]; - - for (label tetPtI = 1; tetPtI < f.size() - 1; ++tetPtI) - { - label facePtI = (tetPtI + faceBasePtI) % f.size(); - label otherFacePtI = f.fcIndex(facePtI); - - label ptAI = -1; - label ptBI = -1; - - if (own) - { - ptAI = f[facePtI]; - ptBI = f[otherFacePtI]; - } - else - { - ptAI = f[otherFacePtI]; - ptBI = f[facePtI]; - } - - const point& pA = pPts[ptAI]; - const point& pB = pPts[ptBI]; - - tetPointRef tet(cC, tetBasePt, pA, pB); - - scalar tetQuality = tet.quality(); - - if (tetQuality < thisBaseMinTetQuality) - { - thisBaseMinTetQuality = tetQuality; - } - } - - if (thisBaseMinTetQuality > tol) + if (quality > tol) { return faceBasePtI; } diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H index da2ff79d20..76babccb1b 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H @@ -5,7 +5,7 @@ \\ / A nd | \\/ M anipulation | ------------------------------------------------------------------------------- - | Copyright (C) 2011-2017 OpenFOAM Foundation + | Copyright (C) 2011-2019 OpenFOAM Foundation ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -69,6 +69,17 @@ public: // Member Functions + //- Given a face and cc and starting index for triangulation determine + // the worst tet quality. + static scalar minQuality + ( + const polyMesh& mesh, + const point& cC, + const label fI, + const bool isOwner, + const label faceBasePtI + ); + //- Find the first suitable base point to use for a minimum // triangle decomposition of the face, suiting owner and // neighbour cells. Finds the first base point on the face diff --git a/src/sampling/surface/isoSurface/isoSurfaceTopo.C b/src/sampling/surface/isoSurface/isoSurfaceTopo.C index 48c6091656..f28cae2270 100644 --- a/src/sampling/surface/isoSurface/isoSurfaceTopo.C +++ b/src/sampling/surface/isoSurface/isoSurfaceTopo.C @@ -5,7 +5,7 @@ \\ / A nd | \\/ M anipulation | ------------------------------------------------------------------------------- - | Copyright (C) 2011-2018 OpenFOAM Foundation + | Copyright (C) 2011-2019 OpenFOAM Foundation ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,6 +30,8 @@ License #include "tetMatcher.H" #include "tetPointRef.H" #include "DynamicField.H" +#include "syncTools.H" +#include "polyMeshTetDecomposition.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -107,7 +109,14 @@ Foam::isoSurfaceTopo::cellCutType Foam::isoSurfaceTopo::calcCutType break; } - const label fp0 = mesh_.tetBasePtIs()[facei]; + label fp0 = tetBasePtIs_[facei]; + + // Fall back for problem decompositions + if (fp0 < 0) + { + fp0 = 0; + } + label fp = f.fcIndex(fp0); for (label i = 2; i < f.size(); ++i) { @@ -189,6 +198,184 @@ Foam::label Foam::isoSurfaceTopo::calcCutTypes } +Foam::scalar Foam::isoSurfaceTopo::minTetQ +( + const label facei, + const label faceBasePtI +) const +{ + scalar q = polyMeshTetDecomposition::minQuality + ( + mesh_, + mesh_.cellCentres()[mesh_.faceOwner()[facei]], + facei, + true, + faceBasePtI + ); + + if (mesh_.isInternalFace(facei)) + { + q = min + ( + q, + polyMeshTetDecomposition::minQuality + ( + mesh_, + mesh_.cellCentres()[mesh_.faceNeighbour()[facei]], + facei, + false, + faceBasePtI + ) + ); + } + return q; +} + + +void Foam::isoSurfaceTopo::fixTetBasePtIs() +{ + // Determine points used by two faces on the same cell + const cellList& cells = mesh_.cells(); + const faceList& faces = mesh_.faces(); + const labelList& faceOwner = mesh_.faceOwner(); + const labelList& faceNeighbour = mesh_.faceNeighbour(); + + + // Get face triangulation base point + tetBasePtIs_ = mesh_.tetBasePtIs(); + + + // Pre-filter: mark all cells with illegal base points + labelHashSet problemCells(cells.size()/128); + forAll(tetBasePtIs_, facei) + { + if (tetBasePtIs_[facei] == -1) + { + problemCells.insert(faceOwner[facei]); + if (mesh_.isInternalFace(facei)) + { + problemCells.insert(faceNeighbour[facei]); + } + } + } + + + label nAdapted = 0; + + + // Number of times a point occurs in a cell. Used to detect dangling + // vertices (count = 2) + Map