diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
index 8b0fbaa8567d8db0016c9d4c83d1fa1986918776..0fdf183b78b9dca6c6b6fc7018145aa49e83a22e 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
@@ -244,15 +244,6 @@ private:
             labelList& minLevel
         ) const;
 
-        //- Remove cells. Put exposedFaces into exposedPatchIDs.
-        autoPtr<mapPolyMesh> doRemoveCells
-        (
-            const labelList& cellsToRemove,
-            const labelList& exposedFaces,
-            const labelList& exposedPatchIDs,
-            removeCells& cellRemover
-        );
-
         //- Get cells which are inside any closed surface. Note that
         //  all closed surfaces
         //  will have already been oriented to have keepPoint outside.
@@ -1336,6 +1327,16 @@ public:
                 const List<labelPair>& baffles
             );
 
+            //- Get per-face information (faceZone, master/slave patch)
+            void getZoneFaces
+            (
+                const labelList& zoneIDs,
+                labelList& faceZoneID,
+                labelList& ownPatch,
+                labelList& neiPatch,
+                labelList& nBaffles
+            ) const;
+
             //- Create baffles for faces on faceZones. Return created baffles
             //  (= pairs of faces) and corresponding faceZone
             autoPtr<mapPolyMesh> createZoneBaffles
@@ -1458,6 +1459,15 @@ public:
                 const writer<scalar>& leakPathFormatter
             );
 
+            //- Remove cells. Put exposedFaces into exposedPatchIDs.
+            autoPtr<mapPolyMesh> doRemoveCells
+            (
+                const labelList& cellsToRemove,
+                const labelList& exposedFaces,
+                const labelList& exposedPatchIDs,
+                removeCells& cellRemover
+            );
+
             //- Split faces into two
             void doSplitFaces
             (
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
index eaa2e901691ca671b4b57d07c84291696ba6b66d..f6db6804bfd2bb6f3a8d96c3aa131ea567192722 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C
@@ -715,6 +715,67 @@ Foam::List<Foam::labelPair> Foam::meshRefinement::subsetBaffles
 }
 
 
+void Foam::meshRefinement::getZoneFaces
+(
+    const labelList& zoneIDs,
+    labelList& faceZoneID,
+    labelList& ownPatch,
+    labelList& neiPatch,
+    labelList& nBaffles
+) const
+{
+    const faceZoneMesh& faceZones = mesh_.faceZones();
+
+    // Per (internal) face the patch related to the faceZone
+    ownPatch.setSize(mesh_.nFaces());
+    ownPatch= -1;
+    neiPatch.setSize(mesh_.nFaces());
+    neiPatch = -1;
+    faceZoneID.setSize(mesh_.nFaces());
+    faceZoneID = -1;
+    nBaffles.setSize(zoneIDs.size());
+    nBaffles = Zero;
+
+    forAll(zoneIDs, j)
+    {
+        label zoneI = zoneIDs[j];
+        const faceZone& fz = faceZones[zoneI];
+        const word& masterName = faceZoneToMasterPatch_[fz.name()];
+        label masterPatchI = mesh_.boundaryMesh().findPatchID(masterName);
+        const word& slaveName = faceZoneToSlavePatch_[fz.name()];
+        label slavePatchI = mesh_.boundaryMesh().findPatchID(slaveName);
+
+        if (masterPatchI == -1 || slavePatchI == -1)
+        {
+            FatalErrorInFunction
+                << "Problem: masterPatchI:" << masterPatchI
+                << " slavePatchI:" << slavePatchI << exit(FatalError);
+        }
+
+        forAll(fz, i)
+        {
+            label faceI = fz[i];
+            if (mesh_.isInternalFace(faceI))
+            {
+                if (fz.flipMap()[i])
+                {
+                    ownPatch[faceI] = slavePatchI;
+                    neiPatch[faceI] = masterPatchI;
+                }
+                else
+                {
+                    ownPatch[faceI] = masterPatchI;
+                    neiPatch[faceI] = slavePatchI;
+                }
+                faceZoneID[faceI] = zoneI;
+
+                nBaffles[j]++;
+            }
+        }
+    }
+}
+
+
 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createZoneBaffles
 (
     const labelList& zoneIDs,
@@ -731,52 +792,12 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createZoneBaffles
         // Split internal faces on interface surfaces
         Info<< "Converting zoned faces into baffles ..." << endl;
 
-        // Per (internal) face the patch it should go into
-        labelList ownPatch(mesh_.nFaces(), -1);
-        labelList neiPatch(mesh_.nFaces(), -1);
-        labelList faceZoneID(mesh_.nFaces(), -1);
-
-        labelList nBaffles(zoneIDs.size(), Zero);
-
-        forAll(zoneIDs, j)
-        {
-            label zoneI = zoneIDs[j];
-
-            const faceZone& fz = faceZones[zoneI];
-
-            const word& masterName = faceZoneToMasterPatch_[fz.name()];
-            label masterPatchI = mesh_.boundaryMesh().findPatchID(masterName);
-            const word& slaveName = faceZoneToSlavePatch_[fz.name()];
-            label slavePatchI = mesh_.boundaryMesh().findPatchID(slaveName);
-
-            if (masterPatchI == -1 || slavePatchI == -1)
-            {
-                FatalErrorInFunction
-                    << "Problem: masterPatchI:" << masterPatchI
-                    << " slavePatchI:" << slavePatchI << exit(FatalError);
-            }
-
-            forAll(fz, i)
-            {
-                label faceI = fz[i];
-                if (mesh_.isInternalFace(faceI))
-                {
-                    if (fz.flipMap()[i])
-                    {
-                        ownPatch[faceI] = slavePatchI;
-                        neiPatch[faceI] = masterPatchI;
-                    }
-                    else
-                    {
-                        ownPatch[faceI] = masterPatchI;
-                        neiPatch[faceI] = slavePatchI;
-                    }
-                    faceZoneID[faceI] = zoneI;
-
-                    nBaffles[j]++;
-                }
-            }
-        }
+        // Get faceZone and patch(es) per face (or -1 if face not on faceZone)
+        labelList faceZoneID;
+        labelList ownPatch;
+        labelList neiPatch;
+        labelList nBaffles;
+        getZoneFaces(zoneIDs, faceZoneID, ownPatch, neiPatch, nBaffles);
 
         label nLocalBaffles = sum(nBaffles);
 
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.C
index 47c2bae13ad74de578aa505e1ea0708fcca86bad..f774db14ce4351b5167bb298760f8c777b7bbc0d 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.C
@@ -94,6 +94,7 @@ Foam::refinementParameters::refinementParameters
     ),
     nErodeCellZone_(dict.getOrDefault<label>("nCellZoneErodeIter", 0)),
     nFilterIter_(dict.getOrDefault<label>("nFilterIter", 2)),
