diff --git a/applications/utilities/postProcessing/sampling/sample/sampleDict b/applications/utilities/postProcessing/sampling/sample/sampleDict index 57385a9555..db42299d1e 100644 --- a/applications/utilities/postProcessing/sampling/sample/sampleDict +++ b/applications/utilities/postProcessing/sampling/sample/sampleDict @@ -155,21 +155,25 @@ surfaces // Optional: whether to leave as faces (=default) or triangulate } - constantIso - { - name isoSurface; - isoField rho; - isoValue 0.5; - interpolate false - } interpolatedIso { - name isoSurface; + // Iso surface for interpolated values only + type isoSurface; isoField rho; isoValue 0.5; interpolate true; //regularise false; //optional: do not simplify } + constantIso + { + // Iso surface for constant values. Guarantees triangles to not + // cross cells. + type isoSurfaceCell; + isoField rho; + isoValue 0.5; + interpolate false; + //regularise false; //optional: do not simplify + } ); diff --git a/src/sampling/Make/files b/src/sampling/Make/files index bbc77a3dde..991057a157 100644 --- a/src/sampling/Make/files +++ b/src/sampling/Make/files @@ -24,6 +24,8 @@ sampledSurface/patch/sampledPatch.C sampledSurface/plane/sampledPlane.C sampledSurface/isoSurface/isoSurface.C sampledSurface/isoSurface/sampledIsoSurface.C +sampledSurface/isoSurface/isoSurfaceCell.C +sampledSurface/isoSurface/sampledIsoSurfaceCell.C sampledSurface/distanceSurface/distanceSurface.C sampledSurface/sampledSurface/sampledSurface.C sampledSurface/sampledSurfaces/sampledSurfaces.C diff --git a/src/sampling/sampledSurface/distanceSurface/distanceSurface.C b/src/sampling/sampledSurface/distanceSurface/distanceSurface.C index fca90949ca..8c4acea996 100644 --- a/src/sampling/sampledSurface/distanceSurface/distanceSurface.C +++ b/src/sampling/sampledSurface/distanceSurface/distanceSurface.C @@ -30,6 +30,7 @@ License #include "volPointInterpolation.H" #include "addToRunTimeSelectionTable.H" #include "fvMesh.H" +#include "isoSurfaceCell.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -110,7 +111,7 @@ void Foam::distanceSurface::createGeometry() const } //- Direct from cell field and point field. - const isoSurface iso + const isoSurfaceCell iso ( mesh(), cellDistance, diff --git a/src/sampling/sampledSurface/isoSurface/isoSurface.C b/src/sampling/sampledSurface/isoSurface/isoSurface.C index 4e3d08f44a..13c210d395 100644 --- a/src/sampling/sampledSurface/isoSurface/isoSurface.C +++ b/src/sampling/sampledSurface/isoSurface/isoSurface.C @@ -25,13 +25,10 @@ License \*---------------------------------------------------------------------------*/ #include "isoSurface.H" -#include "dictionary.H" -#include "polyMesh.H" +#include "fvMesh.H" #include "mergePoints.H" -#include "tetMatcher.H" #include "syncTools.H" #include "addToRunTimeSelectionTable.H" -#include "faceTriangulation.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -61,142 +58,128 @@ Foam::scalar Foam::isoSurface::isoFraction } -//Foam::List Foam::isoSurface::triangulate(const face& f) const -//{ -// faceList triFaces(f.nTriangles(mesh_.points())); -// label triFaceI = 0; -// f.triangles(mesh_.points(), triFaceI, triFaces); -// -// List tris(triFaces.size()); -// forAll(triFaces, i) -// { -// tris[i][0] = triFaces[i][0]; -// tris[i][1] = triFaces[i][1]; -// tris[i][2] = triFaces[i][2]; -// } -// return tris; -//} - - -Foam::isoSurface::cellCutType Foam::isoSurface::calcCutType +// Determine for every face/cell whether it (possibly) generates triangles. +void Foam::isoSurface::calcCutTypes ( - const PackedList<1>& isTet, - const scalarField& cellValues, - const scalarField& pointValues, - const label cellI -) const + const volScalarField& cVals, + const scalarField& pVals +) { - const cell& cFaces = mesh_.cells()[cellI]; + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + const labelList& own = mesh_.faceOwner(); + const labelList& nei = mesh_.faceNeighbour(); - if (isTet.get(cellI) == 1) + faceCutType_.setSize(mesh_.nFaces()); + faceCutType_ = NOTCUT; + + for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++) { - forAll(cFaces, cFaceI) + // CC edge. + bool ownLower = (cVals[own[faceI]] < iso_); + bool neiLower = (cVals[nei[faceI]] < iso_); + + if (ownLower != neiLower) { - const face& f = mesh_.faces()[cFaces[cFaceI]]; - - for (label fp = 1; fp < f.size() - 1; fp++) - { - triFace tri(f[0], f[fp], f[f.fcIndex(fp)]); - - bool aLower = (pointValues[tri[0]] < iso_); - bool bLower = (pointValues[tri[1]] < iso_); - bool cLower = (pointValues[tri[2]] < iso_); - - if (aLower == bLower && aLower == cLower) - {} - else - { - return CUT; - } - } - } - return NOTCUT; - } - else - { - bool cellLower = (cellValues[cellI] < iso_); - - // First check if there is any cut in cell - bool edgeCut = false; - - forAll(cFaces, cFaceI) - { - const face& f = mesh_.faces()[cFaces[cFaceI]]; - - // Check pyramids cut - forAll(f, fp) - { - if ((pointValues[f[fp]] < iso_) != cellLower) - { - edgeCut = true; - break; - } - } - - if (edgeCut) - { - break; - } - - for (label fp = 1; fp < f.size() - 1; fp++) - { - triFace tri(f[0], f[fp], f[f.fcIndex(fp)]); - //List tris(triangulate(f)); - //forAll(tris, i) - //{ - // const triFace& tri = tris[i]; - - bool aLower = (pointValues[tri[0]] < iso_); - bool bLower = (pointValues[tri[1]] < iso_); - bool cLower = (pointValues[tri[2]] < iso_); - - if (aLower == bLower && aLower == cLower) - {} - else - { - edgeCut = true; - break; - } - } - - if (edgeCut) - { - break; - } - } - - if (edgeCut) - { - // Count actual cuts (expensive since addressing needed) - // Note: not needed if you don't want to preserve maxima/minima - // centred around cellcentre. In that case just always return CUT - - const labelList& cPoints = mesh_.cellPoints(cellI); - - label nPyrCuts = 0; - - forAll(cPoints, i) - { - if ((pointValues[cPoints[i]] < iso_) != cellLower) - { - nPyrCuts++; - } - } - - if (nPyrCuts == cPoints.size()) - { - return SPHERE; - } - else - { - return CUT; - } + faceCutType_[faceI] = CUT; } else { - return NOTCUT; + // Mesh edge. + const face f = mesh_.faces()[faceI]; + + forAll(f, fp) + { + bool fpLower = (pVals[f[fp]] < iso_); + if + ( + (fpLower != (pVals[f[f.fcIndex(fp)]] < iso_)) + || (fpLower != ownLower) + || (fpLower != neiLower) + ) + { + faceCutType_[faceI] = CUT; + break; + } + } } } + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + + label faceI = pp.start(); + forAll(pp, i) + { + bool ownLower = (cVals[own[faceI]] < iso_); + bool neiLower = (cVals.boundaryField()[patchI][i] < iso_); + + if (ownLower != neiLower) + { + faceCutType_[faceI] = CUT; + } + else + { + // Mesh edge. + const face f = mesh_.faces()[faceI]; + + forAll(f, fp) + { + bool fpLower = (pVals[f[fp]] < iso_); + if + ( + (fpLower != (pVals[f[f.fcIndex(fp)]] < iso_)) + || (fpLower != ownLower) + || (fpLower != neiLower) + ) + { + faceCutType_[faceI] = CUT; + break; + } + } + } + faceI++; + } + } + + + + nCutCells_ = 0; + cellCutType_.setSize(mesh_.nCells()); + cellCutType_ = NOTCUT; + + for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++) + { + if (faceCutType_[faceI] != NOTCUT) + { + if (cellCutType_[own[faceI]] == NOTCUT) + { + cellCutType_[own[faceI]] = CUT; + nCutCells_++; + } + if (cellCutType_[nei[faceI]] == NOTCUT) + { + cellCutType_[nei[faceI]] = CUT; + nCutCells_++; + } + } + } + for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++) + { + if (faceCutType_[faceI] != NOTCUT) + { + if (cellCutType_[own[faceI]] == NOTCUT) + { + cellCutType_[own[faceI]] = CUT; + nCutCells_++; + } + } + } + + if (debug) + { + Pout<< "isoSurface : detected " << nCutCells_ + << " candidate cut cells." << endl; + } } @@ -319,151 +302,195 @@ Foam::pointIndexHit Foam::isoSurface::collapseSurface } +// Get neighbour value and position. +void Foam::isoSurface::getNeighbour +( + const labelList& boundaryRegion, + const volScalarField& cVals, + const label cellI, + const label faceI, + scalar& nbrValue, + point& nbrPoint +) const +{ + const labelList& own = mesh_.faceOwner(); + const labelList& nei = mesh_.faceNeighbour(); + + if (mesh_.isInternalFace(faceI)) + { + label nbr = (own[faceI] == cellI ? nei[faceI] : own[faceI]); + nbrValue = cVals[nbr]; + nbrPoint = mesh_.C()[nbr]; + } + else + { + label bFaceI = faceI-mesh_.nInternalFaces(); + label patchI = boundaryRegion[bFaceI]; + label patchFaceI = faceI-mesh_.boundaryMesh()[patchI].start(); + + nbrValue = cVals.boundaryField()[patchI][patchFaceI]; + nbrPoint = mesh_.C().boundaryField()[patchI][patchFaceI]; + } +} + + +// Determine per cell centre whether all the intersections get collapsed +// to a single point void Foam::isoSurface::calcSnappedCc ( - const PackedList<1>& isTet, - const scalarField& cVals, + const labelList& boundaryRegion, + const volScalarField& cVals, const scalarField& pVals, - const List& cellCutType, DynamicList& snappedPoints, labelList& snappedCc ) const { - const pointField& cc = mesh_.cellCentres(); const pointField& pts = mesh_.points(); snappedCc.setSize(mesh_.nCells()); snappedCc = -1; // Work arrays - DynamicList localPoints(64); - DynamicList localTris(64); - Map