43template<
class PatchType>
52 edgeList dumpEdges(
p.edges(), selectEdges);
77 const bool validBoundary
83 <<
"boundary already exists"
87 globalMeshDataPtr_.reset(
nullptr);
89 boundary_.transfer(plist);
91 setPrimitiveMeshData();
95 boundary_.checkDefinition();
102 const List<faPatch*>&
p,
103 const bool validBoundary
109 addFaPatches(plist, validBoundary);
115 const word& patchName,
116 const word& patchType
120 if (!patchName.empty())
122 onePatchDict.add(
"name", patchName);
124 if (!patchType.empty())
126 onePatchDict.add(
"type", patchType);
129 return createPatchList
141 const word& emptyPatchName,
149 for (
const entry& dEntry : bndDict)
151 if (!dEntry.isDict())
154 <<
"Not a dictionary entry: " << dEntry.name() <<
nl;
160 auto& patchDef = faPatchDefs.emplace_back();
161 patchDef.name_ = dEntry.keyword();
162 patchDef.type_ = patchDict.get<
word>(
"type");
167 if (patchDict.readIfPresent(
"ownerPolyPatch", patchName))
170 if (patchDef.ownerPolyPatchId_ < 0)
173 <<
"ownerPolyPatch " << patchName <<
" not found"
179 patchDict.readEntry(
"neighbourPolyPatch", patchName);
182 if (patchDef.neighPolyPatchId_ < 0)
185 <<
"neighbourPolyPatch " << patchName <<
" not found"
192 if (!emptyPatchName.empty())
194 auto& patchDef = faPatchDefs.emplace_back();
195 patchDef.name_ = emptyPatchName;
196 patchDef.type_ = emptyFaPatch::typeName_();
199 label nWarnUndefinedPatch(5);
202 const label undefPatchIndex = faPatchDefs.size();
204 auto& patchDef = faPatchDefs.emplace_back();
205 patchDef.name_ =
"undefined";
206 patchDef.type_ =
"patch";
208 if (defaultPatchDefinition)
212 (*defaultPatchDefinition).readIfPresent(
"name", patchDef.name_)
217 nWarnUndefinedPatch = 0;
219 (*defaultPatchDefinition).readIfPresent(
"type", patchDef.type_);
224 const label ignorePatchIndex = faPatchDefs.size();
226 auto& patchDef = faPatchDefs.emplace_back();
227 patchDef.name_ =
"_ignore_edges_";
228 patchDef.type_ = ignoreFaPatch::typeName_();
236 this->getBoundaryEdgeConnections()
240 this->setBoundaryConnections(bndEdgeConnections);
244 labelList patchDefLookup(bndEdgeConnections.size(), -1);
251 forAll(bndEdgeConnections, connecti)
254 const auto& a = connection.
first();
255 const auto&
b = connection.second();
259 if (!a.valid() || !
b.valid())
262 patchDefLookup[connecti] = ignorePatchIndex;
263 patchDefsUsed.insert(ignorePatchIndex);
266 else if (a.is_finiteArea())
268 if (
b.is_finiteArea())
272 if (a.procNo() ==
b.procNo())
276 <<
"Processor-processor addressing error:" <<
nl
277 <<
"Both connections have the same processor: "
279 <<
"Connecting patches "
280 << a.realPatchi() <<
" and " <<
b.realPatchi() <<
nl
283 else if (a.is_localProc())
285 procConnections(
b.procNo()).insert(connecti);
289 procConnections(a.procNo()).insert(connecti);
294 else if (a.is_localProc())
296 patchPair.first() = a.realPatchi();
297 patchPair.second() =
b.realPatchi();
300 else if (
b.is_finiteArea() &&
b.is_localProc())
302 patchPair.first() =
b.realPatchi();
303 patchPair.second() = a.realPatchi();
310 label bestPatchDefi = -1;
312 const label nPatchDefs = (patchPair.valid() ? faPatchDefs.size() : 0);
314 for (label patchDefi = 0; patchDefi < nPatchDefs; ++patchDefi)
316 const int match = faPatchDefs[patchDefi].matchPatchPair(patchPair);
320 bestPatchDefi = patchDefi;
323 else if (match == 2 && bestPatchDefi < 0)
326 bestPatchDefi = patchDefi;
330 if (bestPatchDefi < 0)
332 bestPatchDefi = undefPatchIndex;
335 patchDefLookup[connecti] = bestPatchDefi;
336 patchDefsUsed.
insert(bestPatchDefi);
340 bool reportBadEdges =
false;
345 faPatchDefs[undefPatchIndex].clear();
349 patchDefsUsed.insert(undefPatchIndex);
350 reportBadEdges =
true;
356 faPatchDefs[ignorePatchIndex].clear();
360 patchDefsUsed.insert(ignorePatchIndex);
361 reportBadEdges =
true;
368 forAll(patchDefLookup, connecti)
370 if (patchDefLookup[connecti] == undefPatchIndex)
372 const auto& connection = bndEdgeConnections[connecti];
374 const auto& a = connection.first();
375 const auto&
b = connection.second();
377 if (a.is_localProc() && a.is_finiteArea())
381 else if (
b.is_localProc() &&
b.is_finiteArea())
388 Pout<<
"Undefined connection: "
389 <<
"(patch:" << a.realPatchi()
390 <<
" face:" << a.meshFacei()
391 <<
" proc:" << a.procNo()
392 <<
") and (patch:" <<
b.realPatchi()
393 <<
" face:" <<
b.meshFacei()
394 <<
" proc:" <<
b.procNo()
423 <<
" undefined edge connections, added to defaultPatch: "
424 << faPatchDefs[undefPatchIndex].name_ <<
nl <<
nl
425 <<
"==> Could indicate a non-manifold patch geometry" <<
nl
428 if (nWarnUndefinedPatch)
437 thisDb().time().globalPath(),
451 forAll(patchDefLookup, connecti)
453 if (patchDefLookup[connecti] == ignorePatchIndex)
455 const auto& connection = bndEdgeConnections[connecti];
457 const auto& a = connection.first();
458 const auto&
b = connection.second();
460 if (a.is_localProc() && a.is_finiteArea())
464 else if (
b.is_localProc() &&
b.is_finiteArea())
471 Pout<<
"Illegal connection: "
472 <<
"(patch:" << a.realPatchi()
473 <<
" face:" << a.meshFacei()
474 <<
" proc:" << a.procNo()
475 <<
") and (patch:" <<
b.realPatchi()
476 <<
" face:" <<
b.meshFacei()
477 <<
" proc:" <<
b.procNo()
506 <<
" illegal edge connections, added to "
507 << faPatchDefs[ignorePatchIndex].name_ <<
nl <<
nl
508 <<
"==> Could indicate a non-manifold patch geometry" <<
nl
511 if (nWarnUndefinedPatch)
520 thisDb().time().globalPath(),
533 procToDefLookup.reserve(procConnections.size());
534 faPatchDefs.reserve(faPatchDefs.size() + procConnections.size());
536 for (
const label otherProci : procConnections.sortedToc())
538 const label patchDefi = faPatchDefs.size();
539 procToDefLookup.insert(otherProci, patchDefi);
542 auto& patchDef = faPatchDefs.emplace_back();
553 label nOffProcessorEdges = 0;
555 for (
const label patchDefi : patchDefsUsed.sortedToc())
557 auto& patchDef = faPatchDefs[patchDefi];
563 forAll(patchDefLookup, connecti)
565 if (patchDefLookup[connecti] == patchDefi)
567 const auto& a = bndEdgeConnections[connecti].first();
568 const auto&
b = bndEdgeConnections[connecti].second();
570 if (a.is_localProc() && a.is_finiteArea())
572 selectEdges.push_back(a.patchEdgei());
574 else if (
b.is_localProc() &&
b.is_finiteArea())
576 selectEdges.push_back(
b.patchEdgei());
578 else if (a.valid() &&
b.valid())
581 <<
"Error in programming logic" <<
nl
585 if (a.is_localProc() !=
b.is_localProc())
587 ++nOffProcessorEdges;
590 patchDefLookup[connecti] = -2;
598 patchDef.edgeLabels_ = selectEdges;
603 Pout<<
"Had " << nOffProcessorEdges
604 <<
" patch edges connected off-processor" <<
endl;
609 <<
" patch edges connected off-processor" <<
endl;
614 for (
const label otherProci : procToDefLookup.sortedToc())
616 const label patchDefi = procToDefLookup[otherProci];
618 auto& patchDef = faPatchDefs[patchDefi];
624 for (
const label connecti : procConnections(otherProci).
sortedToc())
626 const auto& connection = bndEdgeConnections[connecti];
627 const auto& a = connection.first();
628 const auto&
b = connection.second();
630 if (a.is_localProc())
632 selectEdges.push_back(a.patchEdgei());
634 else if (
b.is_localProc())
636 selectEdges.push_back(
b.patchEdgei());
641 <<
"Error in programming logic" <<
nl
645 patchDefLookup[connecti] = -2;
651 patchDef.edgeLabels_ = selectEdges;
662 if (!patchDef.good())
673 patchDef.dict(
false),
680 newPatches[
nPatches].resetEdges(std::move(patchDef.edgeLabels_));
688 Pout<<
"Created new finiteArea patches:" <<
nl;
692 <<
" name:" <<
p.
name()
693 <<
" type:" <<
p.type() <<
nl;
697 Pout<<
"addressed: " << nTotal
698 <<
'/' <<
patch().nBoundaryEdges() <<
" edges" <<
endl;
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edgesCentres")))
const polyBoundaryMesh & pbm
labelHashSet badEdges(pp.nEdges()/20)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
bool empty() const noexcept
label size() const noexcept
The number of elements in table.
void clear()
Remove all entries from table.
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 HashTable to objects of type <T> with a label key.
An ordered pair of two objects of type <T> with first() and second() elements.
const T & first() const noexcept
Access the first element.
void size(const label n)
Older name for setAddressableSize.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
bool insert(const label vertex)
Fill any open slot with the vertex label (if not previously contained in the edge).
A keyword and a list of tokens is an 'entry'.
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
void addFaPatches(faPatchList &plist, const bool validBoundary=true)
Add boundary patches. Constructor helper.
Helper class for holding data during faPatch construction. Most data members are exposed at the momen...
Finite area patch class. Used for 2-D non-Euclidian finite area method.
static autoPtr< faPatch > New(const word &name, const dictionary &dict, const label index, const faBoundaryMesh &bm)
Return pointer to a new patch created on freestore from dictionary.
A class for handling file names.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Write edge/points (optionally with fields) as a vtp file or a legacy vtk file.
A class for handling words, derived from Foam::string.
static const word null
An empty word.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
word outputName("finiteArea-edges.obj")
#define WarningInFunction
Report a warning using Foam::Warning.
#define InfoInFunction
Report an information message using Foam::Info.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to 'true' entries.
Namespace for handling debugging switches.
const std::string patch
OpenFOAM patch number as a std::string.
bool match(const UList< wordRe > &selectors, const std::string &text)
True if text matches one of the selector expressions.
List< edge > edgeList
List of edge.
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< label > labelList
A List of labels.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
static void vtkWritePatchEdges(const PatchType &p, const labelList &selectEdges, const fileName &outputPath, const word &outputName)
messageStream Info
Information stream (stdout output on master, null elsewhere).
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
void sort(UList< T > &list)
Sort the list.
errorManip< error > abort(error &err)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
PtrList< faPatch > faPatchList
Store lists of faPatch as a PtrList.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.