From 239a7884a6aa2d5114134b0adbf62363f6877366 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 9 Jun 2021 20:32:09 +0200
Subject: [PATCH] ENH: more flexible finiteArea patch selection (#2084)

- support wordRes for selecting patch names

- ownerPolyPatch specification is now optional, which simplifies input
  and also supports a faMesh spanning different patches but with a
  single boundary condition.

  Alternatively, can specify more granularity if required.

  ```
  polyMeshPatches  ( "top.*" );

  boundary
  {
      inlet1
      {
          type patch;
          ownerPolyPatch top1;    // <- specific to this portion
          neighbourPolyPatch inlet;
      }
      inlet2
      {
          type patch;
          ownerPolyPatch top2;    // <- specific to this portion
          neighbourPolyPatch inlet;
      }
      outlet
      {
          type patch;
          neighbourPolyPatch outflow;
      }
      bound
      {
          type symmetry;
          neighbourPolyPatch bound;
      }
  }
  ```
---
 src/finiteArea/faMesh/faMesh.C                | 44 +++++-----
 src/finiteArea/faMesh/faMeshPatches.C         | 61 +++++++++-----
 .../faMesh/faPatches/faPatch/faPatchData.C    | 45 ++++++++--
 .../faMesh/faPatches/faPatch/faPatchData.H    | 15 +++-
 .../main/system/faMeshDefinition              |  1 -
 .../cylinder/system/faMeshDefinition          |  5 --
 .../surfactantFoam/planeTransport/0.orig/Cs   |  8 +-
 .../surfactantFoam/planeTransport/0.orig/Us   |  8 +-
 .../planeTransport/system/blockMeshDict       | 84 +++++++++++++------
 .../planeTransport/system/faMeshDefinition    | 16 ++--
 .../system/faMeshDefinition                   |  3 -
 .../system/faMeshDefinition                   |  1 -
 .../sloshing2D/system/faMeshDefinition        |  3 -
 13 files changed, 196 insertions(+), 98 deletions(-)

diff --git a/src/finiteArea/faMesh/faMesh.C b/src/finiteArea/faMesh/faMesh.C
index d53be606046..a0896f63efa 100644
--- a/src/finiteArea/faMesh/faMesh.C
+++ b/src/finiteArea/faMesh/faMesh.C
@@ -64,35 +64,41 @@ namespace Foam
 static labelList selectPatchFaces
 (
     const polyBoundaryMesh& pbm,
-    const wordList& polyPatchNames
+    const wordRes& polyPatchNames
 )
 {
-    labelHashSet patchIDs;
+    //- Return the set of patch IDs corresponding to the given names
+    //  By default warns if given names are not found.
+    //  Optionally matches to patchGroups as well as patchNames.
+    const labelList patchIDs
+    (
+        pbm.patchSet
+        (
+            polyPatchNames,
+            false,  // warnNotFound
+            true    // useGroups
+        ).sortedToc()
+    );
 
-    label nFaceLabels = 0;
-    for (const word& patchName : polyPatchNames)
+    if (patchIDs.empty())
     {
-        const label polyPatchi = pbm.findPatchID(patchName);
-
-        if (polyPatchi < 0)
-        {
-            FatalErrorInFunction
-                << "Patch " << patchName << " not found"
-                << exit(FatalError);
-        }
+        FatalErrorInFunction
+            << "No matching patches: " << polyPatchNames << nl
+            << exit(FatalError);
+    }
 
-        if (patchIDs.insert(polyPatchi))
-        {
-            nFaceLabels += pbm[polyPatchi].size();
-        }
+    label nFaceLabels = 0;
+    for (const label patchi : patchIDs)
+    {
+        nFaceLabels += pbm[patchi].size();
     }
 
     labelList faceLabels(nFaceLabels);
 
     nFaceLabels = 0;
-    for (const label polyPatchi : patchIDs.sortedToc())
+    for (const label patchi : patchIDs)
     {
-        for (const label facei : pbm[polyPatchi].range())
+        for (const label facei : pbm[patchi].range())
         {
             faceLabels[nFaceLabels] = facei;
             ++nFaceLabels;
@@ -413,7 +419,7 @@ Foam::faMesh::faMesh
         selectPatchFaces
         (
             pMesh.boundaryMesh(),
-            faMeshDefinition.get<wordList>("polyMeshPatches")
+            faMeshDefinition.get<wordRes>("polyMeshPatches")
         )
     )
 {
diff --git a/src/finiteArea/faMesh/faMeshPatches.C b/src/finiteArea/faMesh/faMeshPatches.C
index 889bdd7826c..436f3f5678e 100644
--- a/src/finiteArea/faMesh/faMeshPatches.C
+++ b/src/finiteArea/faMesh/faMeshPatches.C
@@ -697,23 +697,30 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
         patchDef.name_ = dEntry.keyword();
         patchDef.type_ = patchDict.get<word>("type");
 
-        const word ownName(patchDict.get<word>("ownerPolyPatch"));
-        const word neiName(patchDict.get<word>("neighbourPolyPatch"));
+        word patchName;
 
-        patchDef.ownerPolyPatchId_ = pbm.findPatchID(ownName);
-        patchDef.neighPolyPatchId_ = pbm.findPatchID(neiName);
-
-        if (patchDef.ownerPolyPatchId_ < 0)
+        // Optional: ownerPolyPatch
+        if (patchDict.readIfPresent("ownerPolyPatch", patchName))
         {
-            FatalErrorInFunction
-                << "ownerPolyPatch " << ownName << " not found"
-                << exit(FatalError);
+            patchDef.ownerPolyPatchId_ = pbm.findPatchID(patchName);
+            if (patchDef.ownerPolyPatchId_ < 0)
+            {
+                FatalErrorInFunction
+                    << "ownerPolyPatch " << patchName << " not found"
+                    << exit(FatalError);
+            }
         }
-        if (patchDef.neighPolyPatchId_ < 0)
+
+        // Mandatory: neighbourPolyPatch
+        patchDict.readEntry("neighbourPolyPatch", patchName);
         {
-            FatalErrorInFunction
-                << "neighbourPolyPatch " << neiName << " not found"
-                << exit(FatalError);
+            patchDef.neighPolyPatchId_ = pbm.findPatchID(patchName);
+            if (patchDef.neighPolyPatchId_ < 0)
+            {
+                FatalErrorInFunction
+                    << "neighbourPolyPatch " << patchName << " not found"
+                    << exit(FatalError);
+            }
         }
     }
 
@@ -756,20 +763,28 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
     {
         const patchPairInfo& patchPair = bndEdgePatchPairs[bndEdgei];
 
-        if (patchPair.valid())
-        {
-            // Non-negative, unique pairing
-            // - find corresponding definition
+        // Find first definition with a matching neighbour and
+        // possibly with a matching owner.
+
+        label bestPatchi = -1;
 
-            for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi)
+        for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi)
+        {
+            const int match = faPatchDefs[patchi].matchPatchPair(patchPair);
+            if (match == 3)
             {
-                if (faPatchDefs[patchi].foundPatchPair(patchPair))
-                {
-                    bndEdgeFaPatchIDs[bndEdgei] = patchi;
-                    break;
-                }
+                // Match (owner/neighbour) - done!
+                bestPatchi = patchi;
+                break;
+            }
+            else if (match == 2 && bestPatchi < 0)
+            {
+                // Match (neighbour) - keep looking for exact match
+                bestPatchi = patchi;
             }
         }
+
+        bndEdgeFaPatchIDs[bndEdgei] = bestPatchi;
     }
 
 
diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.C b/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.C
index 7d712c99efd..c83150cea4c 100644
--- a/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.C
+++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.C
@@ -26,7 +26,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "faPatchData.H"
-#include "edge.H"
 #include "dictionary.H"
 #include "processorFaPatch.H"
 
@@ -109,21 +108,53 @@ void Foam::faPatchData::assign(const faPatch& fap)
 }
 
 
-bool Foam::faPatchData::foundPatchPair(const edge& patchPair) const
+int Foam::faPatchData::matchPatchPair
+(
+    const labelPair& patchPair
+) const noexcept
 {
-    // Same as edge::compare
-    return
-    (
+    int ret = 0;
+    if (patchPair.first() >= 0 && patchPair.first() == ownerPolyPatchId_)
+    {
+        ret |= 1;
+    }
+    if (patchPair.second() >= 0 && patchPair.second() == neighPolyPatchId_)
+    {
+        ret |= 2;
+    }
+    return ret;
+}
+
+
+int Foam::faPatchData::comparePatchPair
+(
+    const labelPair& patchPair
+) const noexcept
+{
+    // As per edge::compare, with validity check
+
+    if (patchPair.first() >= 0 || patchPair.second() >= 0)
+    {
+        if
         (
             ownerPolyPatchId_ == patchPair.first()
          && neighPolyPatchId_ == patchPair.second()
         )
-     ||
+        {
+            return 1;
+        }
+
+        if
         (
             ownerPolyPatchId_ == patchPair.second()
          && neighPolyPatchId_ == patchPair.first()
         )
-    );
+        {
+            return -1;
+        }
+    }
+
+    return 0;
 }
 
 
diff --git a/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.H b/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.H
index 4f785b35156..e66c91723e6 100644
--- a/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.H
+++ b/src/finiteArea/faMesh/faPatches/faPatch/faPatchData.H
@@ -37,6 +37,7 @@ Description
 #define faPatchData_H
 
 #include "labelList.H"
+#include "labelPair.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -44,7 +45,6 @@ namespace Foam
 {
 
 // Forward Declarations
-class edge;
 class faPatch;
 class dictionary;
 
@@ -116,8 +116,17 @@ public:
             return !owner();
         }
 
-        //- True it matches the owner/neighbour patch pair (any order)
-        bool foundPatchPair(const edge& patchPair) const;
+        //- Ordered match with owner/neighbour patchPair.
+        //  \return
+        //      - 0: matched none
+        //      - 1: matched first only (owner)
+        //      - 2: matched second only (neighbour)
+        //      - 3: matched both (owner/neighbour)
+        //      .
+        int matchPatchPair(const labelPair& patchPair) const noexcept;
+
+        //- Unordered comparison with owner/neighbour patchPair.
+        int comparePatchPair(const labelPair& patchPair) const noexcept;
 };
 
 
