diff --git a/src/finiteArea/faMesh/faMesh.H b/src/finiteArea/faMesh/faMesh.H index b6515b510fa9fa999d9d9edc396f329ac69f9c41..9498c7ade34cfd1992a2a02d5ba30456585b5886 100644 --- a/src/finiteArea/faMesh/faMesh.H +++ b/src/finiteArea/faMesh/faMesh.H @@ -71,6 +71,7 @@ namespace Foam class faMeshLduAddressing; class faMeshMapper; class faPatchData; +template<class T> class LabelledItem; /*---------------------------------------------------------------------------*\ Class faMesh Declaration @@ -267,6 +268,12 @@ class faMesh // Helpers + //- Get the polyPatch pairs for the boundary edges (natural order) + List<LabelledItem<edge>> getBoundaryEdgePatchPairs + ( + const labelUList& meshEdges + ) const; + //- Create a single patch PtrList<faPatch> createOnePatch ( @@ -287,7 +294,8 @@ class faMesh void reorderProcEdges ( faPatchData& patchDef, - const labelUList& meshEdges + const labelUList& meshEdges, + const List<LabelledItem<edge>>& bndEdgePatchPairs ) const; diff --git a/src/finiteArea/faMesh/faMeshPatches.C b/src/finiteArea/faMesh/faMeshPatches.C index 765252c67060b406a89a0a4f3d1856b403ece54b..966f58299402e7c706a555c8b52ecc97c119ba4e 100644 --- a/src/finiteArea/faMesh/faMeshPatches.C +++ b/src/finiteArea/faMesh/faMeshPatches.C @@ -31,14 +31,84 @@ License #include "faPatchData.H" #include "processorPolyPatch.H" #include "processorFaPatch.H" +#include "globalMeshData.H" +#include "indirectPrimitivePatch.H" #include "edgeHashes.H" +#include "LabelledItem.H" + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Manage patch pairs with a 'labelled' edge. +// The edge first/second correspond to the owner/neighbour patches. +// The index is a face index on the neighbour patch (FUTURE). + +// Local typedefs + +typedef LabelledItem<edge> patchPairInfo; +typedef List<patchPairInfo> patchPairInfoList; +typedef UIndirectList<patchPairInfo> patchPairInfoUIndList; + + +// Synchronize edge patch pairs. +// - only propagate real (non-processor) patch ids + +struct syncEdgePatchPairs +{ + const label upperLimit; + + explicit syncEdgePatchPairs(const label nNonProcessor) + : + upperLimit(nNonProcessor) + {} + + void insert(edge& e, const label i) const + { + // This could probably be simpler + if (i >= 0 && i < upperLimit && !e.found(i)) + { + if (e.first() == -1) + { + e.first() = i; + } + else if (e.second() == -1) + { + e.second() = i; + } + else if (upperLimit < e.first()) + { + e.first() = i; + } + else if (upperLimit < e.second()) + { + e.second() = i; + } + } + } + + void operator()(edge& x, const edge& y) const + { + if (edge::compare(x, y) == 0) + { + insert(x, y.first()); + insert(x, y.second()); + } + } +}; + + +} // End namespace Foam + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::faMesh::reorderProcEdges ( faPatchData& patchDef, - const labelUList& meshEdges + const labelUList& meshEdges, + const List<LabelledItem<edge>>& bndEdgePatchPairs ) const { if (!patchDef.coupled() || patchDef.edgeLabels_.empty()) @@ -245,12 +315,181 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createOnePatch return createPatchList ( dictionary::null, - "", // Name for empty patch placeholder + word::null, // Name for empty patch placeholder &onePatchDict // Definitions for defaultPatch ); } +Foam::List<Foam::LabelledItem<Foam::edge>> +Foam::faMesh::getBoundaryEdgePatchPairs +( + const labelUList& meshEdges +) const +{ + const polyBoundaryMesh& pbm = mesh().boundaryMesh(); + const labelListList& edgeFaces = mesh().edgeFaces(); + + const label nInternalEdges = patch().nInternalEdges(); + const label nBoundaryEdges = patch().nBoundaryEdges(); + + // Map edges (mesh numbering) back to a boundary index + EdgeMap<label> edgeToBoundaryIndex(2*nBoundaryEdges); + + + // Use 'edge' for accounting + patchPairInfoList bndEdgePatchPairs(nBoundaryEdges); + + // Get pair of polyPatches for each boundary edge + for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei) + { + edgeToBoundaryIndex.insert + ( + patch().meshEdge(bndEdgei + nInternalEdges), + edgeToBoundaryIndex.size() + ); + + const label patchEdgei = (bndEdgei + nInternalEdges); + const label meshEdgei = meshEdges[patchEdgei]; + + patchPairInfo& patchPair = bndEdgePatchPairs[bndEdgei]; + + for (const label meshFacei : edgeFaces[meshEdgei]) + { + const label patchId = pbm.whichPatch(meshFacei); + + // Note: negative labels never insert + patchPair.insert(patchId); + } + } + + + // Synchronize edge information - we want the 'global' patch connectivity + + // Looks like PatchTools::matchEdges + + const indirectPrimitivePatch& cpp = mesh().globalData().coupledPatch(); + + labelList patchEdgeLabels(nBoundaryEdges); + labelList coupledEdgeLabels(nBoundaryEdges); + + { + label nMatches = 0; + forAll(cpp.edges(), coupledEdgei) + { + const edge coupledMeshEdge(cpp.meshEdge(coupledEdgei)); + + const auto iter = edgeToBoundaryIndex.cfind(coupledMeshEdge); + + if (iter.found()) + { + patchEdgeLabels[nMatches] = iter.val(); + coupledEdgeLabels[nMatches] = coupledEdgei; + ++nMatches; + } + } + + patchEdgeLabels.resize(nMatches); + coupledEdgeLabels.resize(nMatches); + } + + + const globalMeshData& globalData = mesh().globalData(); + const mapDistribute& map = globalData.globalEdgeSlavesMap(); + + //- Construct with all data + patchPairInfoList cppEdgeData(map.constructSize()); + + // Convert patch-edge data into cpp-edge data + patchPairInfoUIndList(cppEdgeData, coupledEdgeLabels) = + patchPairInfoUIndList(bndEdgePatchPairs, patchEdgeLabels); + + + // Also need to check for dangling edges, which are finiteArea + // boundary edges that only exist on one side of a proc boundary. + // Eg, proc boundary coincides with the end of the finiteArea + + { + boolList edgeInUse(map.constructSize(), false); + + for (const label coupledEdgei : coupledEdgeLabels) + { + edgeInUse[coupledEdgei] = true; + } + + // Retain pre-synchronized state for later xor + const boolList nonSyncEdgeInUse + ( + SubList<bool>(edgeInUse, cpp.nEdges()) + ); + + globalData.syncData + ( + edgeInUse, + globalData.globalEdgeSlaves(), + globalData.globalEdgeTransformedSlaves(), + map, + orEqOp<bool>() + ); + + // Check for anything coupled from the other side, + // but not originally from this. + // + // Process these dangling edges, obtain the attached pair + // of polyPatches for each. + // + // These edges have no finiteArea correspondence on this processor, + // but the information is obviously needed for other processors + + forAll(nonSyncEdgeInUse, coupledEdgei) + { + // Coupled, but originating from elsewhere + if (edgeInUse[coupledEdgei] && !nonSyncEdgeInUse[coupledEdgei]) + { + // Already default initialized + patchPairInfo& patchPair = cppEdgeData[coupledEdgei]; + + const label meshEdgei = + cpp.meshEdge + ( + coupledEdgei, + mesh().edges(), + mesh().pointEdges() + ); + + for (const label meshFacei : edgeFaces[meshEdgei]) + { + const label patchId = pbm.whichPatch(meshFacei); + + // Note: negative labels never insert + patchPair.insert(patchId); + } + } + } + } + + // Convert patch-edge data into cpp-edge data + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + globalData.syncData + ( + cppEdgeData, + globalData.globalEdgeSlaves(), + globalData.globalEdgeTransformedSlaves(), + map, + syncEdgePatchPairs(pbm.nNonProcessor()) + ); + + // Back from cpp-edge to patch-edge data + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + patchPairInfoUIndList(bndEdgePatchPairs, patchEdgeLabels) = + patchPairInfoUIndList(cppEdgeData, coupledEdgeLabels); + + return bndEdgePatchPairs; +} + + Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList ( const dictionary& bndDict, @@ -260,6 +499,13 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList { const polyBoundaryMesh& pbm = mesh().boundaryMesh(); + const labelListList& edgeFaces = mesh().edgeFaces(); + const labelList meshEdges + ( + patch().meshEdges(mesh().edges(), mesh().pointEdges()) + ); + + // Transcribe into patch definitions DynamicList<faPatchData> faPatchDefs(bndDict.size() + 4); for (const entry& dEntry : bndDict) @@ -327,47 +573,28 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList // ---------------------------------------------------------------------- - // Determine faPatch ID for each boundary edge. - // Result is in the bndEdgeFaPatchIDs list + const label nInternalEdges = patch().nInternalEdges(); + const label nBoundaryEdges = patch().nBoundaryEdges(); - const labelList meshEdges + patchPairInfoList bndEdgePatchPairs ( - patch().meshEdges(mesh().edges(), mesh().pointEdges()) + getBoundaryEdgePatchPairs(meshEdges) ); - const labelListList& edgeFaces = mesh().edgeFaces(); - - const label nInternalEdges = patch().nInternalEdges(); - const label nBoundaryEdges = patch().nBoundaryEdges(); - labelList bndEdgeFaPatchIDs(nBoundaryEdges, -1); for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei) { - const label patchEdgei = meshEdges[bndEdgei + nInternalEdges]; - - // Use 'edge' for accounting - edge curEdgePatchPair; + const patchPairInfo& patchPair = bndEdgePatchPairs[bndEdgei]; - for (const label meshFacei : edgeFaces[patchEdgei]) - { - const label polyPatchID = pbm.whichPatch(meshFacei); - - if (polyPatchID != -1) - { - curEdgePatchPair.insert(polyPatchID); - } - } - - - if (curEdgePatchPair.valid()) + if (patchPair.valid()) { // Non-negative, unique pairing // - find corresponding definition for (label patchi = 0; patchi < faPatchDefs.size(); ++patchi) { - if (faPatchDefs[patchi].foundPatchPair(curEdgePatchPair)) + if (faPatchDefs[patchi].foundPatchPair(patchPair)) { bndEdgeFaPatchIDs[bndEdgei] = patchi; break; @@ -535,12 +762,11 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList { if (patchDef.coupled()) { - reorderProcEdges(patchDef, meshEdges); - patchDef.neighPolyPatchId_ = -1; // No longer required + confusing + reorderProcEdges(patchDef, meshEdges, bndEdgePatchPairs); + patchDef.neighPolyPatchId_ = -1; // No lookup of neighbour faces } } - // Now convert list of definitions to list of patches label nPatches = 0;