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;
      }
  }
  ```
This commit is contained in:
Mark Olesen
2021-06-09 20:32:09 +02:00
parent 7b14af4230
commit 239a7884a6
13 changed files with 196 additions and 98 deletions

View File

@ -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()
);
if (patchIDs.empty())
{
FatalErrorInFunction
<< "No matching patches: " << polyPatchNames << nl
<< exit(FatalError);
}
label nFaceLabels = 0;
for (const word& patchName : polyPatchNames)
for (const label patchi : patchIDs)
{
const label polyPatchi = pbm.findPatchID(patchName);
if (polyPatchi < 0)
{
FatalErrorInFunction
<< "Patch " << patchName << " not found"
<< exit(FatalError);
}
if (patchIDs.insert(polyPatchi))
{
nFaceLabels += pbm[polyPatchi].size();
}
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")
)
)
{

View File

@ -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.
for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi)
label bestPatchi = -1;
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;
}

View File

@ -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;
}

View File

@ -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;
};