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

View File

@ -21,7 +21,6 @@ boundary
sealing
{
type patch;
ownerPolyPatch window;
neighbourPolyPatch fixedWall;
}
}

View File

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

View File

@ -22,12 +22,18 @@ referenceLevel 0;
boundaryField
{
inlet
inlet1
{
type fixedValue;
value uniform 1;
}
inlet2
{
type fixedValue;
value uniform 0.9;
}
outlet
{
type inletOutlet;

View File

@ -20,7 +20,13 @@ internalField uniform (0.05 0 0);
boundaryField
{
inlet
inlet1
{
type fixedValue;
value $internalField;
}
inlet2
{
type fixedValue;
value $internalField;

View File

@ -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)
/* 2*/ ($out 0 0)
/* 8*/ ($out 0 0)
/* 9*/ ($out 1 0)
/*10*/ ($out 0 $height)
/*11*/ ($out 1 $height)
/* 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)
);
}
top
top1
{
type patch;
faces
(
(4 5 6 7)
(9 10 13 12)
);
}
top2
{
type patch;
faces
(
(12 13 16 15)
);
}
@ -112,7 +145,8 @@ boundary
type patch;
faces
(
(5 10 11 6)
(10 11 14 13)
(13 14 17 16)
);
}
);

View File

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

View File

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

View File

@ -21,7 +21,6 @@ boundary
frontAndBack
{
type empty;
ownerPolyPatch freeSurface;
neighbourPolyPatch frontAndBack;
}
}

View File

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