mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: improved handling of dangling finiteArea edges (#2084)
- restrict searching to patch quantities to avoid triggering mesh edge calculations
This commit is contained in:
@ -269,10 +269,7 @@ class faMesh
|
|||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
//- Get the polyPatch pairs for the boundary edges (natural order)
|
//- Get the polyPatch pairs for the boundary edges (natural order)
|
||||||
List<LabelledItem<edge>> getBoundaryEdgePatchPairs
|
List<LabelledItem<edge>> getBoundaryEdgePatchPairs() const;
|
||||||
(
|
|
||||||
const labelUList& meshEdges
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Create a single patch
|
//- Create a single patch
|
||||||
PtrList<faPatch> createOnePatch
|
PtrList<faPatch> createOnePatch
|
||||||
@ -294,7 +291,6 @@ class faMesh
|
|||||||
void reorderProcEdges
|
void reorderProcEdges
|
||||||
(
|
(
|
||||||
faPatchData& patchDef,
|
faPatchData& patchDef,
|
||||||
const labelUList& meshEdges,
|
|
||||||
const List<LabelledItem<edge>>& bndEdgePatchPairs
|
const List<LabelledItem<edge>>& bndEdgePatchPairs
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|||||||
@ -52,53 +52,125 @@ typedef List<patchPairInfo> patchPairInfoList;
|
|||||||
typedef UIndirectList<patchPairInfo> patchPairInfoUIndList;
|
typedef UIndirectList<patchPairInfo> patchPairInfoUIndList;
|
||||||
|
|
||||||
|
|
||||||
// Synchronize edge patch pairs.
|
// Handling of dangling coupled edges.
|
||||||
// - only propagate real (non-processor) patch ids
|
// Tag values to "push" with special -(patchId+2)
|
||||||
|
struct combineDanglingEdge
|
||||||
struct syncEdgePatchPairs
|
|
||||||
{
|
{
|
||||||
const label upperLimit;
|
const label upperLimit;
|
||||||
|
|
||||||
explicit syncEdgePatchPairs(const label nNonProcessor)
|
// Set dangling patchId from real patchId
|
||||||
|
static void setDangling(patchPairInfo& pairing, const label patchId)
|
||||||
|
{
|
||||||
|
pairing.first() = pairing.second() = -(patchId + 2);
|
||||||
|
pairing.setIndex(-1); // Invalidate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert dangling patchId to real patchId
|
||||||
|
static void correct(patchPairInfo& pairing)
|
||||||
|
{
|
||||||
|
if (pairing.first() < -1)
|
||||||
|
{
|
||||||
|
pairing.first() = -(pairing.first() + 2);
|
||||||
|
}
|
||||||
|
if (pairing.second() < -1)
|
||||||
|
{
|
||||||
|
pairing.second() = -(pairing.second() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Construct with upper limit (the number of non-processor patches)
|
||||||
|
explicit combineDanglingEdge(const label nNonProcessor)
|
||||||
:
|
:
|
||||||
upperLimit(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
|
// Combine operation: overwrite unused or processor patches with
|
||||||
|
// 'dangling' patch information only
|
||||||
|
void operator()(patchPairInfo& x, const patchPairInfo& y) const
|
||||||
{
|
{
|
||||||
if (edge::compare(x, y) == 0)
|
if (y.first() < -1 && edge::compare(x, y) == 0)
|
||||||
{
|
{
|
||||||
insert(x, y.first());
|
if (x.first() == -1 || x.first() >= upperLimit)
|
||||||
insert(x, y.second());
|
{
|
||||||
|
x.first() = y.first();
|
||||||
|
}
|
||||||
|
if (x.second() == -1 || x.second() >= upperLimit)
|
||||||
|
{
|
||||||
|
x.second() = y.first();
|
||||||
|
x.index() = y.index();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Populate patch pairings according to the boundary edges
|
||||||
|
void findEdgePatchPairing
|
||||||
|
(
|
||||||
|
const polyBoundaryMesh& pbm,
|
||||||
|
const EdgeMap<label>& edgeToIndex,
|
||||||
|
patchPairInfoList& patchPairs,
|
||||||
|
label nMissing = -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Count how many slots (both sides) to be filled
|
||||||
|
if (nMissing < 0)
|
||||||
|
{
|
||||||
|
nMissing = 0;
|
||||||
|
for (const patchPairInfo& pairing : patchPairs)
|
||||||
|
{
|
||||||
|
if (pairing.first() == -1) ++nMissing;
|
||||||
|
if (pairing.second() == -1) ++nMissing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(pbm, patchID)
|
||||||
|
{
|
||||||
|
if (!nMissing) break; // Everything filled
|
||||||
|
|
||||||
|
const polyPatch& pp = pbm[patchID];
|
||||||
|
|
||||||
|
const bool isProcPatch = isA<processorPolyPatch>(pp);
|
||||||
|
|
||||||
|
// Examine neighbour boundary edges
|
||||||
|
for (label edgei = pp.nInternalEdges(); edgei < pp.nEdges(); ++edgei)
|
||||||
|
{
|
||||||
|
// Lookup global edge of this neighbour,
|
||||||
|
// find matching owner boundary edge
|
||||||
|
|
||||||
|
const label edgeIndex =
|
||||||
|
edgeToIndex.lookup(pp.meshEdge(edgei), -1);
|
||||||
|
|
||||||
|
if (edgeIndex != -1)
|
||||||
|
{
|
||||||
|
// Add patchId.
|
||||||
|
// - hash-like so will only insert once
|
||||||
|
// - also add in the attached patch face (there is only one),
|
||||||
|
// saved in mesh face numbering for processor patches
|
||||||
|
|
||||||
|
patchPairInfo& pairing = patchPairs[edgeIndex];
|
||||||
|
|
||||||
|
if (pairing.insert(patchID))
|
||||||
|
{
|
||||||
|
if (isProcPatch)
|
||||||
|
{
|
||||||
|
// Save the mesh face
|
||||||
|
|
||||||
|
const label patchFacei = pp.edgeFaces()[edgei][0];
|
||||||
|
|
||||||
|
pairing.index() = (pp.start() + patchFacei);
|
||||||
|
}
|
||||||
|
|
||||||
|
--nMissing;
|
||||||
|
|
||||||
|
if (!nMissing) break; // Early exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +179,6 @@ struct syncEdgePatchPairs
|
|||||||
void Foam::faMesh::reorderProcEdges
|
void Foam::faMesh::reorderProcEdges
|
||||||
(
|
(
|
||||||
faPatchData& patchDef,
|
faPatchData& patchDef,
|
||||||
const labelUList& meshEdges,
|
|
||||||
const List<LabelledItem<edge>>& bndEdgePatchPairs
|
const List<LabelledItem<edge>>& bndEdgePatchPairs
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -117,38 +188,45 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
}
|
}
|
||||||
|
|
||||||
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
||||||
const labelListList& edgeFaces = mesh().edgeFaces();
|
|
||||||
|
const label procPatchID = patchDef.neighPolyPatchId_;
|
||||||
|
|
||||||
|
const auto* procPatch = isA<processorPolyPatch>(pbm[procPatchID]);
|
||||||
|
|
||||||
|
if (!procPatch)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Internal addressing error. Patch " << procPatchID
|
||||||
|
<< " is not a processor patch" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
// Reorder processor edges using order of neighbour processorPolyPatch
|
// Reorder processor edges using order of neighbour processorPolyPatch
|
||||||
|
|
||||||
const label procPatchID = patchDef.neighPolyPatchId_;
|
|
||||||
const label nProcEdges = patchDef.edgeLabels_.size();
|
const label nProcEdges = patchDef.edgeLabels_.size();
|
||||||
|
|
||||||
labelList procFaces(nProcEdges, -1);
|
labelList procFaces(nProcEdges, -1);
|
||||||
|
|
||||||
forAll(procFaces, edgei)
|
forAll(procFaces, edgei)
|
||||||
{
|
{
|
||||||
const label localEdgei = patchDef.edgeLabels_[edgei];
|
const label bndEdgei =
|
||||||
const label meshEdgei = meshEdges[localEdgei];
|
(patchDef.edgeLabels_[edgei] - patch().nInternalEdges());
|
||||||
|
|
||||||
for (const label meshFacei : edgeFaces[meshEdgei])
|
procFaces[edgei] = bndEdgePatchPairs[bndEdgei].index();
|
||||||
{
|
|
||||||
if
|
|
||||||
(
|
|
||||||
!faceLabels_.found(meshFacei)
|
|
||||||
&& (procPatchID == pbm.whichPatch(meshFacei))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// The edge's proc-face
|
|
||||||
procFaces[edgei] = meshFacei;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ascending proc-face numbering
|
// Ascending proc-face numbering
|
||||||
const labelList sortIndices(Foam::sortedOrder(procFaces));
|
const labelList sortIndices(Foam::sortedOrder(procFaces));
|
||||||
|
|
||||||
|
if (procFaces.size() && procFaces[sortIndices[0]] < 0)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Internal addressing error. Patch " << procPatchID
|
||||||
|
<< " with negative face" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const labelList& oldEdgeLabels = patchDef.edgeLabels_;
|
const labelList& oldEdgeLabels = patchDef.edgeLabels_;
|
||||||
labelList newEdgeLabels(oldEdgeLabels.size());
|
labelList newEdgeLabels(oldEdgeLabels.size());
|
||||||
|
|
||||||
@ -161,14 +239,14 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
|
|
||||||
for (label edgei = 0; edgei < nProcEdges; /*nil*/)
|
for (label edgei = 0; edgei < nProcEdges; /*nil*/)
|
||||||
{
|
{
|
||||||
const label procFacei = procFaces[sortIndices[edgei]];
|
const label meshFacei = procFaces[sortIndices[edgei]];
|
||||||
|
|
||||||
// Find all identical faces
|
// Find all identical faces
|
||||||
label endEdgei = edgei + 1; // one beyond
|
label endEdgei = edgei + 1; // one beyond
|
||||||
while
|
while
|
||||||
(
|
(
|
||||||
(endEdgei < nProcEdges)
|
(endEdgei < nProcEdges)
|
||||||
&& (procFacei == procFaces[sortIndices[endEdgei]])
|
&& (meshFacei == procFaces[sortIndices[endEdgei]])
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
++endEdgei;
|
++endEdgei;
|
||||||
@ -184,16 +262,16 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
{
|
{
|
||||||
multihit.clear();
|
multihit.clear();
|
||||||
|
|
||||||
// Map from global edge to local edgeId
|
// Map from global edge to patch local edgeId
|
||||||
for (label i = edgei; i < endEdgei; ++i)
|
for (label i = edgei; i < endEdgei; ++i)
|
||||||
{
|
{
|
||||||
label localEdgei = oldEdgeLabels[sortIndices[i]];
|
const label patchEdgei = oldEdgeLabels[sortIndices[i]];
|
||||||
label meshEdgei = meshEdges[localEdgei];
|
|
||||||
|
|
||||||
|
// The edge in mesh numbering
|
||||||
multihit.insert
|
multihit.insert
|
||||||
(
|
(
|
||||||
mesh().edges()[meshEdgei],
|
patch().meshEdge(patchEdgei),
|
||||||
localEdgei
|
patchEdgei
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +285,7 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
const face& f = mesh().faces()[procFacei];
|
const face& f = mesh().faces()[meshFacei];
|
||||||
|
|
||||||
forAll(f, fedgei) // Note size() == nEdges()
|
forAll(f, fedgei) // Note size() == nEdges()
|
||||||
{
|
{
|
||||||
@ -234,7 +312,7 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Missed " << (edgei < endEdgei)
|
<< "Missed " << (edgei < endEdgei)
|
||||||
<< " edges for face: " << procFacei
|
<< " edges for face: " << meshFacei
|
||||||
<< " ... indicates serious geometry issue" << nl
|
<< " ... indicates serious geometry issue" << nl
|
||||||
<< multihit << nl
|
<< multihit << nl
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
@ -242,7 +320,7 @@ void Foam::faMesh::reorderProcEdges
|
|||||||
if (!multihit.empty())
|
if (!multihit.empty())
|
||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Missed edges for face: " << procFacei
|
<< "Missed edges for face: " << meshFacei
|
||||||
<< " ... indicates serious geometry issue" << nl
|
<< " ... indicates serious geometry issue" << nl
|
||||||
<< multihit << nl
|
<< multihit << nl
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
@ -322,13 +400,9 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createOnePatch
|
|||||||
|
|
||||||
|
|
||||||
Foam::List<Foam::LabelledItem<Foam::edge>>
|
Foam::List<Foam::LabelledItem<Foam::edge>>
|
||||||
Foam::faMesh::getBoundaryEdgePatchPairs
|
Foam::faMesh::getBoundaryEdgePatchPairs() const
|
||||||
(
|
|
||||||
const labelUList& meshEdges
|
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
||||||
const labelListList& edgeFaces = mesh().edgeFaces();
|
|
||||||
|
|
||||||
const label nInternalEdges = patch().nInternalEdges();
|
const label nInternalEdges = patch().nInternalEdges();
|
||||||
const label nBoundaryEdges = patch().nBoundaryEdges();
|
const label nBoundaryEdges = patch().nBoundaryEdges();
|
||||||
@ -336,11 +410,21 @@ Foam::faMesh::getBoundaryEdgePatchPairs
|
|||||||
// Map edges (mesh numbering) back to a boundary index
|
// Map edges (mesh numbering) back to a boundary index
|
||||||
EdgeMap<label> edgeToBoundaryIndex(2*nBoundaryEdges);
|
EdgeMap<label> edgeToBoundaryIndex(2*nBoundaryEdges);
|
||||||
|
|
||||||
|
// Use labelled 'edge' for accounting of patch pairs
|
||||||
// Use 'edge' for accounting
|
|
||||||
patchPairInfoList bndEdgePatchPairs(nBoundaryEdges);
|
patchPairInfoList bndEdgePatchPairs(nBoundaryEdges);
|
||||||
|
|
||||||
// Get pair of polyPatches for each boundary edge
|
|
||||||
|
// Pass 1:
|
||||||
|
// - setup lookup (edge -> bnd index)
|
||||||
|
// - add owner patch for each boundary edge
|
||||||
|
{
|
||||||
|
const SubList<labelList> bndEdgeToPatchFace
|
||||||
|
(
|
||||||
|
patch().edgeFaces(),
|
||||||
|
patch().nBoundaryEdges(),
|
||||||
|
patch().nInternalEdges()
|
||||||
|
);
|
||||||
|
|
||||||
for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei)
|
for (label bndEdgei = 0; bndEdgei < nBoundaryEdges; ++bndEdgei)
|
||||||
{
|
{
|
||||||
edgeToBoundaryIndex.insert
|
edgeToBoundaryIndex.insert
|
||||||
@ -349,142 +433,237 @@ Foam::faMesh::getBoundaryEdgePatchPairs
|
|||||||
edgeToBoundaryIndex.size()
|
edgeToBoundaryIndex.size()
|
||||||
);
|
);
|
||||||
|
|
||||||
const label patchEdgei = (bndEdgei + nInternalEdges);
|
// The attached patch face (there is only one):
|
||||||
const label meshEdgei = meshEdges[patchEdgei];
|
const label patchFacei = bndEdgeToPatchFace[bndEdgei][0];
|
||||||
|
|
||||||
patchPairInfo& patchPair = bndEdgePatchPairs[bndEdgei];
|
const label meshFacei = faceLabels_[patchFacei];
|
||||||
|
|
||||||
for (const label meshFacei : edgeFaces[meshEdgei])
|
|
||||||
{
|
|
||||||
const label patchId = pbm.whichPatch(meshFacei);
|
const label patchId = pbm.whichPatch(meshFacei);
|
||||||
|
|
||||||
// Note: negative labels never insert
|
bndEdgePatchPairs[bndEdgei].insert(patchId);
|
||||||
patchPair.insert(patchId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pass 2:
|
||||||
|
// - Add in first neighbour patch for the boundary edges
|
||||||
|
// - examine all possible connecting neighbours
|
||||||
|
|
||||||
// Synchronize edge information - we want the 'global' patch connectivity
|
findEdgePatchPairing
|
||||||
|
(
|
||||||
|
pbm,
|
||||||
|
edgeToBoundaryIndex,
|
||||||
|
bndEdgePatchPairs,
|
||||||
|
edgeToBoundaryIndex.size() // Number of places to still fill
|
||||||
|
);
|
||||||
|
|
||||||
// Looks like PatchTools::matchEdges
|
|
||||||
|
|
||||||
const indirectPrimitivePatch& cpp = mesh().globalData().coupledPatch();
|
|
||||||
|
|
||||||
labelList patchEdgeLabels(nBoundaryEdges);
|
|
||||||
labelList coupledEdgeLabels(nBoundaryEdges);
|
|
||||||
|
|
||||||
|
// Nothing dangling if running in serial - can return already
|
||||||
|
if (!Pstream::parRun())
|
||||||
{
|
{
|
||||||
label nMatches = 0;
|
return bndEdgePatchPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In parallel 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 outer extent of the finiteArea
|
||||||
|
|
||||||
|
const globalMeshData& globalData = mesh().globalData();
|
||||||
|
const indirectPrimitivePatch& cpp = globalData.coupledPatch();
|
||||||
|
const mapDistribute& map = globalData.globalEdgeSlavesMap();
|
||||||
|
|
||||||
|
// Construct coupled edge usage with all data
|
||||||
|
List<unsigned char> coupledEdgesUsed(map.constructSize(), 0u);
|
||||||
|
|
||||||
forAll(cpp.edges(), coupledEdgei)
|
forAll(cpp.edges(), coupledEdgei)
|
||||||
{
|
{
|
||||||
const edge coupledMeshEdge(cpp.meshEdge(coupledEdgei));
|
const auto iter =
|
||||||
|
edgeToBoundaryIndex.cfind(cpp.meshEdge(coupledEdgei));
|
||||||
|
|
||||||
const auto iter = edgeToBoundaryIndex.cfind(coupledMeshEdge);
|
// Used from this side or other other side
|
||||||
|
coupledEdgesUsed[coupledEdgei] = (iter.found() ? 1 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the original (pre-sync) coupling state
|
||||||
|
const List<unsigned char> coupledEdgesOrig(coupledEdgesUsed);
|
||||||
|
|
||||||
|
globalData.syncData
|
||||||
|
(
|
||||||
|
coupledEdgesUsed,
|
||||||
|
globalData.globalEdgeSlaves(),
|
||||||
|
globalData.globalEdgeTransformedSlaves(), // probably not used
|
||||||
|
map,
|
||||||
|
bitOrEqOp<unsigned char>()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Check for one-sided edge coupling (coupled value == 3)
|
||||||
|
// original == 1:
|
||||||
|
// - coupled to a real finiteArea edge.
|
||||||
|
// - receive a patch-pair value
|
||||||
|
//
|
||||||
|
// original == 2:
|
||||||
|
// - a "dangled" edge. Information required for other procs.
|
||||||
|
// - push a patch-pair value
|
||||||
|
|
||||||
|
// Map edges (mesh numbering) back to a coupled index.
|
||||||
|
// These are the edges to 'push' information for.
|
||||||
|
|
||||||
|
EdgeMap<label> edgeToCoupledIndex;
|
||||||
|
|
||||||
|
label nEdgesPull = 0;
|
||||||
|
|
||||||
|
forAll(coupledEdgesUsed, coupledEdgei)
|
||||||
|
{
|
||||||
|
if (coupledEdgesUsed[coupledEdgei] == 3)
|
||||||
|
{
|
||||||
|
if (coupledEdgesOrig[coupledEdgei] == 1)
|
||||||
|
{
|
||||||
|
// Coupled side with finiteArea
|
||||||
|
++nEdgesPull;
|
||||||
|
}
|
||||||
|
else if (coupledEdgesOrig[coupledEdgei] == 2)
|
||||||
|
{
|
||||||
|
// Coupled side without finiteArea
|
||||||
|
edgeToCoupledIndex.insert
|
||||||
|
(
|
||||||
|
cpp.meshEdge(coupledEdgei),
|
||||||
|
coupledEdgei
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing to do - can return already
|
||||||
|
if (returnReduce(edgeToCoupledIndex.empty(), andOp<bool>()))
|
||||||
|
{
|
||||||
|
return bndEdgePatchPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data locations to pull
|
||||||
|
labelList patchEdgeLabels(nEdgesPull);
|
||||||
|
labelList coupledEdgeLabels(nEdgesPull);
|
||||||
|
|
||||||
|
// Populate the locations
|
||||||
|
{
|
||||||
|
nEdgesPull = 0;
|
||||||
|
|
||||||
|
forAll(cpp.edges(), coupledEdgei)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
coupledEdgesUsed[coupledEdgei] == 3
|
||||||
|
&& coupledEdgesOrig[coupledEdgei] == 1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Pull this edge
|
||||||
|
const auto iter =
|
||||||
|
edgeToBoundaryIndex.cfind(cpp.meshEdge(coupledEdgei));
|
||||||
|
|
||||||
if (iter.found())
|
if (iter.found())
|
||||||
{
|
{
|
||||||
patchEdgeLabels[nMatches] = iter.val();
|
patchEdgeLabels[nEdgesPull] = iter.val();
|
||||||
coupledEdgeLabels[nMatches] = coupledEdgei;
|
coupledEdgeLabels[nEdgesPull] = coupledEdgei;
|
||||||
++nMatches;
|
++nEdgesPull;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Should be impossible to fail here
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Failed on second lookup of "
|
||||||
|
<< cpp.meshEdge(coupledEdgei) << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patchEdgeLabels.resize(nMatches);
|
if (nEdgesPull != coupledEdgeLabels.size())
|
||||||
coupledEdgeLabels.resize(nMatches);
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Failed lookup of some coupled edges" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Construct edge sync with all data
|
||||||
const globalMeshData& globalData = mesh().globalData();
|
|
||||||
const mapDistribute& map = globalData.globalEdgeSlavesMap();
|
|
||||||
|
|
||||||
//- Construct with all data
|
|
||||||
patchPairInfoList cppEdgeData(map.constructSize());
|
patchPairInfoList cppEdgeData(map.constructSize());
|
||||||
|
|
||||||
// Convert patch-edge data into cpp-edge data
|
// Fill in for 'push' locations. Only really interested in the owner
|
||||||
patchPairInfoUIndList(cppEdgeData, coupledEdgeLabels) =
|
// (corresponds to non-proc connection), but grab everything
|
||||||
patchPairInfoUIndList(bndEdgePatchPairs, patchEdgeLabels);
|
findEdgePatchPairing
|
||||||
|
(
|
||||||
|
pbm,
|
||||||
|
edgeToCoupledIndex,
|
||||||
|
cppEdgeData,
|
||||||
|
2*edgeToCoupledIndex.size() // Accept both sides?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Also need to check for dangling edges, which are finiteArea
|
const label nNonProcessor = pbm.nNonProcessor();
|
||||||
// boundary edges that only exist on one side of a proc boundary.
|
|
||||||
// Eg, proc boundary coincides with the end of the finiteArea
|
|
||||||
|
|
||||||
|
// Adjust patch information to reflect dangling patch neighbour
|
||||||
|
// Tag with -(value+2)
|
||||||
|
forAllConstIters(edgeToCoupledIndex, iter)
|
||||||
{
|
{
|
||||||
boolList edgeInUse(map.constructSize(), false);
|
const edge& e = iter.key();
|
||||||
|
const label coupledEdgei = iter.val();
|
||||||
|
|
||||||
for (const label coupledEdgei : coupledEdgeLabels)
|
patchPairInfo& pairing = cppEdgeData[coupledEdgei];
|
||||||
|
const label ownerPatchId = pairing.first();
|
||||||
|
|
||||||
|
// Some sanity checks
|
||||||
|
if (ownerPatchId < 0)
|
||||||
{
|
{
|
||||||
edgeInUse[coupledEdgei] = true;
|
FatalErrorInFunction
|
||||||
|
<< "Error finding dangling edge at "
|
||||||
|
<< cpp.points()[e.first()] << ' '
|
||||||
|
<< cpp.points()[e.second()] << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
else if (ownerPatchId >= nNonProcessor)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Cannot handle edge on processor-processor connection at "
|
||||||
|
<< cpp.points()[e.first()] << ' '
|
||||||
|
<< cpp.points()[e.second()] << nl
|
||||||
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retain pre-synchronized state for later xor
|
combineDanglingEdge::setDangling(pairing, ownerPatchId);
|
||||||
const boolList nonSyncEdgeInUse
|
|
||||||
(
|
|
||||||
SubList<bool>(edgeInUse, cpp.nEdges())
|
|
||||||
);
|
|
||||||
|
|
||||||
globalData.syncData
|
// TBD:
|
||||||
(
|
// may wish to remember the corresponding proc number,
|
||||||
edgeInUse,
|
// if we wish to bridge across 'fan-like' connections.
|
||||||
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
|
// pairing.setIndex(-(Pstream::myProcNo() + 2));
|
||||||
// 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
|
// Synchronize edge information
|
||||||
|
|
||||||
|
const combineDanglingEdge edgeCombineOp(nNonProcessor);
|
||||||
|
|
||||||
|
globalMeshData::syncData
|
||||||
(
|
(
|
||||||
cppEdgeData,
|
cppEdgeData,
|
||||||
globalData.globalEdgeSlaves(),
|
globalData.globalEdgeSlaves(),
|
||||||
globalData.globalEdgeTransformedSlaves(),
|
globalData.globalEdgeTransformedSlaves(), // probably not used
|
||||||
map,
|
map,
|
||||||
syncEdgePatchPairs(pbm.nNonProcessor())
|
edgeCombineOp
|
||||||
);
|
);
|
||||||
|
|
||||||
// Back from cpp-edge to patch-edge data
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
patchPairInfoUIndList(bndEdgePatchPairs, patchEdgeLabels) =
|
// Combine back from pushed cpp-edge data
|
||||||
patchPairInfoUIndList(cppEdgeData, coupledEdgeLabels);
|
|
||||||
|
forAll(patchEdgeLabels, i)
|
||||||
|
{
|
||||||
|
patchPairInfo& pairing = bndEdgePatchPairs[patchEdgeLabels[i]];
|
||||||
|
const patchPairInfo& other = cppEdgeData[coupledEdgeLabels[i]];
|
||||||
|
|
||||||
|
edgeCombineOp(pairing, other);
|
||||||
|
|
||||||
|
// Resolve special tagging
|
||||||
|
combineDanglingEdge::correct(pairing);
|
||||||
|
}
|
||||||
|
|
||||||
return bndEdgePatchPairs;
|
return bndEdgePatchPairs;
|
||||||
}
|
}
|
||||||
@ -499,13 +678,6 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
|
|||||||
{
|
{
|
||||||
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
||||||
|
|
||||||
const labelListList& edgeFaces = mesh().edgeFaces();
|
|
||||||
const labelList meshEdges
|
|
||||||
(
|
|
||||||
patch().meshEdges(mesh().edges(), mesh().pointEdges())
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Transcribe into patch definitions
|
// Transcribe into patch definitions
|
||||||
DynamicList<faPatchData> faPatchDefs(bndDict.size() + 4);
|
DynamicList<faPatchData> faPatchDefs(bndDict.size() + 4);
|
||||||
for (const entry& dEntry : bndDict)
|
for (const entry& dEntry : bndDict)
|
||||||
@ -576,10 +748,7 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
|
|||||||
const label nInternalEdges = patch().nInternalEdges();
|
const label nInternalEdges = patch().nInternalEdges();
|
||||||
const label nBoundaryEdges = patch().nBoundaryEdges();
|
const label nBoundaryEdges = patch().nBoundaryEdges();
|
||||||
|
|
||||||
patchPairInfoList bndEdgePatchPairs
|
patchPairInfoList bndEdgePatchPairs(this->getBoundaryEdgePatchPairs());
|
||||||
(
|
|
||||||
getBoundaryEdgePatchPairs(meshEdges)
|
|
||||||
);
|
|
||||||
|
|
||||||
labelList bndEdgeFaPatchIDs(nBoundaryEdges, -1);
|
labelList bndEdgeFaPatchIDs(nBoundaryEdges, -1);
|
||||||
|
|
||||||
@ -653,23 +822,10 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
|
|||||||
labelList edgeNbrPolyPatch(undefinedEdges.size(), -1);
|
labelList edgeNbrPolyPatch(undefinedEdges.size(), -1);
|
||||||
forAll(edgeNbrPolyPatch, edgei)
|
forAll(edgeNbrPolyPatch, edgei)
|
||||||
{
|
{
|
||||||
const label localEdgei = undefinedEdges[edgei];
|
const label patchEdgei = undefinedEdges[edgei];
|
||||||
const label meshEdgei = meshEdges[localEdgei];
|
const label bndEdgei = (patchEdgei - nInternalEdges);
|
||||||
label polyPatchID;
|
|
||||||
|
|
||||||
for (const label meshFacei : edgeFaces[meshEdgei])
|
edgeNbrPolyPatch[edgei] = bndEdgePatchPairs[bndEdgei].second();
|
||||||
{
|
|
||||||
if
|
|
||||||
(
|
|
||||||
!faceLabels_.found(meshFacei)
|
|
||||||
&& (polyPatchID = pbm.whichPatch(meshFacei)) != -1
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Found the edge's off-patch neighbour face
|
|
||||||
edgeNbrPolyPatch[edgei] = polyPatchID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Categorize as processor/non-processor associations
|
// Categorize as processor/non-processor associations
|
||||||
@ -762,7 +918,7 @@ Foam::PtrList<Foam::faPatch> Foam::faMesh::createPatchList
|
|||||||
{
|
{
|
||||||
if (patchDef.coupled())
|
if (patchDef.coupled())
|
||||||
{
|
{
|
||||||
reorderProcEdges(patchDef, meshEdges, bndEdgePatchPairs);
|
reorderProcEdges(patchDef, bndEdgePatchPairs);
|
||||||
patchDef.neighPolyPatchId_ = -1; // No lookup of neighbour faces
|
patchDef.neighPolyPatchId_ = -1; // No lookup of neighbour faces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user