diff --git a/tutorials/compressible/acousticFoam/obliqueAirJet/main/system/faMeshDefinition b/tutorials/compressible/acousticFoam/obliqueAirJet/main/system/faMeshDefinition
index 7bc2d201aca..af8d22d4933 100644
--- a/tutorials/compressible/acousticFoam/obliqueAirJet/main/system/faMeshDefinition
+++ b/tutorials/compressible/acousticFoam/obliqueAirJet/main/system/faMeshDefinition
@@ -21,7 +21,6 @@ boundary
     sealing
     {
         type                patch;
-        ownerPolyPatch      window;
         neighbourPolyPatch  fixedWall;
     }
 }
diff --git a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/faMeshDefinition b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/faMeshDefinition
index 66da6e5c0e5..099c6ba9c3a 100644
--- a/tutorials/finiteArea/liquidFilmFoam/cylinder/system/faMeshDefinition
+++ b/tutorials/finiteArea/liquidFilmFoam/cylinder/system/faMeshDefinition
@@ -21,35 +21,30 @@ boundary
     inlet
     {
         type                patch;
-        ownerPolyPatch      film;
         neighbourPolyPatch  inlet;
     }
 
     outlet
     {
         type                patch;
-        ownerPolyPatch      film;
         neighbourPolyPatch  outlet;
     }
 
     side
     {
         type                patch;
-        ownerPolyPatch      film;
         neighbourPolyPatch  side;
     }
 
     symmetry
     {
         type                symmetry;
-        ownerPolyPatch      film;
         neighbourPolyPatch  symmetry;
     }
 
     cylinder
     {
         type                patch;
-        ownerPolyPatch      film;
         neighbourPolyPatch  cylinder;
     }
 }
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Cs b/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Cs
index 1cda272f838..a253322f6f1 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Cs
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Cs
@@ -22,12 +22,18 @@ referenceLevel      0;
 
 boundaryField
 {
-    inlet
+    inlet1
     {
         type        fixedValue;
         value       uniform 1;
     }
 
+    inlet2
+    {
+        type        fixedValue;
+        value       uniform 0.9;
+    }
+
     outlet
     {
         type        inletOutlet;
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Us b/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Us
index 83ebb0fa65a..394b7a5f850 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Us
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/0.orig/Us
@@ -20,7 +20,13 @@ internalField       uniform (0.05 0 0);
 
 boundaryField
 {
-    inlet
+    inlet1
+    {
+        type        fixedValue;
+        value       $internalField;
+    }
+
+    inlet2
     {
         type        fixedValue;
         value       $internalField;
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/system/blockMeshDict b/tutorials/finiteArea/surfactantFoam/planeTransport/system/blockMeshDict
index 6f5e501b6be..056f69e05f3 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/system/blockMeshDict
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/system/blockMeshDict
@@ -18,6 +18,9 @@ FoamFile
 // Depending on the decomposition, the outflow boundary may
 // coincide with a processor patch.
 
+// Additionally the plate is split into two top zones (top1 top2)
+// with different inlet boundary conditions
+
 scale   0.1;
 
 height  0.1;
@@ -26,6 +29,8 @@ len     3;
 out     1;
 out     #eval{ $out + $len };
 
+width_2 #eval{ 0.5 * $width };
+
 nx 60;
 ny 20;
 nz 1;
@@ -33,25 +38,40 @@ nout 20;
 
 vertices
 (
+    // bottom
     /* 0*/ (0 0 0)
     /* 1*/ ($len 0 0)
-    /* 2*/ ($len $width 0)
-    /* 3*/ (0 $width 0)
-    /* 4*/ (0 0 $height)
-    /* 5*/ ($len 0 $height)
-    /* 6*/ ($len $width $height)
-    /* 7*/ (0 $width $height)
-
-    /* 8*/ ($out 0 0)
-    /* 9*/ ($out 1 0)
-    /*10*/ ($out 0 $height)
-    /*11*/ ($out 1 $height)
+    /* 2*/ ($out 0 0)
+
+    /* 3*/ (0 $width_2 0)
+    /* 4*/ ($len $width_2 0)
+    /* 5*/ ($out $width_2 0)
+
+    /* 6*/ (0 $width 0)
+    /* 7*/ ($len $width 0)
+    /* 8*/ ($out $width 0)
+
+    // top
+    /* 9*/ (0 0 $height)
+    /*10*/ ($len 0 $height)
+    /*11*/ ($out 0 $height)
+
+    /*12*/ (0 $width_2 $height)
+    /*13*/ ($len $width_2 $height)
+    /*14*/ ($out $width_2 $height)
+
+    /*15*/ (0 $width $height)
+    /*16*/ ($len $width $height)
+    /*17*/ ($out $width $height)
 );
 
 blocks
 (
-    hex (0 1 2 3 4 5 6 7)   ($nx   $ny $nz) grading (1 1 1)
-    hex (1 8 9 2 5 10 11 6) ($nout $ny $nz) grading (1 1 1)
+    hex (0 1 4 3   9 10 13 12) ($nx   $ny $nz) grading (1 1 1)
+    hex (1 2 5 4  10 11 14 13) ($nout $ny $nz) grading (1 1 1)
+
+    hex (3 4 7 6  12 13 16 15) ($nx   $ny $nz) grading (1 1 1)
+    hex (4 5 8 7  13 14 17 16) ($nout $ny $nz) grading (1 1 1)
 );
 
 boundary
@@ -61,7 +81,8 @@ boundary
         type patch;
         faces
         (
-            (0 4 7 3)
+            (0 9 12 3)
+            (3 12 15 6)
         );
     }
 
@@ -70,12 +91,11 @@ boundary
         type wall;
         faces
         (
-            (3 7 6 2)
-            (1 5 4 0)
+            (0 1 10 9)
+            (1 2 11 10)
 
-            // outflow
-            (1 8 10 5)
-            (2 6 11 9)
+            (7 6 15 16)
+            (8 7 16 17)
         );
     }
 
@@ -84,7 +104,8 @@ boundary
         type patch;
         faces
         (
-            (8 9 10 11)
+            (2 5 14 11)
+            (5 8 17 14)
         );
     }
 
@@ -93,17 +114,29 @@ boundary
         type patch;
         faces
         (
-            (0 3 2 1)
-            (1 8 9 2)
+            (0 3 4 1)
+            (1 4 5 2)
+
+            (3 6 7 4)
+            (4 7 8 5)
+         );
+    }
+
+    top1
+    {
+        type patch;
+        faces
+        (
+            (9 10 13 12)
         );
     }
 
