From f005b36b6633133839609a4e2b0d51ac8e6b4df7 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 26 Feb 2020 10:18:00 +0100
Subject: [PATCH] ENH: code cleanup in MeshedSurface (#1600)

- removed swapZones method (unused, potentially fragile)

- add subsetMesh by name

BUG: incorrect zone assignment in MeshedSurface::subsetMesh

- used the new (zero-sized) zone when determining the old zone ending
  instead of the original zone bounds.
---
 src/surfMesh/MeshedSurface/MeshedSurface.C    | 200 ++++++++++--------
 src/surfMesh/MeshedSurface/MeshedSurface.H    |  28 +--
 .../MeshedSurface/MeshedSurfaceZones.C        | 107 ++++++----
 .../UnsortedMeshedSurface.C                   |  12 +-
 .../UnsortedMeshedSurface.H                   |   3 +-
 .../surfaceFormats/surfaceFormatsCore.C       |  19 ++
 .../surfaceFormats/surfaceFormatsCore.H       |  12 ++
 7 files changed, 229 insertions(+), 152 deletions(-)

diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.C b/src/surfMesh/MeshedSurface/MeshedSurface.C
index f9055b3b017..3ab8d778844 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.C
@@ -178,7 +178,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
 )
 :
     ParentType(surf.surfFaces(), surf.points()),
-    zones_(surf.surfZones())
+    zones_(surf.zones_)
 {}
 
 
@@ -188,7 +188,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
     const UnsortedMeshedSurface<Face>& surf
 )
 :