+    minCellFraction_(dict.getOrDefault<scalar>("minCellFraction", 0)),
     dryRun_(dryRun)
 {
     point locationInMesh;
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.H b/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.H
index 4e301de0e4dd572dc9317a983d34cf33f0931c35..d05bce28e47e1f1220eddc934a30ee700cd23244 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.H
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/refinementParameters/refinementParameters.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2014 OpenFOAM Foundation
-    Copyright (C) 2015-2019 OpenCFD Ltd.
+    Copyright (C) 2015-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -113,6 +113,8 @@ class refinementParameters
 
         const label nFilterIter_;
 
+        const scalar minCellFraction_;
+
         const bool dryRun_;
 
 
@@ -235,6 +237,13 @@ public:
                 return nFilterIter_;
             }
 
+            //- When are disconnected regions small. Fraction of overall size
+            //  of a zone or background. Default 0.
+            scalar minCellFraction() const
+            {
+                return minCellFraction_;
+            }
+
 
         // Other
 
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
index 5dd6392ac40996e37d917863036778618bfb2916..374827f252ae295fa277fa2652ac0b238e1213a6 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2015 OpenFOAM Foundation
-    Copyright (C) 2015-2019 OpenCFD Ltd.
+    Copyright (C) 2015-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -47,6 +47,8 @@ License
 #include "fvMeshSubset.H"
 #include "interpolationTable.H"
 #include "snappyVoxelMeshDriver.H"
+#include "regionSplit.H"
+#include "removeCells.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -2869,6 +2871,142 @@ void Foam::snappyRefineDriver::mergePatchFaces
 }
 
 
