diff --git a/src/sampling/surface/isoSurface/isoSurfaceCell.C b/src/sampling/surface/isoSurface/isoSurfaceCell.C
index 4e27f0084e84e77770abda930d939af1bcc4c0c2..9ac005c1bbb68775928cff43c5fac4f51f34c5b3 100644
--- a/src/sampling/surface/isoSurface/isoSurfaceCell.C
+++ b/src/sampling/surface/isoSurface/isoSurfaceCell.C
@@ -45,6 +45,29 @@ namespace Foam
 }
 
 
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    // Does any edge of triangle cross iso value?
+    inline static bool isTriCut
+    (
+        const label a,
+        const label b,
+        const label c,
+        const scalarField& pointValues,
+        const scalar isoValue
+    )
+    {
+        const bool aLower = (pointValues[a] < isoValue);
+        const bool bLower = (pointValues[b] < isoValue);
+        const bool cLower = (pointValues[c] < isoValue);
+
+        return !(aLower == bLower && aLower == cLower);
+    }
+}
+
+
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 Foam::scalar Foam::isoSurfaceCell::isoFraction
@@ -64,20 +87,6 @@ Foam::scalar Foam::isoSurfaceCell::isoFraction
 }
 
 
-bool Foam::isoSurfaceCell::isTriCut
-(
-    const triFace& tri,
-    const scalarField& pointValues
-) const
-{
-    const bool aLower = (pointValues[tri[0]] < iso_);
-    const bool bLower = (pointValues[tri[1]] < iso_);
-    const bool cLower = (pointValues[tri[2]] < iso_);
-
-    return !(aLower == bLower && aLower == cLower);
-}
-
-
 Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
 (
     const bitSet& isTet,
@@ -101,9 +110,7 @@ Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
 
             for (label fp = 1; fp < f.size() - 1; ++fp)
             {
-                triFace tri(f[0], f[fp], f[f.fcIndex(fp)]);
-
-                if (isTriCut(tri, pointValues))
+                if (isTriCut(f[0], f[fp], f[f.fcIndex(fp)], pointValues, iso_))
                 {
                     return CUT;
                 }
@@ -112,6 +119,7 @@ Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
         return NOTCUT;
     }
 
+
     const bool cellLower = (cellValues[celli] < iso_);
 
     // First check if there is any cut in cell
@@ -137,13 +145,16 @@ Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
         }
 
         // Check (triangulated) face edges