-    ParentType(List<Face>(), surf.points())
+    ParentType(List<Face>(), surf.points())  // Copy points only
 {
     labelList faceMap;
     this->storedZones() = surf.sortedZones(faceMap);
@@ -230,7 +230,7 @@ Foam::MeshedSurface<Face>::MeshedSurface
 
 
 template<class Face>
-    Foam::MeshedSurface<Face>::MeshedSurface
+Foam::MeshedSurface<Face>::MeshedSurface
 (
     const pointField& pointLst,
     const UList<Face>& faceLst,
@@ -505,10 +505,10 @@ Foam::MeshedSurface<Face>::~MeshedSurface()
 template<class Face>
 void Foam::MeshedSurface<Face>::remapFaces
 (
-    const labelUList& faceMap
+    const labelUList& faceMapNewToOld
 )
 {
-    if (faceMap.empty())
+    if (faceMapNewToOld.empty())
     {
         return;
     }
@@ -517,23 +517,24 @@ void Foam::MeshedSurface<Face>::remapFaces
 
     if (zones.size() == 1)
     {
-        zones[0].size() = faceMap.size();   // Single zone case is trivial
+        // Single zone case is trivial
+        zones[0].size() = faceMapNewToOld.size();
         return;
     }
 
     // Recalculate the zone start/size
     label newFacei = 0;
-    label origEndI = 0;
+    label origEndi = 0;
 
     for (surfZone& zone : zones)
     {
         // Adjust zone start
         zone.start() = newFacei;
-        origEndI += zone.size();
+        origEndi += zone.size();
 
-        for (label facei = newFacei; facei < faceMap.size(); ++facei)
+        for (label facei = newFacei; facei < faceMapNewToOld.size(); ++facei)
         {
-            if (faceMap[facei] < origEndI)
+            if (faceMapNewToOld[facei] < origEndi)
             {
                 ++newFacei;
             }
@@ -588,7 +589,7 @@ void Foam::MeshedSurface<Face>::scalePoints(const scalar scaleFactor)
         // Adapt for new point position
         ParentType::movePoints(newPoints);
 
-        storedPoints() = newPoints;
+        storedPoints() = std::move(newPoints);
     }
 }
 
@@ -635,19 +636,19 @@ bool Foam::MeshedSurface<Face>::stitchFaces
 
     List<Face>& faceLst = this->storedFaces();
 
-    List<label> faceMap(faceLst.size());
+    labelList faceMap(faceLst.size(), -1);
 
     // Reset the point labels to the unique points array
     label newFacei = 0;
     forAll(faceLst, facei)
     {
         Face& f = faceLst[facei];
-        forAll(f, fp)
+        for (label& vert : f)
         {
-            f[fp] = pointMap[f[fp]];
+            vert = pointMap[vert];
         }
 
-        // for extra safety: collapse face as well
+        // For extra safety: collapse face as well
         if (f.collapse() >= 3)
         {
             if (newFacei != facei)
@@ -674,8 +675,9 @@ bool Foam::MeshedSurface<Face>::stitchFaces
                 << "Removed " << faceLst.size() - newFacei
                 << " faces" << endl;
         }
-        faceLst.setSize(newFacei);
-        faceMap.setSize(newFacei);
+        faceMap.resize(newFacei);
+        faceLst.resize(newFacei);
+
         remapFaces(faceMap);
     }
     faceMap.clear();
@@ -697,26 +699,27 @@ bool Foam::MeshedSurface<Face>::checkFaces
     bool changed = false;
     List<Face>& faceLst = this->storedFaces();
 
-    List<label> faceMap(faceLst.size());
+    labelList faceMap(faceLst.size());
 
     label newFacei = 0;
+    const label maxPointi = this->points().size();
+
     // Detect badly labelled faces and mark degenerate faces
-    const label maxPointi = this->points().size() - 1;
     forAll(faceLst, facei)
     {
         Face& f = faceLst[facei];
 
-        // avoid degenerate faces
+        // Avoid degenerate faces
         if (f.collapse() >= 3)
         {
-            forAll(f, fp)
+            for (const label vert : f)
             {
-                if (f[fp] < 0 || f[fp] > maxPointi)
+                if (vert < 0 || vert >= maxPointi)
                 {
                     FatalErrorInFunction
                         << "face " << f
                         << " uses point indices outside point range 0.."
-                    << maxPointi
+                        << (maxPointi-1)
                         << exit(FatalError);
                 }
             }
@@ -726,7 +729,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
         }
         else
         {
-            // mark as bad face
+            // Mark as bad face
             faceMap[facei] = -1;
 
             changed = true;
@@ -745,7 +748,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
     newFacei = 0;
     forAll(faceLst, facei)
     {
-        // skip already collapsed faces:
+        // Skip already collapsed faces
         if (faceMap[facei] < 0)
         {
             continue;
@@ -753,16 +756,14 @@ bool Foam::MeshedSurface<Face>::checkFaces
 
         const Face& f = faceLst[facei];
 
-        // duplicate face check
+        // Duplicate face check
         bool okay = true;
         const labelList& neighbours = fFaces[facei];
 
         // Check if faceNeighbours use same points as this face.
         // Note: discards normal information - sides of baffle are merged.
-        forAll(neighbours, neighI)
+        for (const label neiFacei : neighbours)
         {
-            const label neiFacei = neighbours[neighI];
-
             if (neiFacei <= facei || faceMap[neiFacei] < 0)
             {
                 // lower numbered faces already checked
@@ -801,6 +802,9 @@ bool Foam::MeshedSurface<Face>::checkFaces
         }
     }
 
+
+    // Until now, faceMap is an identity for good faces and -1 for bad faces
+
     // Phase 1: pack
     // Done to keep numbering constant in phase 1
 
@@ -815,7 +819,7 @@ bool Foam::MeshedSurface<Face>::checkFaces
                 << " illegal faces." << endl;
         }
 
-        // compress the face list
+        // Compress the face list
         newFacei = 0;
         forAll(faceLst, facei)
         {
@@ -823,14 +827,16 @@ bool Foam::MeshedSurface<Face>::checkFaces
             {
                 if (newFacei != facei)
                 {
-                    faceLst[newFacei] = faceLst[facei];
+                    faceLst[newFacei] = std::move(faceLst[facei]);
                 }
                 faceMap[newFacei] = facei;
                 ++newFacei;
             }
         }
 
-        faceLst.setSize(newFacei);
+        faceMap.resize(newFacei);
+        faceLst.resize(newFacei);
+
         remapFaces(faceMap);
     }
     faceMap.clear();
@@ -866,9 +872,9 @@ Foam::label Foam::MeshedSurface<Face>::nTriangles
     const List<Face>& faceLst = surfFaces();
 
     // Count triangles needed
-    forAll(faceLst, facei)
+    for (const auto& f : faceLst)
     {
-        nTri += faceLst[facei].nTriangles();
+        nTri += f.nTriangles();
     }
 
     // Nothing to do
@@ -881,8 +887,8 @@ Foam::label Foam::MeshedSurface<Face>::nTriangles
     }
     else if (notNull(faceMap))
     {
-        // face map requested
-        faceMap.setSize(nTri);
+        // Face map requested
+        faceMap.resize(nTri);
 
         nTri = 0;
         forAll(faceLst, facei)
@@ -894,7 +900,7 @@ Foam::label Foam::MeshedSurface<Face>::nTriangles
             }
         }
 
-        faceMap.setSize(nTri);
+        faceMap.resize(nTri);
     }
 
     return nTri;
@@ -940,10 +946,10 @@ Foam::label Foam::MeshedSurface<Face>::triangulate
     label maxTri = 0;  // the maximum number of triangles for any single face
     List<Face>& faceLst = this->storedFaces();
 
-    // determine how many triangles will be needed
-    forAll(faceLst, facei)
+    // How many triangles will be needed
+    for (const auto& f : faceLst)
     {
-        const label n = faceLst[facei].nTriangles();
+        const label n = f.nTriangles();
         if (maxTri < n)
         {
             maxTri = n;
@@ -951,7 +957,7 @@ Foam::label Foam::MeshedSurface<Face>::triangulate
         nTri += n;
     }
 
-    // nothing to do
+    // Nothing to do
     if (nTri <= faceLst.size())
     {
         if (notNull(faceMapOut))
@@ -969,7 +975,7 @@ Foam::label Foam::MeshedSurface<Face>::triangulate
     {
         faceMap.transfer(faceMapOut);
     }
-    faceMap.setSize(nTri);
+    faceMap.resize(nTri);
 
     if (this->points().empty())
     {
@@ -1047,58 +1053,50 @@ Foam::MeshedSurface<Face> Foam::MeshedSurface<Face>::subsetMesh
     const pointField& locPoints = this->localPoints();
     const List<Face>& locFaces  = this->localFaces();
 
-
     // Fill pointMap, faceMap
     PatchTools::subsetMap(*this, include, pointMap, faceMap);
 
-    // Create compact coordinate list and forward mapping array
-    pointField newPoints(pointMap.size());
-    labelList oldToNew(locPoints.size());
+    // Subset of points (compact)
+    pointField newPoints(UIndirectList<point>(locPoints, pointMap));
+
+    // Inverse point mapping - same as ListOps invert() without checks
+    labelList oldToNew(locPoints.size(), -1);
     forAll(pointMap, pointi)
     {
-        newPoints[pointi] = locPoints[pointMap[pointi]];
         oldToNew[pointMap[pointi]] = pointi;
     }
 
-    // create/copy a new zones list, each zone with zero size
-    surfZoneList newZones(this->surfZones());
-    forAll(newZones, zoneI)
-    {
-        newZones[zoneI].size() = 0;
-    }
+    // Subset of faces
+    List<Face> newFaces(UIndirectList<Face>(locFaces, faceMap));
 
     // Renumber face node labels
-    List<Face> newFaces(faceMap.size());
-    forAll(faceMap, facei)
+    for (auto& f : newFaces)
     {
-        const label origFacei = faceMap[facei];
-        newFaces[facei] = Face(locFaces[origFacei]);
-
-        // Renumber labels for face
-        Face& f = newFaces[facei];
-        forAll(f, fp)
+        for (label& vert : f)
         {
-            f[fp] = oldToNew[f[fp]];
+            vert = oldToNew[vert];
         }
     }
     oldToNew.clear();
 
-    // recalculate the zones start/size
+    // Deep copy of zones, leave start/size intact!!
+    surfZoneList newZones(zones_);
+
+    // Recalculate the zone start/size
     label newFacei = 0;
-    label origEndI = 0;
+    label origEndi = 0;
 
-    // adjust zone sizes
-    forAll(newZones, zoneI)
+    for (surfZone& zone : newZones)
     {
-        surfZone& zone = newZones[zoneI];
+        // The old zone ending
+        origEndi += zone.size();
 
-        // adjust zone start
+        // The new zone start
         zone.start() = newFacei;
-        origEndI += zone.size();
 
         for (label facei = newFacei; facei < faceMap.size(); ++facei)
         {
-            if (faceMap[facei] < origEndI)
+            if (faceMap[facei] < origEndi)
             {
                 ++newFacei;
             }
@@ -1108,17 +1106,18 @@ Foam::MeshedSurface<Face> Foam::MeshedSurface<Face>::subsetMesh
             }
         }
 
-        // adjust zone size
+        // The new zone size
         zone.size() = newFacei - zone.start();
     }
 
-    // Construct a sub-surface
-    return MeshedSurface<Face>
-    (
-        std::move(newPoints),
-        std::move(newFaces),
-        std::move(newZones)
-    );
+
+    // Construct the sub-surface
+    MeshedSurface<Face> newSurf;
+    newSurf.storedFaces().transfer(newFaces);
+    newSurf.storedPoints().transfer(newPoints);
+    newSurf.storedZones().transfer(newZones);
+
+    return newSurf;
 }
 
 
@@ -1144,6 +1143,33 @@ Foam::MeshedSurface<Face> Foam::MeshedSurface<Face>::subsetMesh
 }
 
 
+template<class Face>
+Foam::MeshedSurface<Face> Foam::MeshedSurface<Face>::subsetMesh
+(
+    const wordRes& includeNames,
+    const wordRes& excludeNames
+) const
+{
+    bitSet include(this->size());
+
+    for
+    (
+        const label zonei
+      : fileFormats::surfaceFormatsCore::getSelectedPatches
+        (
+            zones_,
+            includeNames,
+            excludeNames
+        )
+    )
+    {
+        include.set(zones_[zonei].range());
+    }
+
+    return subsetMesh(include);
+}
+
+
 template<class Face>
 void Foam::MeshedSurface<Face>::swap
 (
@@ -1206,7 +1232,8 @@ void Foam::MeshedSurface<Face>::transfer
     UnsortedMeshedSurface<Face>& surf
 )
 {
-    clear();
+    // Clear everything
+    this->clear();
 
     labelList faceMap;
     surfZoneList zoneLst = surf.sortedZones(faceMap);
@@ -1265,13 +1292,6 @@ void Foam::MeshedSurface<Face>::swapPoints(pointField& points)
 }
 
 
-template<class Face>
-void Foam::MeshedSurface<Face>::swapZones(surfZoneList& zones)
-{
-    this->storedZones().swap(zones);
-}
-
-
 template<class Face>
 bool Foam::MeshedSurface<Face>::read(const fileName& name)
 {
@@ -1318,7 +1338,13 @@ void Foam::MeshedSurface<Face>::write
 template<class Face>
 void Foam::MeshedSurface<Face>::operator=(const MeshedSurface<Face>& surf)
 {
-    clear();
+    if (this == &surf)
+    {
+        return;  // Self-assignment is a no-op
+    }
+
+    // Clear everything
+    this->clear();
 
     this->storedPoints() = surf.points();
     this->storedFaces()  = surf.surfFaces();
diff --git a/src/surfMesh/MeshedSurface/MeshedSurface.H b/src/surfMesh/MeshedSurface/MeshedSurface.H
index 4d407384705..87834f17603 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurface.H
+++ b/src/surfMesh/MeshedSurface/MeshedSurface.H
@@ -175,7 +175,7 @@ protected:
         );
 
         //- Set new zones from faceMap
-        virtual void remapFaces(const labelUList& faceMap);
+        virtual void remapFaces(const labelUList& faceMapNewToOld);
 
 
 public:
@@ -377,7 +377,7 @@ public:
         }
 
         //- Return const access to the faces
-        inline const List<Face>& surfFaces() const
+        const List<Face>& surfFaces() const
         {
             return static_cast<const List<Face>&>(*this);
         }
@@ -391,19 +391,19 @@ public:
         }
 
         //- Face area vectors (normals)
-        inline const vectorField& Sf() const
+        const vectorField& Sf() const
         {
             return ParentType::faceAreas();
         }
 
         //- Face area magnitudes
-        inline const scalarField& magSf() const
+        const scalarField& magSf() const
         {
             return ParentType::magFaceAreas();
         }
 
         //- Face centres
-        inline const vectorField& Cf() const
+        const vectorField& Cf() const
         {
             return ParentType::faceCentres();
         }
@@ -482,7 +482,7 @@ public:
         //  The faceMap is zero-sized when no triangulation was done.
         virtual label triangulate(List<label>& faceMap);
 
-        //- Return new surface.
+        //- Return a new surface subsetted on the selected faces.
         //
         //  \param[in] include the faces to select
         //  \param[out] pointMap from subsetMeshMap
@@ -495,12 +495,19 @@ public:
             labelList& faceMap
         ) const;
 
