diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C index f68bbd476c..3ff3071a77 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -35,6 +35,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, @@ -45,7 +98,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(); @@ -55,52 +107,12 @@ Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint const point& oCc = pC[oCI]; - List tetQualities(2, 0.0); - 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; } @@ -140,7 +152,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(); @@ -154,43 +165,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 1b8b55f343..03c7b9d7a2 100644 --- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H +++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/polyMeshTetDecomposition.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -67,6 +67,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/sampledSurface/isoSurface/isoSurface.C b/src/sampling/sampledSurface/isoSurface/isoSurface.C index 94d15f1a7a..9f86c30572 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurface.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurface.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org - \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -28,6 +28,8 @@ License #include "tetMatcher.H" #include "tetPointRef.H" #include "DynamicField.H" +#include "syncTools.H" +#include "polyMeshTetDecomposition.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -106,7 +108,14 @@ Foam::isoSurface::cellCutType Foam::isoSurface::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++) { @@ -191,6 +200,184 @@ Foam::label Foam::isoSurface::calcCutTypes } +Foam::scalar Foam::isoSurface::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::isoSurface::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