+void Foam::snappyRefineDriver::deleteSmallRegions
+(
+    const refinementParameters& refineParams
+)
+{
+    const fvMesh& mesh = meshRefiner_.mesh();
+    const cellZoneMesh& czm = mesh.cellZones();
+
+    //const labelList zoneIDs
+    //(
+    //    meshRefiner_.getZones
+    //    (
+    //        List<surfaceZonesInfo::faceZoneType> fzTypes
+    //        ({
+    //            surfaceZonesInfo::BAFFLE,
+    //            surfaceZonesInfo::BOUNDARY,
+    //        });
+    //    )
+    //);
+    const labelList zoneIDs(identity(mesh.faceZones().size()));
+
+    // Get faceZone and patch(es) per face (or -1 if face not on faceZone)
+    labelList faceZoneID;
+    labelList ownPatch;
+    labelList neiPatch;
+    labelList nB;       // local count of faces per faceZone
+    meshRefiner_.getZoneFaces(zoneIDs, faceZoneID, ownPatch, neiPatch, nB);
+
+
+    // Mark all faces on outside of zones. Note: assumes that faceZones
+    // are consistent with the outside of cellZones ...
+
+    boolList isBlockedFace(mesh.nFaces(), false);
+    meshRefiner_.selectSeparatedCoupledFaces(isBlockedFace);
+
+    forAll(ownPatch, facei)
+    {
+        if (ownPatch[facei] != -1)
+        {
+            isBlockedFace[facei] = true;
+        }
+    }
+
+    // Map from cell to zone. Not that background cells are not -1 but
+    // cellZones.size()
+    labelList cellToZone(mesh.nCells(), czm.size());
+    for (const auto& cz : czm)
+    {
+        UIndirectList<label>(cellToZone, cz) = cz.index();
+    }
+
+    // Walk to split into regions
+    const regionSplit cellRegion(mesh, isBlockedFace);
+
+    // Count number of cells per zone and per region
+    labelList nCellsPerRegion(cellRegion.nRegions(), 0);
+    labelList regionToZone(cellRegion.nRegions(), -2);
+    labelList nCellsPerZone(czm.size()+1, 0);
+    forAll(cellRegion, celli)
+    {
+        const label regioni = cellRegion[celli];
+        const label zonei = cellToZone[celli];
+
+        // Zone for this region
+        regionToZone[regioni] = zonei;
+
+        nCellsPerRegion[regioni]++;
+        nCellsPerZone[zonei]++;
+    }
+    Pstream::listCombineGather(nCellsPerRegion, plusEqOp<label>());
+    Pstream::listCombineGather(regionToZone, maxEqOp<label>());
+    Pstream::listCombineGather(nCellsPerZone, plusEqOp<label>());
+
+
+    // Mark small regions
+    forAll(nCellsPerRegion, regioni)
+    {
+        const label zonei = regionToZone[regioni];
+
+        if
+        (
+            nCellsPerRegion[regioni]
+          < refineParams.minCellFraction()*nCellsPerZone[zonei]
+        )
+        {
+            Info<< "Deleting region " << regioni
+                << " (size " << nCellsPerRegion[regioni]
+                << ") of zone size " << nCellsPerZone[zonei]
+                << endl;
+
+            // Mark region to be deleted. 0 size (= global) should never
+            // occur.
+            nCellsPerRegion[regioni] = 0;
+        }
+    }
+
+    DynamicList<label> cellsToRemove(mesh.nCells()/128);
+    forAll(cellRegion, celli)
+    {
+        if (nCellsPerRegion[cellRegion[celli]] == 0)
+        {
+            cellsToRemove.append(celli);
+        }
+    }
+    const label nTotCellsToRemove = returnReduce
+    (
+        cellsToRemove.size(),
+        sumOp<label>()
+    );
+    if (nTotCellsToRemove > 0)
+    {
+        Info<< "Deleting " << nTotCellsToRemove
+            << " cells in small regions" << endl;
+
+        removeCells cellRemover(mesh);
+
+        cellsToRemove.shrink();
+        const labelList exposedFaces
+        (
+            cellRemover.getExposedFaces(cellsToRemove)
+        );
+        const labelList exposedPatch
+        (
+            UIndirectList<label>(ownPatch, exposedFaces)
+        );
+        (void)meshRefiner_.doRemoveCells
+        (
+            cellsToRemove,
+            exposedFaces,
+            exposedPatch,
+            cellRemover
+        );
+    }
+}
+
+
 void Foam::snappyRefineDriver::doRefine
 (
     const dictionary& refineDict,
@@ -3099,6 +3237,17 @@ void Foam::snappyRefineDriver::doRefine
     }
 
 
+    if (refineParams.minCellFraction() > 0)
+    {
+        // Some small disconnected bits of mesh might remain since at
+        // this point faceZones have not been converted into e.g. baffles.
+        // We don't know whether e.g. the baffles are reset to be cyclicAMI
+        // thus reconnecting. For now check if there are any particularly
+        // small regions.
+        deleteSmallRegions(refineParams);
+    }
+
+
     if (!dryRun_ && Pstream::parRun())
     {
         Info<< nl
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
index d3667968b7ac265e8e9f5fe0b27e9654a342f59d..787190069e9f0dedbfb82f4f0ac928d3cf9d82a5 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2014 OpenFOAM Foundation
-    Copyright (C) 2015-2018 OpenCFD Ltd.
+    Copyright (C) 2015-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -232,6 +232,10 @@ class snappyRefineDriver
             const dictionary& motionDict
         );
 
+        //- Optionally delete some small regions
+        void deleteSmallRegions(const refinementParameters&);
+
+
         //- No copy construct
         snappyRefineDriver(const snappyRefineDriver&) = delete;