-        //- Return new surface
+        //- Return a new surface subsetted on the selected faces.
         MeshedSurface subsetMesh(const bitSet& include) const;
 
-        //- Return new surface
+        //- Return a new surface subsetted on the selected faces.
         MeshedSurface subsetMesh(const labelHashSet& include) const;
 
+        //- Return a new surface subsetted on the selected zone names
+        MeshedSurface subsetMesh
+        (
+            const wordRes& includeNames,
+            const wordRes& excludeNames = wordRes()
+        ) const;
+
         //- Swap contents
         void swap(MeshedSurface<Face>& surf);
 
@@ -516,15 +523,12 @@ public:
         //- Release (clear) geometry and return for reuse
         autoPtr<MeshedSurface<Face>> releaseGeom();
 
-        //- Swap the stored faces
+        //- Swap the stored faces. Use with caution
         void swapFaces(List<Face>& faces);
 
         //- Swap the stored points
         void swapPoints(pointField& points);
 
-        //- Swap the stored zones
-        void swapZones(surfZoneList& zones);
-
 
     // Read
 
diff --git a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
index bbc475c6d7f..0dfea99cf0e 100644
--- a/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
+++ b/src/surfMesh/MeshedSurface/MeshedSurfaceZones.C
@@ -36,22 +36,23 @@ void Foam::MeshedSurface<Face>::checkZones()
 {
     // extra safety, ensure we have at some zones
     // and they cover all the faces - fix start silently
-    surfZoneList& zones = this->storedZones();
-    if (zones.size())
+
+    auto& zones = this->storedZones();
+
+    label count = 0;
+    for (surfZone& zn : zones)
     {
-        label count = 0;
-        forAll(zones, zoneI)
-        {
-            zones[zoneI].start() = count;
-            count += zones[zoneI].size();
-        }
+        zn.start() = count;
+        count += zn.size();
+    }
 
+    if (!zones.empty())
+    {
         if (count < this->size())
         {
             WarningInFunction
                 << "more faces " << this->size() << " than zones " << count
-                << " ... extending final zone"
-                << endl;
+                << " ... extending final zone" << nl;
 
             zones.last().size() += count - this->size();
         }
@@ -73,30 +74,38 @@ void Foam::MeshedSurface<Face>::sortFacesAndStore
     const bool sorted
 )
 {
-    List<Face>  oldFaces(std::move(unsortedFaces));
-    List<label> zones(std::move(zoneIds));
+    // Basic sanity check
+    const label nInputFaces = unsortedFaces.size();
+
+    if (sorted || zoneIds.size() != nInputFaces)
+    {
+        // Sorting not required or not possible
+        zoneIds.clear();
+        sorted = true;
+    }
 
     if (sorted)
     {
-        // Already sorted - simply transfer faces
-        this->storedFaces().transfer(oldFaces);
-        zones.clear();
+        // No additional sorting required
+        this->storedFaces().transfer(unsortedFaces);
         return;
     }
 
-    // Determine the sorted order:
-    // use sortedOrder directly since we discard the intermediate list anyhow
-    labelList faceMap(sortedOrder(zones));
-    zones.clear();
+    // The sorted order, based on zone-ids
 
-    // Sorted faces
-    List<Face> newFaces(faceMap.size());
-    forAll(faceMap, facei)
+    labelList faceMap;
+    Foam::sortedOrder(zoneIds, faceMap);
+    zoneIds.clear();
+
+    auto& newFaces = this->storedFaces();
+    newFaces.resize(nInputFaces);
+
+    // Faces in sorted order
+    forAll(newFaces, facei)
     {
-        // use transfer to recover memory where possible
-        newFaces[facei].transfer(oldFaces[faceMap[facei]]);
+        // Can use transfer, faceMap is unique
+        newFaces[facei].transfer(unsortedFaces[faceMap[facei]]);
     }
-    this->storedFaces().transfer(newFaces);
 }
 
 
@@ -109,19 +118,21 @@ void Foam::MeshedSurface<Face>::addZones
     const bool cullEmpty
 )
 {
+    auto& zones = this->storedZones();
+    zones.resize(zones.size());
+
     label nZone = 0;
 
-    surfZoneList& zones = this->storedZones();
-    zones.setSize(zones.size());
-    forAll(zones, zoneI)
+    forAll(zones, zonei)
     {
-        if (srfZones[zoneI].size() || !cullEmpty)
+        if (srfZones[zonei].size() || !cullEmpty)
         {
-            zones[nZone] = surfZone(srfZones[zoneI], nZone);
+            zones[nZone] = surfZone(srfZones[zonei], nZone);
             ++nZone;
         }
     }
-    zones.setSize(nZone);
+
+    zones.resize(nZone);
 }
 
 
