42template<
class PatchType>
53 for (
const label patchEdgei : edgeIds)
55 const edge e(
p.meshEdge(patchEdgei));
59 <<
p.points()[
e.second()] <<
nl;
62 if (maxOutput > 0 && nOutput >= maxOutput)
64 os <<
" ... suppressing further output" <<
nl;
76Foam::faMesh::getBoundaryEdgeConnections()
const
100 label patchEdgei_ = -1;
101 label meshFacei_ = -1;
114 <<
"Determining required boundary edge connections, "
115 <<
"resolving locally attached boundary edges." <<
endl;
125 edgeToBoundaryIndex.insert
134 if (edgeFaces.size() != 1)
136 badEdges.insert(patchEdgei);
140 const label patchFacei = edgeFaces[0];
141 const label meshFacei = faceLabels_[patchFacei];
145 const label
patchId = pbm.patchID()[bndFacei];
149 auto& tuple = bndEdgeConnections[bndEdgei].first();
153 tuple.patchEdgei(patchEdgei);
154 tuple.meshFacei(meshFacei);
159 auto& pairing = patchPairings[bndEdgei];
163 pairing.patchEdgei_ = patchEdgei;
164 pairing.meshFacei_ = meshFacei;
168 if ((nBadEdges =
returnReduce(badEdges.size(), sumOp<label>())) > 0)
174 patch().localPoints(),
179 / (
"faMesh-construct.nonManifoldEdges")
190 <<
"Boundary edges not singly connected: "
201 <<
"(debug) wrote " <<
writer.output().name() <<
nl;
212 label nMissing = patchPairings.size();
216 if (!nMissing)
break;
218 const polyPatch& pp = pbm[patchi];
223 label patchEdgei = pp.nInternalEdges();
224 patchEdgei < pp.nEdges();
228 const label bndEdgei =
229 edgeToBoundaryIndex.lookup(pp.meshEdge(patchEdgei), -1);
235 auto& pairing = patchPairings[bndEdgei];
240 if (pairing.insert(patchi))
243 const labelList& edgeFaces = pp.edgeFaces()[patchEdgei];
245 if (edgeFaces.size() != 1)
247 pairing.erase(patchi);
248 badEdges.insert(badEdges.size());
252 const label patchFacei = edgeFaces[0];
253 const label meshFacei = patchFacei + pp.start();
256 pairing.patchEdgei_ = patchEdgei;
257 pairing.meshFacei_ = meshFacei;
260 if (!nMissing)
break;
266 if ((nBadEdges =
returnReduce(badEdges.size(), sumOp<label>())) > 0)
269 <<
"Had " << nBadEdges
270 <<
" boundary edges with missing or multiple edge connections"
278 const auto& pairing = patchPairings[bndEdgei];
279 const label nbrPatchi = pairing.second();
280 const label nbrPatchEdgei = pairing.patchEdgei_;
281 const label nbrMeshFacei = pairing.meshFacei_;
283 if (nbrMeshFacei >= 0)
286 auto& tuple = bndEdgeConnections[bndEdgei].second();
289 tuple.patchi(nbrPatchi);
290 tuple.patchEdgei(nbrPatchEdgei);
291 tuple.meshFacei(nbrMeshFacei);
308 nBadEdges = badEdges.size();
315 patch().localPoints(),
320 / (
"faMesh-construct.invalidEdges")
331 <<
"Boundary edges with missing/invalid neighbours: "
342 <<
"(debug) wrote " <<
writer.output().name() <<
nl;
349 return bndEdgeConnections;
358 <<
"Creating global coupling data" <<
endl;
362 const mapDistribute& map =
globalData.globalEdgeSlavesMap();
363 const label nCoupledEdges = cpp.nEdges();
366 List<bool> coupledEdgesUsed(map.constructSize(),
false);
369 for (label cppEdgei = 0; cppEdgei < nCoupledEdges; ++cppEdgei)
371 coupledEdgesUsed[cppEdgei] =
372 edgeToBoundaryIndex.found(cpp.meshEdge(cppEdgei));
376 <<
"Starting sync of boundary edge topology" <<
endl;
390 for (label cppEdgei = 0; cppEdgei < nCoupledEdges; ++cppEdgei)
392 if (coupledEdgesUsed[cppEdgei])
401 <<
" connected boundary edges (total, some duplicates)" <<
endl;
407 List<DynamicList<patchTuple, 2>> gatheredConnections(map.constructSize());
410 EdgeMap<label> edgeToCoupledIndex(2*nCoupledEdges);
417 for (label cppEdgei = 0; cppEdgei < nCoupledEdges; ++cppEdgei)
419 if (coupledEdgesUsed[cppEdgei])
421 const edge meshEdge(cpp.meshEdge(cppEdgei));
423 const label bndEdgei =
424 edgeToBoundaryIndex.lookup(meshEdge, -1);
430 auto& gathered = gatheredConnections[cppEdgei];
431 gathered.setCapacity(2);
433 auto& tuple = gathered.last();
435 tuple = bndEdgeConnections[bndEdgei].first();
442 edgeToCoupledIndex.insert(meshEdge, cppEdgei);
454 if (edgeToCoupledIndex.empty())
break;
456 const polyPatch& pp = pbm[patchi];
461 label patchEdgei = pp.nInternalEdges();
462 patchEdgei < pp.nEdges();
466 const edge meshEdge(pp.meshEdge(patchEdgei));
468 const label cppEdgei =
469 edgeToCoupledIndex.lookup(meshEdge, -1);
476 const labelList& edgeFaces = pp.edgeFaces()[patchEdgei];
478 if (edgeFaces.size() != 1)
480 badEdges.insert(cppEdgei);
484 const label patchFacei = edgeFaces[0];
485 const label meshFacei = patchFacei + pp.start();
487 auto& gathered = gatheredConnections[cppEdgei];
488 gathered.setCapacity(2);
490 auto& tuple = gathered.last();
493 tuple.patchi(patchi);
494 tuple.patchEdgei(patchEdgei);
495 tuple.meshFacei(meshFacei);
498 edgeToCoupledIndex.erase(meshEdge);
500 if (edgeToCoupledIndex.empty())
break;
505 if ((nBadEdges =
returnReduce(badEdges.size(), sumOp<label>())) > 0)
508 <<
"Had " << nBadEdges <<
" coupled boundary edges"
509 <<
" with missing or multiple edge connections"
514 <<
"Starting sync of boundary edge information" <<
endl;
522 ListOps::appendEqOp<patchTuple>()
527 <<
"Collating sync information" <<
endl;
530 for (label cppEdgei = 0; cppEdgei < nCoupledEdges; ++cppEdgei)
532 const auto& gathered = gatheredConnections[cppEdgei];
534 const label bndEdgei =
535 edgeToBoundaryIndex.lookup(cpp.meshEdge(cppEdgei), -1);
543 && gathered.size() == 2
546 const auto& a = gathered[0];
547 const auto&
b = gathered[1];
550 auto& connection = bndEdgeConnections[bndEdgei];
552 connection.second() = (connection.first() ==
b) ? a :
b;
560 const auto& connection = bndEdgeConnections[bndEdgei];
562 if (!connection.second().valid())
575 patch().localPoints(),
576 patch().boundaryEdges(),
580 / (
"faMesh-construct.boundaryEdges")
595 const auto& connection = bndEdgeConnections[bndEdgei];
597 neighProc[bndEdgei] = connection.second().procNo();
598 neighPatch[bndEdgei] = connection.second().patchi();
601 writer.write(
"neighProc", neighProc);
602 writer.write(
"neighPatch", neighPatch);
613 / (
"faMesh-construct.faPatch")
626 if ((nBadEdges =
returnReduce(badEdges.size(), sumOp<label>())) > 0)
632 patch().localPoints(),
637 / (
"faMesh-construct.invalidEdges")
648 <<
"Boundary edges with missing/invalid neighbours: "
659 <<
"(debug) wrote " <<
writer.output().name() <<
nl;
669 <<
"Return sorted list of boundary connections" <<
endl;
671 return bndEdgeConnections;
675void Foam::faMesh::setBoundaryConnections
677 const List<Pair<patchTuple>>& bndEdgeConnections
680 const label nInternalEdges =
patch().nInternalEdges();
681 const label nBoundaryEdges =
patch().nBoundaryEdges();
683 if (bndEdgeConnections.size() != nBoundaryEdges)
686 <<
"Sizing mismatch. Expected " << nBoundaryEdges
687 <<
" boundary edge connections, but had "
688 << bndEdgeConnections.size() <<
nl
694 new List<labelPair>(nBoundaryEdges,
labelPair(-1,-1))
696 auto& bndConnect = *bndConnectPtr_;
698 for (
const auto& connection : bndEdgeConnections)
700 const auto& a = connection.first();
701 const auto&
b = connection.second();
703 if (a.is_finiteArea() && a.is_localProc())
705 const label bndEdgei = (a.patchEdgei() - nInternalEdges);
707 bndConnect[bndEdgei].
first() =
b.procNo();
708 bndConnect[bndEdgei].second() =
b.meshFacei();
710 else if (
b.is_finiteArea() &&
b.is_localProc())
712 const label bndEdgei = (
b.patchEdgei() - nInternalEdges);
714 bndConnect[bndEdgei].
first() = a.procNo();
715 bndConnect[bndEdgei].second() = a.meshFacei();
720 <<
"Unexpected pairing input " << connection
721 <<
" ... programming error" <<
nl
727 for (
const auto& connection : bndConnect)
729 if (connection.first() < 0 || connection.second() < 0)
737 reduce(nInvalid, sumOp<label>());
743 <<
"Did not properly match " << nInvalid
744 <<
" boundary edges" <<
nl
750void Foam::faMesh::calcBoundaryConnections()
const
752 setBoundaryConnections(this->getBoundaryEdgeConnections());
760 const auto& connections = this->boundaryConnections();
764 for (
const labelPair& tuple : connections)
766 procsUsed.
insert(tuple.first());
778 const auto& connections = this->boundaryConnections();
782 for (
const labelPair& tuple : connections)
784 ++procCount(tuple.first());
792 for (
const label proci : procCount.
sortedToc())
794 output[count].first() = proci;
795 output[count].second() = procCount[proci];
814void Foam::faMesh::calcHaloFaceGeometry()
const
816 if (haloFaceCentresPtr_ || haloFaceNormalsPtr_)
819 <<
"Halo centres/normals already calculated"
824 <<
"Calculating halo face centres/normals" <<
endl;
829 const faMeshBoundaryHalo& halo = boundaryHaloMap();
831 const labelList& inputFaceIds = halo.inputMeshFaces();
836 auto& centres = *haloFaceCentresPtr_;
837 auto& normals = *haloFaceNormalsPtr_;
839 centres.
resize(inputFaceIds.size());
840 normals.resize(inputFaceIds.size());
845 const face&
f = faces[inputFaceIds[i]];
848 normals[i] =
f.unitNormal(
points);
852 halo.distributeSparse(centres);
853 halo.distributeSparse(normals);
859 if (!haloFaceCentresPtr_ || !haloFaceNormalsPtr_)
861 calcHaloFaceGeometry();
864 return *haloFaceCentresPtr_;
870 if (!haloFaceCentresPtr_ || !haloFaceNormalsPtr_)
872 calcHaloFaceGeometry();
875 return *haloFaceNormalsPtr_;
882 if (patchi < 0 || patchi >=
boundary().size())
885 <<
"Patch " << patchi <<
" is out-of-range 0.."
896 this->haloFaceCentres(),
907 if (patchi < 0 || patchi >=
boundary().size())
910 <<
"Patch " << patchi <<
" is out-of-range 0.."
921 this->haloFaceNormals(),
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
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.
label size() const noexcept
The number of elements in table.
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
void resize(const label len)
Adjust allocated size of list.
void clear()
Clear the list, i.e. set size to zero.
A HashTable to objects of type <T> with a label key.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
label nBoundaryEdges() const
Number of boundary edges == (nEdges() - nInternalEdges())
label nInternalEdges() const
Number of internal edges.
edge meshEdge(const label edgei) const
From patch edge to global edge using meshPoints.
const labelListList & edgeFaces() const
Return edge-face addressing.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
T & first()
Return the first element of the list.
void size(const label n)
Older name for setAddressableSize.
static bool & parRun() noexcept
Test if this a parallel run.
static int debug
Debug switch.
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
void clear()
'Clears' edge by setting both ends to invalid point labels.
void sort()
Sort element lists numerically.
Class for obtaining halo face data for the boundary edges. The ordering follows that natural edge ord...
void reset(const faMesh &mesh)
Redefine map and connectivity for a mesh.
const vectorField & haloFaceNormals() const
Face normals of boundary halo neighbours.
const Time & time() const
Return reference to time.
const pointField & haloFaceCentres() const
Face centres of boundary halo neighbours.
label nBoundaryEdges() const noexcept
Number of boundary edges (== nEdges - nInternalEdges)
const polyMesh & mesh() const
Return access to polyMesh.
const edgeList & edges() const noexcept
Return local edges with reordered boundary.
const uindirectPrimitivePatch & patch() const
Return constant reference to primitive patch.
label nInternalEdges() const noexcept
Number of internal faces.
const faGlobalMeshData & globalData() const
Return parallel info.
labelList boundaryProcs() const
List< labelPair > boundaryProcSizes() const
const faMeshBoundaryHalo & boundaryHaloMap() const
Mapping/swapping for boundary halo neighbours.
static void syncData(List< Type > &elems, const labelListList &slaves, const labelListList &transformedSlaves, const mapDistribute &slavesMap, const globalIndexAndTransform &, const CombineOp &cop, const TransformOp &top)
Helper: synchronise data with transforms.
virtual const faceList & faces() const
Return raw faces.
const globalMeshData & globalData() const
Return parallel info.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
virtual const pointField & points() const
Return raw points.
label nInternalFaces() const noexcept
Number of internal faces.
int myProcNo() const noexcept
Return processor number.
A class for managing temporary objects.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
const label nNonProcessor
#define DebugInFunction
Report an information message using Foam::Info.
#define InfoInFunction
Report an information message using Foam::Info.
const std::string patch
OpenFOAM patch number as a std::string.
GenericPatchWriter< uindirectPrimitivePatch > uindirectPatchWriter
Write uindirectPrimitivePatch faces/points (optionally with fields) as a vtp file or a legacy vtk fil...
Pair< label > labelPair
A pair of labels.
List< label > labelList
A List of labels.
vectorField pointField
pointField is a vectorField.
Ostream & endl(Ostream &os)
Add newline and flush stream.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
static void printPatchEdges(Ostream &os, const PatchType &p, const labelList &edgeIds, label maxOutput=10)
errorManip< error > abort(error &err)
static Ostream & output(Ostream &os, const IntRange< T > &range)
Field< vector > vectorField
Specialisation of Field<T> for vector.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
List< edge > edgeList
A List of edges.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
List< face > faceList
A List of faces.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
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.