-    top
+    top2
     {
         type patch;
         faces
         (
-            (4 5 6 7)
+            (12 13 16 15)
         );
     }
 
@@ -112,7 +145,8 @@ boundary
         type patch;
         faces
         (
-            (5 10 11 6)
+            (10 11 14 13)
+            (13 14 17 16)
         );
     }
 );
diff --git a/tutorials/finiteArea/surfactantFoam/planeTransport/system/faMeshDefinition b/tutorials/finiteArea/surfactantFoam/planeTransport/system/faMeshDefinition
index 889f10a7214..30ef37e82c0 100644
--- a/tutorials/finiteArea/surfactantFoam/planeTransport/system/faMeshDefinition
+++ b/tutorials/finiteArea/surfactantFoam/planeTransport/system/faMeshDefinition
@@ -14,29 +14,33 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-polyMeshPatches  ( top );
+polyMeshPatches  ( "top.*" );
 
 boundary
 {
-    inlet
+    inlet1
     {
         type patch;
-        ownerPolyPatch top;
+        ownerPolyPatch top1;
+        neighbourPolyPatch inlet;
+    }
+
+    inlet2
+    {
+        type patch;
+        ownerPolyPatch top2;
         neighbourPolyPatch inlet;
     }
 
     outlet
     {
         type patch;
-        ownerPolyPatch top;
-        // neighbourPolyPatch outlet;
         neighbourPolyPatch outflow;
     }
 
     bound
     {
         type symmetry;
-        ownerPolyPatch top;
         neighbourPolyPatch bound;
     }
 }