-        const label fp0 = mesh_.tetBasePtIs()[facei];
+        // With fallback for problem decompositions
+        const label fp0 =
+            (mesh_.tetBasePtIs()[facei] < 0 ? 0 : mesh_.tetBasePtIs()[facei]);
+
         label fp = f.fcIndex(fp0);
         for (label i = 2; i < f.size(); ++i)
         {
             const label nextFp = f.fcIndex(fp);
 
-            if (isTriCut(triFace(f[fp0], f[fp], f[nextFp]), pointValues))
+            if (isTriCut(f[fp0], f[fp], f[nextFp], pointValues, iso_))
             {
                 edgeCut = true;
                 break;
@@ -167,21 +178,21 @@ Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
 
         const labelList& cPoints = mesh_.cellPoints(celli);
 
-        label nPyrEdgeCuts = 0;
+        label nPyrCuts = 0;
 
         for (const label pointi : cPoints)
         {
-            if (cellLower != (pointValues[pointi] < iso_))
+            if ((pointValues[pointi] < iso_) != cellLower)
             {
-                ++nPyrEdgeCuts;
+                ++nPyrCuts;
             }
         }
 
-        if (nPyrEdgeCuts == cPoints.size())
+        if (nPyrCuts == cPoints.size())
         {
             return SPHERE;
         }
-        else if (nPyrEdgeCuts)
+        else if (nPyrCuts)
         {
             // There is a pyramid edge cut. E.g. lopping off a tet from a corner
             return CUT;
@@ -206,7 +217,7 @@ void Foam::isoSurfaceCell::calcCutTypes
     // Do now to ensure things stay synchronized.
     (void)mesh_.tetBasePtIs();
 
-    forAll(mesh_.cells(), celli)
+    forAll(cellCutType_, celli)
     {
         cellCutType_[celli] = calcCutType(isTet, cVals, pVals, celli);
 
diff --git a/src/sampling/surface/isoSurface/isoSurfaceCell.H b/src/sampling/surface/isoSurface/isoSurfaceCell.H
index 34e022f5f6588ff12cb00b84f13400e4fb2396f4..b4e4c5076e6e3722002b300ea44c3c60e18638bb 100644
--- a/src/sampling/surface/isoSurface/isoSurfaceCell.H
+++ b/src/sampling/surface/isoSurface/isoSurfaceCell.H
@@ -128,12 +128,6 @@ class isoSurfaceCell
             const scalar s1
         ) const;
 
-        //- Does any edge of triangle cross iso value?
-        bool isTriCut
-        (
-            const triFace& tri,
-            const scalarField& pointValues
-        ) const;
 
         //- Determine whether cell is cut
         cellCutType calcCutType
diff --git a/src/sampling/surface/isoSurface/isoSurfaceTopo.C b/src/sampling/surface/isoSurface/isoSurfaceTopo.C
index 5d52e79150b26b12df936ddfd235ce46a0e293a7..744d995c7b0e9c9343b6b12f47daa4b98b16811b 100644
--- a/src/sampling/surface/isoSurface/isoSurfaceTopo.C
+++ b/src/sampling/surface/isoSurface/isoSurfaceTopo.C
@@ -42,22 +42,31 @@ namespace Foam
 }
 
 
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
 
-bool Foam::isoSurfaceTopo::isTriCut
-(
-    const triFace& tri,
-    const scalarField& pointValues
-) const
+namespace Foam
 {
-    const bool aLower = (pointValues[tri[0]] < iso_);
-    const bool bLower = (pointValues[tri[1]] < iso_);
-    const bool cLower = (pointValues[tri[2]] < iso_);
+    // Does any edge of triangle cross iso value?
+    inline static bool isTriCut
+    (
+        const label a,
+        const label b,
+        const label c,
+        const scalarField& pointValues,
+        const scalar isoValue
+    )
+    {
+        const bool aLower = (pointValues[a] < isoValue);
+        const bool bLower = (pointValues[b] < isoValue);
+        const bool cLower = (pointValues[c] < isoValue);
 
-    return !(aLower == bLower && aLower == cLower);
+        return !(aLower == bLower && aLower == cLower);
+    }
 }
 
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
 Foam::isoSurfaceTopo::cellCutType Foam::isoSurfaceTopo::calcCutType
 (
     const bool isTet,
@@ -79,9 +88,7 @@ Foam::isoSurfaceTopo::cellCutType Foam::isoSurfaceTopo::calcCutType
 
             for (label fp = 1; fp < f.size() - 1; ++fp)
             {
-                const triFace tri(f[0], f[fp], f[f.fcIndex(fp)]);
-
-                if (isTriCut(tri, pVals_))
+                if (isTriCut(f[0], f[fp], f[f.fcIndex(fp)], pVals_, iso_))
                 {
                     return CUT;
                 }
@@ -89,89 +96,85 @@ Foam::isoSurfaceTopo::cellCutType Foam::isoSurfaceTopo::calcCutType
         }
         return NOTCUT;
     }
-    else
-    {
-        const bool cellLower = (cVals_[celli] < iso_);
 
-        // First check if there is any cut in cell
-        bool edgeCut = false;
 
-        for (const label facei : cFaces)
-        {
-            const face& f = mesh_.faces()[facei];
-
-            // Check pyramids cut
-            for (const label pointi : f)
-            {
-                if ((pVals_[pointi] < iso_) != cellLower)
-                {
-                    edgeCut = true;
-                    break;
-                }
-            }
+    const bool cellLower = (cVals_[celli] < iso_);
 
-            if (edgeCut)
-            {
-                break;
-            }
+    // First check if there is any cut in cell
+    bool edgeCut = false;
 
-            label fp0 = tetBasePtIs_[facei];
+    for (const label facei : cFaces)
+    {
+        const face& f = mesh_.faces()[facei];
 
-            // Fall back for problem decompositions
-            if (fp0 < 0)
+        // Check pyramids cut
+        for (const label pointi : f)
+        {
+            if ((pVals_[pointi] < iso_) != cellLower)
             {
-                fp0 = 0;
+                edgeCut = true;
+                break;
             }
+        }
 
-            label fp = f.fcIndex(fp0);
-            for (label i = 2; i < f.size(); ++i)
-            {
-                label nextFp = f.fcIndex(fp);
+        if (edgeCut)
+        {
+            break;
+        }
 
-                if (isTriCut(triFace(f[fp0], f[fp], f[nextFp]), pVals_))
-                {
-                    edgeCut = true;
-                    break;
-                }
+        // Check (triangulated) face edges
+        // With fallback for problem decompositions
+        const label fp0 = (tetBasePtIs_[facei] < 0 ? 0 : tetBasePtIs_[facei]);
 
-                fp = nextFp;
-            }
+        label fp = f.fcIndex(fp0);
+        for (label i = 2; i < f.size(); ++i)
+        {
+            const label nextFp = f.fcIndex(fp);
 
-            if (edgeCut)
+            if (isTriCut(f[fp0], f[fp], f[nextFp], pVals_, iso_))
             {
+                edgeCut = true;
                 break;
             }
+
+            fp = nextFp;
         }
 
         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
+            break;
+        }
+    }
 
-            const labelList& cPoints = mesh_.cellPoints(celli);
+    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
 
-            label nPyrEdgeCuts = 0;
+        const labelList& cPoints = mesh_.cellPoints(celli);
 
-            for (const label pointi : cPoints)
-            {
-                if ((pVals_[pointi] < iso_) != cellLower)
-                {
-                    ++nPyrEdgeCuts;
-                }
-            }
+        label nPyrCuts = 0;
 
-            if (nPyrEdgeCuts == cPoints.size())
-            {
-                return SPHERE;
-            }
-            else if (nPyrEdgeCuts)
+        for (const label pointi : cPoints)
+        {
+            if ((pVals_[pointi] < iso_) != cellLower)
             {
-                return CUT;
+                ++nPyrCuts;
             }
         }
-        return NOTCUT;
+
+        if (nPyrCuts == cPoints.size())
+        {
+            return SPHERE;
+        }
+        else if (nPyrCuts)
+        {
+            return CUT;
+        }
     }
+
+    return NOTCUT;
 }
 
 
@@ -181,11 +184,10 @@ Foam::label Foam::isoSurfaceTopo::calcCutTypes
     List<cellCutType>& cellCutTypes
 )
 {
-    const cellList& cells = mesh_.cells();
+    cellCutTypes.setSize(mesh_.nCells());
 
-    cellCutTypes.setSize(cells.size());
     label nCutCells = 0;
-    forAll(cells, celli)
+    forAll(cellCutTypes, celli)
     {
         cellCutTypes[celli] = calcCutType(tet.isA(mesh_, celli), celli);
 
@@ -394,22 +396,20 @@ Foam::label Foam::isoSurfaceTopo::generatePoint
     EdgeMap<label>& vertsToPoint
 ) const
 {
-    EdgeMap<label>::const_iterator edgeFnd = vertsToPoint.find(vertices);
-    if (edgeFnd != vertsToPoint.end())
-    {
-        return edgeFnd();
-    }
-    else
+    const auto edgeFnd = vertsToPoint.cfind(vertices);
+    if (edgeFnd.found())
     {
-        // Generate new point
-        label pointi = pointToVerts.size();
-
-        pointToVerts.append(vertices);
-        pointToFace.append(facei);
-        pointFromDiag.append(edgeIsDiag);
-        vertsToPoint.insert(vertices, pointi);
-        return pointi;
+        return edgeFnd.val();
     }
+
+    // Generate new point
+    label pointi = pointToVerts.size();
+
+    pointToVerts.append(vertices);
+    pointToFace.append(facei);
+    pointFromDiag.append(edgeIsDiag);
+    vertsToPoint.insert(vertices, pointi);
+    return pointi;
 }
 
 
@@ -1181,7 +1181,8 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
             << min(pVals_) << " / "
             << max(pVals_) << nl
             << "    isoValue      : " << iso << nl
-            << "    filter        : " << int(filter) << nl
+            << "    filter        : " << isoSurfaceTopo::filterNames[filter]
+            << nl
             << "    mesh span     : " << mesh.bounds().mag() << nl
             << "    ignoreCells   : " << ignoreCells_.count()
             << " / " << cVals_.size() << nl
@@ -1329,11 +1330,8 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
         }
 
 
