51 bool Foam::polyBoundaryMesh::hasGroupIDs()
const 56 return !groupIDsPtr_->empty();
63 if (!
p.inGroups().empty())
73 void Foam::polyBoundaryMesh::calcGroupIDs()
const 80 groupIDsPtr_.reset(
new HashTable<labelList>(16));
81 auto& groupLookup = *groupIDsPtr_;
89 for (
const word& groupName : groups)
91 groupLookup(groupName).
append(patchi);
102 <<
"' which clashes with patch " << patchi
103 <<
" of the same name." 110 bool Foam::polyBoundaryMesh::readContents(
const bool allowReadIfPresent)
114 this->isReadRequired()
115 || (allowReadIfPresent && this->isReadOptional() && this->headerOk())
119 warnNoRereading<polyBoundaryMesh>();
124 Istream& is = readStream(typeName);
127 PtrList<entry> patchEntries(is);
138 patchEntries[patchi].keyword(),
139 patchEntries[patchi].
dict(),
157 Foam::polyBoundaryMesh::polyBoundaryMesh
171 Foam::polyBoundaryMesh::polyBoundaryMesh
184 Foam::polyBoundaryMesh::polyBoundaryMesh
195 if (!readContents(
true))
222 neighbourEdgesPtr_.clear();
224 groupIDsPtr_.clear();
237 void Foam::polyBoundaryMesh::calcGeometry()
249 operator[](patchi).initGeometry(pBufs);
252 pBufs.finishedSends();
256 operator[](patchi).calcGeometry(pBufs);
264 pBufs.finishedSends();
266 for (
const auto& schedEval : patchSchedule)
268 const label patchi = schedEval.patch;
272 operator[](patchi).initGeometry(pBufs);
276 operator[](patchi).calcGeometry(pBufs);
292 list.set(patchi, &
patches[patchi].faceCells());
305 <<
"Neighbour edge addressing not correct across parallel" 306 <<
" boundaries." <<
endl;
309 if (!neighbourEdgesPtr_)
311 neighbourEdgesPtr_.reset(
new List<labelPairList>(size()));
312 auto& neighbourEdges = *neighbourEdgesPtr_;
315 label nEdgePairs = 0;
318 const polyPatch& pp = operator[](patchi);
320 neighbourEdges[patchi].setSize(pp.nEdges() - pp.nInternalEdges());
322 for (
labelPair& edgeInfo : neighbourEdges[patchi])
328 nEdgePairs += pp.nEdges() - pp.nInternalEdges();
333 EdgeMap<labelPair> pointsToEdge(nEdgePairs);
337 const polyPatch& pp = operator[](patchi);
343 label edgei = pp.nInternalEdges();
344 edgei < edges.size();
349 const edge&
e = edges[edgei];
352 edge meshEdge(pp.meshPoints()[
e[0]], pp.meshPoints()[
e[1]]);
354 auto fnd = pointsToEdge.find(meshEdge);
366 edgei - pp.nInternalEdges()
375 neighbourEdges[patchi][edgei - pp.nInternalEdges()] =
378 neighbourEdges[edgeInfo[0]][edgeInfo[1]]
379 =
labelPair(patchi, edgei - pp.nInternalEdges());
384 pointsToEdge.erase(meshEdge);
389 if (pointsToEdge.size())
392 <<
"Not all boundary edges of patches match up." <<
nl 393 <<
"Is the outside of your mesh multiply connected?" 399 const polyPatch& pp = operator[](patchi);
407 if (edgeInfo[0] == -1 || edgeInfo[1] == -1)
409 const label edgei = pp.nInternalEdges() + i;
410 const edge&
e = pp.edges()[edgei];
413 <<
"Not all boundary edges of patches match up." <<
nl 414 <<
"Edge " << edgei <<
" on patch " << pp.name()
415 <<
" end points " << pp.localPoints()[
e[0]] <<
' ' 416 << pp.localPoints()[
e[1]] <<
" is not matched to an" 417 <<
" edge on any other patch." <<
nl 418 <<
"Is the outside of your mesh multiply connected?" 425 return *neighbourEdgesPtr_;
433 patchIDPtr_.reset(
new labelList(mesh_.nBoundaryFaces()));
461 return *groupIDsPtr_;
467 const word& groupName,
471 groupIDsPtr_.clear();
478 for (
const label patchi : patchIDs)
480 patches[patchi].inGroups().appendUniq(groupName);
481 donePatch[patchi] =
true;
487 if (!donePatch[patchi])
491 if (groups.found(groupName))
496 if (groups[i] != groupName)
498 groups[newi++] = groups[i];
516 if (isA<processorPolyPatch>(
p))
543 PtrListOps::get<word>
546 [](
const polyPatch&
p) {
return p.physicalType(); }
554 PtrListOps::get<label>
565 PtrListOps::get<label>
576 PtrListOps::get<labelRange>
586 return this->groupPatchIDs().sortedToc();
592 return mesh_.nInternalFaces();
598 return mesh_.nBoundaryFaces();
604 return labelRange(mesh_.nInternalFaces(), mesh_.nBoundaryFaces());
616 return (*
this)[patchi].range();
632 const bool checkGroups = (useGroups && this->hasGroupIDs());
640 const auto& groupLookup = groupPatchIDs();
643 if (matcher.
match(iter.key()))
646 ids.insert(iter.val());
671 else if (checkGroups)
673 const auto iter = groupPatchIDs().cfind(matcher);
678 ids.insert(iter.val());
683 return ids.sortedToc();
689 const wordRes& matcher,
697 else if (matcher.size() == 1)
699 return this->indices(matcher.first(), useGroups);
705 if (useGroups && this->hasGroupIDs())
707 ids.
resize(2*this->size());
709 const auto& groupLookup = groupPatchIDs();
712 if (matcher.match(iter.key()))
715 ids.insert(iter.val());
729 return ids.sortedToc();
745 const word& patchName,
749 if (patchName.empty())
764 <<
"Patch '" << patchName <<
"' not found. " 765 <<
"Available patch names";
770 <<
" in region '" << mesh_.name() <<
"'";
781 Pout<<
"label polyBoundaryMesh::findPatchID(const word&) const" 782 <<
"Patch named " << patchName <<
" not found. " 783 <<
"Available patch names: " <<
names() <<
endl;
794 if (faceIndex <
mesh().nInternalFaces())
799 else if (faceIndex >=
mesh().nFaces())
803 <<
"Face " << faceIndex
804 <<
" out of bounds. Number of geometric faces " <<
mesh().
nFaces()
824 [](
const polyPatch&
p, label val) {
return (
p.start() <= val); }
827 if (patchi < 0 || !
patches[patchi].
range().found(faceIndex))
831 <<
"Face " << faceIndex <<
" not found in any of the patches " 833 <<
"The patches appear to be inconsistent with the mesh :" 835 <<
" total number of faces:" <<
mesh().
nFaces()
852 output[i] = whichPatchFace(faceIndices[i]);
861 const bool warnNotFound,
869 const bool checkGroups = (useGroups && this->hasGroupIDs());
874 ids.insert(matchIndices);
876 bool missed = matchIndices.empty();
878 if (missed && checkGroups)
881 if (matcher.isPattern())
885 if (matcher.match(iter.key()))
888 ids.insert(iter.val());
895 const auto iter = groupPatchIDs().cfind(matcher);
900 ids.insert(iter.val());
906 if (missed && warnNotFound)
911 <<
"Cannot find any patch or group names matching " 917 <<
"Cannot find any patch names matching " 935 DynamicList<word> matchedGroups(1);
940 const HashTable<labelList>& groupLookup = this->groupPatchIDs();
950 label nMatch = nonGroupPatches.
erase(groupPatchSet);
952 if (nMatch == groupPatchSet.size())
954 matchedGroups.append(iter.key());
956 else if (nMatch != 0)
959 nonGroupPatches.transfer(oldNonGroupPatches);
963 groups.transfer(matchedGroups);
974 const polyBoundaryMesh& bm = *
this;
976 bool hasError =
false;
986 if (!isA<processorPolyPatch>(bm[patchi]))
988 if (nonProci != patchi)
995 Pout<<
" ***Problem with boundary patch " << patchi
996 <<
" name:" << bm[patchi].
name()
997 <<
" type:" << bm[patchi].
type()
998 <<
" - seems to be preceeded by processor patches." 999 <<
" This is usually a problem." <<
endl;
1004 localNames[nonProci] = bm[patchi].
name();
1005 localTypes[nonProci] = bm[patchi].
type();
1010 localNames.resize(nonProci);
1011 localTypes.resize(nonProci);
1016 const globalIndex
procAddr(globalIndex::gatherNonLocal{}, nonProci);
1024 const auto procNames(allNames.slice(
procAddr.
range(proci)));
1025 const auto procTypes(allTypes.slice(
procAddr.
range(proci)));
1027 if (procNames != localNames || procTypes != localTypes)
1031 if (
debug || report)
1033 Info<<
" ***Inconsistent patches across processors, " 1034 "processor0 has patch names:" << localNames
1035 <<
" patch types:" << localTypes
1036 <<
" processor" << proci
1037 <<
" has patch names:" << procNames
1038 <<
" patch types:" << procTypes
1052 const polyBoundaryMesh& bm = *
this;
1054 bool hasError =
false;
1060 if (bm[patchi].start() != nextPatchStart && !hasError)
1064 Info<<
" ****Problem with boundary patch " << patchi
1065 <<
" named " << bm[patchi].name()
1066 <<
" of type " << bm[patchi].type()
1067 <<
". The patch should start on face no " << nextPatchStart
1068 <<
" and the patch specifies " << bm[patchi].start()
1070 <<
"Possibly consecutive patches have this same problem." 1071 <<
" Suppressing future warnings." <<
endl;
1074 if (!
patchNames.insert(bm[patchi].name()) && !hasError)
1078 Info<<
" ****Duplicate boundary patch " << patchi
1079 <<
" named " << bm[patchi].name()
1080 <<
" of type " << bm[patchi].type()
1082 <<
"Suppressing future warnings." <<
endl;
1085 nextPatchStart += bm[patchi].size();
1090 if (
debug || report)
1094 Pout<<
" ***Boundary definition is in error." <<
endl;
1098 Info<<
" Boundary definition OK." <<
endl;
1118 operator[](patchi).initMovePoints(pBufs,
p);
1121 pBufs.finishedSends();
1125 operator[](patchi).movePoints(pBufs,
p);
1133 pBufs.finishedSends();
1135 for (
const auto& schedEval : patchSchedule)
1137 const label patchi = schedEval.patch;
1141 operator[](patchi).initMovePoints(pBufs,
p);
1145 operator[](patchi).movePoints(pBufs,
p);
1154 neighbourEdgesPtr_.clear();
1155 patchIDPtr_.clear();
1156 groupIDsPtr_.clear();
1168 operator[](patchi).initUpdateMesh(pBufs);
1171 pBufs.finishedSends();
1175 operator[](patchi).updateMesh(pBufs);
1183 pBufs.finishedSends();
1185 for (
const auto& schedEval : patchSchedule)
1187 const label patchi = schedEval.patch;
1191 operator[](patchi).initUpdateMesh(pBufs);
1195 operator[](patchi).updateMesh(pBufs);
1205 const bool validBoundary
1216 patches[patchi].index() = patchi;
1232 for (
const polyPatch& pp :
patches)
1261 const word& patchName
1264 const label patchi = findPatchID(patchName);
1269 <<
"Patch named " << patchName <<
" not found." <<
nl 1270 <<
"Available patch names: " <<
names() <<
endl 1274 return operator[](patchi);
1280 const word& patchName
1283 const label patchi = findPatchID(patchName);
1288 <<
"Patch named " << patchName <<
" not found." <<
nl 1289 <<
"Available patch names: " <<
names() <<
endl 1293 return operator[](patchi);
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
virtual const fileName & name() const
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
labelList patchSizes() const
Return a list of patch sizes.
const List< labelPairList > & neighbourEdges() const
Per patch the edges on the neighbouring patch.
void size(const label n)
Older name for setAddressableSize.
autoPtr< IOobject > clone() const
Clone.
labelList findMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Extract list indices for all items with 'name()' that matches.
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Binary search to find the index of the last element in a sorted list that is less than value...
"blocking" : (MPI_Bsend, MPI_Recv)
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
virtual const fileName & name() const
The name of the stream.
labelList findMatchingStrings(const UnaryMatchPredicate &matcher, const UList< StringType > &input, const bool invert=false)
Extract list indices for all matches.
errorManipArg< error, int > exit(error &err, const int errNo=1)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
virtual bool check(const char *operation) const
Check IOstream status for given operation.
void setGroup(const word &groupName, const labelUList &patchIDs)
Set/add group with patches.
const word & name() const noexcept
Return the object name.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
A range or interval of labels defined by a start and a size.
constexpr char nl
The newline '\n' character (0x0a)
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
virtual bool writeData(Ostream &os) const
writeData member function required by regIOobject
void reorder(const labelUList &oldToNew, const bool validBoundary)
Reorders patches. Ordering does not have to be done in.
Ostream & endl(Ostream &os)
Add newline and flush stream.
const labelList & patchID() const
Per boundary face label the patch index.
static bool & parRun() noexcept
Test if this a parallel run.
void reorder(const labelUList &oldToNew, const bool check=false)
Reorder elements. Reordering must be unique (ie, shuffle).
wordList groupNames() const
A list of the group names (if any)
void clearGeom()
Clear geometry at this level and at patches.
static void reduceOr(bool &value, const label communicator=worldComm)
Logical (or) reduction (cf. MPI AllReduce)
Begin list [isseparator].
labelRange range() const noexcept
The face range for all boundary faces.
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Functions to operate on Pointer Lists.
A simple container for options an IOstream can normally have.
Operations on lists of strings.
wordList types() const
Return a list of patch types.
label nFaces() const noexcept
Number of mesh faces.
void movePoints(const pointField &p)
Correct polyBoundaryMesh after moving points.
UList< label > labelUList
A UList of labels.
labelRange range() const
Return start/size range of local processor data.
void resize(const label sz)
Resize the hash table for efficiency.
Extract name (as a word) from an object, typically using its name() method.
#define forAll(list, i)
Loop across all elements in list.
labelList indices(const wordRe &matcher, const bool useGroups=true) const
Return (sorted) patch indices for all matches.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
void matchGroups(const labelUList &patchIDs, wordList &groups, labelHashSet &nonGroupPatches) const
Match the patches to groups.
UPtrList< const labelUList > faceCells() const
Return a list of faceCells for each patch.
vectorField pointField
pointField is a vectorField.
const dimensionedScalar e
Elementary charge.
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
"scheduled" : (MPI_Send, MPI_Recv)
List< edge > edgeList
A List of edges.
A class for handling words, derived from Foam::string.
static word defaultRegion
Return the default region name.
bool checkDefinition(const bool report=false) const
Check boundary definition.
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of elements in the list.
virtual Ostream & endBlock()
Write end block group.
wordList patchNames(nPatches)
const globalMeshData & globalData() const
Return parallel info.
label nInternalFaces() const noexcept
Number of internal faces.
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
wordList physicalTypes() const
Return a list of physical types.
friend Ostream & operator(Ostream &os, const UPtrList< T > &list)
Write UPtrList to Ostream.
A HashTable similar to std::unordered_map.
List< labelPair > labelPairList
List of labelPairs.
const HashTable< labelList > & groupPatchIDs() const
The patch indices per patch group.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
errorManip< error > abort(error &err)
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
An Ostream is an abstract base class for all output systems (streams, files, token lists...
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
int debug
Static debugging option.
void updateMesh()
Correct polyBoundaryMesh after topology update.
Pair< label > labelPair
A pair of labels.
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
compressionType compression() const noexcept
Get the stream compression.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
labelList patchStarts() const
Return a list of patch start face indices.
labelRange subProcs() const noexcept
Range of process indices for addressed sub-offsets (processes)
void resize(const label newLen)
Adjust size of PtrList.
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
List< word > wordList
A List of words.
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
label nFaces() const noexcept
The number of boundary faces in the underlying mesh.
static commsTypes defaultCommsType
Default commsType.
labelPair whichPatchFace(const label faceIndex) const
Lookup mesh face index and return (patchi, patchFacei) tuple or (-1, meshFacei) for internal faces...
#define WarningInFunction
Report a warning using Foam::Warning.
globalIndex procAddr(aMesh.nFaces())
List< labelRange > patchRanges() const
Return a list of patch ranges.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
void clearAddressing()
Clear addressing at this level and at patches.
bool good() const noexcept
True if next operation might succeed.
const lduSchedule & patchSchedule() const noexcept
Order in which the patches should be initialised/evaluated corresponding to the schedule.
const polyBoundaryMesh & patches
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
"nonBlocking" : (MPI_Isend, MPI_Irecv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
static Ostream & output(Ostream &os, const IntRange< T > &range)
labelHashSet patchSet(const UList< wordRe > &patchNames, const bool warnNotFound=true, const bool useGroups=true) const
Return the set of patch IDs corresponding to the given names.
bool match(const std::string &text, bool literal=false) const
Smart match as regular expression or as a string.
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return pointer to a new patch created on freestore from components.
Mesh consisting of general polyhedral cells.
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
List< label > labelList
A List of labels.
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
A patch is a list of labels that address the faces in the global face list.
label nNonProcessor() const
The number of patches before the first processor patch.
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Defines the attributes of an object for which implicit objectRegistry management is supported...
List< bool > boolList
A List of bools.
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
bool isPattern() const noexcept
The wordRe is a pattern, not a literal string.
label findIndex(const wordRe &key) const
Return patch index for the first match, return -1 if not found.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Extract type (as a word) from an object, typically using its type() method.
forAllConstIters(mixture.phases(), phase)
label firstMatching(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Find first list item with 'name()' that matches, -1 on failure.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.