@@ -133,27 +144,29 @@ void Foam::MeshedSurface<Face>::addZones
     const bool cullEmpty
 )
 {
+    auto& zones = this->storedZones();
+    zones.resize(sizes.size());
+
     label start = 0;
     label nZone = 0;
 
-    surfZoneList& zones = this->storedZones();
-    zones.setSize(sizes.size());
-    forAll(zones, zoneI)
+    forAll(zones, zonei)
     {
-        if (sizes[zoneI] || !cullEmpty)
+        if (sizes[zonei] || !cullEmpty)
         {
             zones[nZone] = surfZone
             (
-                names[zoneI],
-                sizes[zoneI],
+                names[zonei],
+                sizes[zonei],
                 start,
                 nZone
             );
-            start += sizes[zoneI];
+            start += sizes[zonei];
             ++nZone;
         }
     }
-    zones.setSize(nZone);
+
+    zones.resize(nZone);
 }
 
 
@@ -164,27 +177,29 @@ void Foam::MeshedSurface<Face>::addZones
     const bool cullEmpty
 )
 {
+    auto& zones = this->storedZones();
+    zones.resize(sizes.size());
+
     label start = 0;
     label nZone = 0;
 
-    surfZoneList& zones = this->storedZones();
-    zones.setSize(sizes.size());
-    forAll(zones, zoneI)
+    forAll(zones, zonei)
     {
-        if (sizes[zoneI] || !cullEmpty)
+        if (sizes[zonei] || !cullEmpty)
         {
             zones[nZone] = surfZone
             (
                 surfZone::defaultName(nZone),
-                sizes[zoneI],
+                sizes[zonei],
                 start,
                 nZone
             );
-            start += sizes[zoneI];
+            start += sizes[zonei];
             ++nZone;
         }
     }
-    zones.setSize(nZone);
+
+    zones.resize(nZone);
 }
 
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
index 95633cd35d1..066c1397822 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.C
@@ -419,11 +419,11 @@ void Foam::UnsortedMeshedSurface<Face>::setZones
 template<class Face>
 void Foam::UnsortedMeshedSurface<Face>::remapFaces
 (
-    const labelUList& faceMap
+    const labelUList& faceMapNewToOld
 )
 {
     // Re-assign the zone Ids
-    if (faceMap.empty())
+    if (faceMapNewToOld.empty())
     {
         return;
     }
@@ -438,13 +438,13 @@ void Foam::UnsortedMeshedSurface<Face>::remapFaces
     }
     else
     {
-        List<label> newZones(faceMap.size());
+        List<label> newZonesIds(faceMapNewToOld.size());
 
-        forAll(faceMap, facei)
+        forAll(faceMapNewToOld, facei)
         {
-            newZones[facei] = zoneIds_[faceMap[facei]];
+            newZonesIds[facei] = zoneIds_[faceMapNewToOld[facei]];
         }
-        zoneIds_.transfer(newZones);
+        zoneIds_.transfer(newZonesIds);
     }
 }
 