-        if (filter == filterType::DIAGCELL && ignoreCells_.empty())
+        if (filter == filterType::DIAGCELL)
         {
-            // Note that the following only works without cell subsets
-            // thus we skip this when ignoreCells_ is non-empty
-
             // We remove verts on face diagonals. This is in fact just
             // straightening the edges of the face through the cell. This can
             // close off 'pockets' of triangles and create open or
@@ -1356,43 +1354,71 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
             }
 
 
+            // Include faces that would be exposed from mesh subset
+            if (!ignoreCells_.empty())
+            {
+                const labelList& faceOwner = mesh_.faceOwner();
+                const labelList& faceNeighbour = mesh_.faceNeighbour();
+
+                label nMore = 0;
+                for
+                (
+                    label facei = 0;
+                    facei < mesh.nInternalFaces();
+                    ++facei
+                )
+                {
+                    int n = 0;
+                    if (ignoreCells_.test(faceOwner[facei])) ++n;
+                    if (ignoreCells_.test(faceNeighbour[facei])) ++n;
+
+                    // Only one of the cells is being ignored.
+                    // That means it is an exposed subMesh face.
+                    if (n == 1)
+                    {
+                        isBoundaryPoint.set(mesh.faces()[facei]);
+
+                        ++nMore;
+                    }
+                }
+            }
+
+
+            bitSet faceSelection;
+
             while (true)
             {
+                faceSelection.clear();
+                faceSelection.resize(this->size());
+
                 const labelList& mp = meshPoints();
 
-                bitSet removeFace(this->size());
-                label nFaces = 0;
+                const labelListList& edgeFaces = MeshStorage::edgeFaces();
+
+                forAll(edgeFaces, edgei)
                 {
-                    const labelListList& edgeFaces =
-                        MeshStorage::edgeFaces();
-                    forAll(edgeFaces, edgei)
+                    const labelList& eFaces = edgeFaces[edgei];
+                    if (eFaces.size() == 1)
                     {
-                        const labelList& eFaces = edgeFaces[edgei];
-                        if (eFaces.size() == 1)
+                        // Open edge. Check that vertices do not originate
+                        // from a boundary face
+                        const edge& e = edges()[edgei];
+                        const edge& verts0 = pointToVerts_[mp[e[0]]];
+                        const edge& verts1 = pointToVerts_[mp[e[1]]];
+                        if
+                        (
+                            isBoundaryPoint[verts0[0]]
+                         && isBoundaryPoint[verts0[1]]
+                         && isBoundaryPoint[verts1[0]]
+                         && isBoundaryPoint[verts1[1]]
+                        )
                         {
-                            // Open edge. Check that vertices do not originate
-                            // from a boundary face
-                            const edge& e = edges()[edgei];
-                            const edge& verts0 = pointToVerts_[mp[e[0]]];
-                            const edge& verts1 = pointToVerts_[mp[e[1]]];
-                            if
-                            (
-                                isBoundaryPoint[verts0[0]]
-                             && isBoundaryPoint[verts0[1]]
-                             && isBoundaryPoint[verts1[0]]
-                             && isBoundaryPoint[verts1[1]]
-                            )
-                            {
-                                // Open edge on boundary face. Keep
-                            }
-                            else
-                            {
-                                // Open edge. Mark for erosion
-                                if (removeFace.set(eFaces[0]))
-                                {
-                                    ++nFaces;
-                                }
-                            }
+                            // Open edge on boundary face. Keep
+                        }
+                        else
+                        {
+                            // Open edge. Mark for erosion
+                            faceSelection.set(eFaces[0]);
                         }
                     }
                 }
@@ -1400,24 +1426,18 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
                 if (debug)
                 {
                     Pout<< "isoSurfaceTopo :"
-                        << " removing " << nFaces
+                        << " removing " << faceSelection.count()
                         << " faces since on open edges" << endl;
                 }
 
-                if (returnReduce(nFaces, sumOp<label>()) == 0)
+                if (returnReduce(faceSelection.none(), andOp<bool>()))
                 {
                     break;
                 }
 
-                // Remove the faces
-                labelHashSet keepFaces(2*size());
-                forAll(removeFace, facei)
-                {
-                    if (!removeFace[facei])
-                    {
-                        keepFaces.insert(facei);
-                    }
-                }
+
+                // Flip from remove face -> keep face
+                faceSelection.flip();
 
                 labelList pointMap;
                 labelList faceMap;
@@ -1425,7 +1445,7 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
                 (
                     MeshStorage::subsetMesh
                     (
-                        keepFaces,
+                        faceSelection,
                         pointMap,
                         faceMap
                     )
diff --git a/src/sampling/surface/isoSurface/isoSurfaceTopo.H b/src/sampling/surface/isoSurface/isoSurfaceTopo.H
index 3e1b8a313593b96815e242496027cac4f1da4536..462dd0a06903105a28d4e387e281fb98cadf350a 100644
--- a/src/sampling/surface/isoSurface/isoSurfaceTopo.H
+++ b/src/sampling/surface/isoSurface/isoSurfaceTopo.H
@@ -99,13 +99,6 @@ class isoSurfaceTopo
 
         void fixTetBasePtIs();
 
-        //- Does any edge of triangle cross iso value?
-        bool isTriCut
-        (
-            const triFace& tri,
-            const scalarField& pointValues
-        ) const;
-
         //- Determine whether cell is cut
         cellCutType calcCutType
         (