diff --git a/tutorials/incompressible/pimpleFoam/laminar/contactAngleCavity/system/faMeshDefinition b/tutorials/incompressible/pimpleFoam/laminar/contactAngleCavity/system/faMeshDefinition
index f8a9f149b5c..a62acd25e80 100644
--- a/tutorials/incompressible/pimpleFoam/laminar/contactAngleCavity/system/faMeshDefinition
+++ b/tutorials/incompressible/pimpleFoam/laminar/contactAngleCavity/system/faMeshDefinition
@@ -21,21 +21,18 @@ boundary
     left
     {
         type                patch;
-        ownerPolyPatch      top;
         neighbourPolyPatch  left;
     }
 
     right
     {
         type                patch;
-        ownerPolyPatch      top;
         neighbourPolyPatch  right;
     }
 
     frontAndBack
     {
         type                empty;
-        ownerPolyPatch      top;
         neighbourPolyPatch  frontAndBack;
     }
 }
diff --git a/tutorials/incompressible/pimpleFoam/laminar/contaminatedDroplet2D/system/faMeshDefinition b/tutorials/incompressible/pimpleFoam/laminar/contaminatedDroplet2D/system/faMeshDefinition
index 70deea8c00c..816a0f99f41 100644
--- a/tutorials/incompressible/pimpleFoam/laminar/contaminatedDroplet2D/system/faMeshDefinition
+++ b/tutorials/incompressible/pimpleFoam/laminar/contaminatedDroplet2D/system/faMeshDefinition
@@ -21,7 +21,6 @@ boundary
     frontAndBack
     {
         type                empty;
-        ownerPolyPatch      freeSurface;
         neighbourPolyPatch  frontAndBack;
     }
 }
diff --git a/tutorials/incompressible/pimpleFoam/laminar/sloshing2D/system/faMeshDefinition b/tutorials/incompressible/pimpleFoam/laminar/sloshing2D/system/faMeshDefinition
index bf836d71f0d..acd769f0c16 100644
--- a/tutorials/incompressible/pimpleFoam/laminar/sloshing2D/system/faMeshDefinition
+++ b/tutorials/incompressible/pimpleFoam/laminar/sloshing2D/system/faMeshDefinition
@@ -21,21 +21,18 @@ boundary
     left
     {
         type                patch;
-        ownerPolyPatch      top;
         neighbourPolyPatch  left;
     }
 
     right
     {
         type                patch;
-        ownerPolyPatch      top;
         neighbourPolyPatch  right;
     }
 
     frontAndBack
     {
         type                empty;
-        ownerPolyPatch      top;
         neighbourPolyPatch  frontAndBack;
     }
 }
-- 
GitLab