diff --git a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
index d286d417b69..f0dc3cd269e 100644
--- a/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
+++ b/src/surfMesh/UnsortedMeshedSurface/UnsortedMeshedSurface.H
@@ -125,6 +125,7 @@ private:
         //- Write to Ostream
         Ostream& write(Ostream&) const;
 
+
 protected:
 
     // Protected Member Functions
@@ -142,7 +143,7 @@ protected:
         }
 
         //- Set new zones from faceMap
-        virtual void remapFaces(const labelUList& faceMap);
+        virtual void remapFaces(const labelUList& faceMapNewToOld);
 
 
 public:
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
index fed6385b6a9..c3062b0a74f 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
@@ -31,6 +31,7 @@ License
 #include "ListOps.H"
 #include "Fstream.H"
 #include "surfMesh.H"
+#include "stringListOps.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -56,6 +57,24 @@ Foam::string Foam::fileFormats::surfaceFormatsCore::getLineNoComment
 }
 
 
+Foam::labelList Foam::fileFormats::surfaceFormatsCore::getSelectedPatches
+(
+    const surfZoneList& patches,
+    const wordRes& whitelist,
+    const wordRes& blacklist
+)
+{
+    return
+        stringListOps::findMatching
+        (
+            patches,
+            whitelist,
+            blacklist,
+            nameOp<surfZone>()
+        );
+}
+
+
 #if 0
 Foam::fileName Foam::fileFormats::surfaceFormatsCore::localMeshFileName
 (
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
index 70fe0d39951..61605193809 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.H
@@ -40,6 +40,7 @@ SourceFiles
 
 #include "Map.H"
 #include "HashSet.H"
+#include "wordRes.H"
 #include "labelList.H"
 #include "surfZoneList.H"
 #include "surfZoneIdentifierList.H"
@@ -88,6 +89,17 @@ protected:
             return List<surfZone>(1, surfZone(name, container.size()));
         }
 
+        //- Return ids for zone/patch that match by name.
+        //  Uses a combination of whitelist and blacklist.
+        //
+        //  See Foam::stringListOps::findMatching
+        static labelList getSelectedPatches
+        (
+            const surfZoneList& patches,
+            const wordRes& whitelist,
+            const wordRes& blacklist = wordRes()
+        );
+
 
     // IO helpers
 
-- 
GitLab