Commit 146a1d1b authored by mattijs's avatar mattijs
Browse files

ENH: snappyHexMesh: par extrusion. Fixes #1923

parent 79a4dc51
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2017 OpenCFD Ltd.
Copyright (C) 2015-2017,2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -643,7 +643,6 @@ Foam::labelListList Foam::addPatchCellLayer::addedCells() const
}
// Calculate global faces per pp edge.
Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
(
const polyMesh& mesh,
......@@ -689,6 +688,404 @@ Foam::labelListList Foam::addPatchCellLayer::globalEdgeFaces
}
void Foam::addPatchCellLayer::markPatchEdges
(
const polyMesh& mesh,
const indirectPrimitivePatch& pp,
const labelListList& edgeGlobalFaces,
const labelList& meshEdges,
bitSet& isPatchEdge,
bitSet& isPatchBoundaryEdge
)
{
// Mark (mesh) edges:
// - anywhere on extrusion
// - where the extrusion ends
isPatchEdge.setSize(mesh.nEdges());
isPatchEdge = false;
isPatchEdge.set(meshEdges);
// Synchronise across coupled edges
syncTools::syncEdgeList
(
mesh,
isPatchEdge,
orEqOp<unsigned int>(),
false // initial value
);
isPatchBoundaryEdge.setSize(mesh.nEdges());
isPatchBoundaryEdge = false;
forAll(edgeGlobalFaces, edgei)
{
// Test that edge has single global extruded face.
// Mark on processor that holds the face (since edgeGlobalFaces
// only gets filled from pp faces so if there is only one this
// is it)
if (edgeGlobalFaces[edgei].size() == 1)
{
isPatchBoundaryEdge.set(meshEdges[edgei]);
}
}
// Synchronise across coupled edges
syncTools::syncEdgeList
(
mesh,
isPatchBoundaryEdge,
orEqOp<unsigned int>(),
false // initial value
);
}
void Foam::addPatchCellLayer::globalEdgeInfo
(
const bool zoneFromAnyFace,
const polyMesh& mesh,
const globalIndex& globalFaces,
const labelListList& edgeGlobalFaces,
const indirectPrimitivePatch& pp,
const labelList& meshEdges,
labelList& patchEdgeToFace, // face (in globalFaces index)
labelList& patchEdgeToPatch, // patch on face (or -1 for internal faces)
labelList& patchEdgeToZone, // zone on face
bitSet& patchEdgeToFlip // flip orientation on face
)
{
// For every edge on the outside of the patch return a potential patch/
// faceZone to extrude into.
// Mark (mesh) edges on pp.
bitSet isExtrudeEdge;
bitSet isBoundaryEdge;
markPatchEdges
(
mesh,
pp,
edgeGlobalFaces,
meshEdges,
isExtrudeEdge,
isBoundaryEdge
);
// Build map of pp edges (in mesh point indexing). Note that this
// is now also on processors that do not have pp (but do have the edge)
EdgeMap<label> isBoundaryEdgeSet(pp.nEdges());
for (const label edgei : isBoundaryEdge)
{
isBoundaryEdgeSet.insert(mesh.edges()[edgei], edgei);
}
EdgeMap<label> isExtrudeEdgeSet(pp.nEdges());
for (const label edgei : isExtrudeEdge)
{
isExtrudeEdgeSet.insert(mesh.edges()[edgei], edgei);
}
const faceZoneMesh& fzs = mesh.faceZones();
// Extract zone info into mesh face indexing for ease of addressing
labelList faceToZone(mesh.nFaces(), -1);
bitSet faceToFlip(mesh.nFaces());
for (const faceZone& fz: fzs)
{
const labelList& addressing = fz;
UIndirectList<label>(faceToZone, addressing) = fz.index();
const boolList& fm = fz.flipMap();
forAll(addressing, i)
{
faceToFlip[addressing[i]] = fm[i];
}
}
// Storage (over all mesh edges)
// - face that data originates from (in globalFaces indexing)
labelList meshEdgeToFace(mesh.nEdges(), -1);
// - patch (for boundary faces)
labelList meshEdgeToPatch(mesh.nEdges(), -1);
// - faceZone
labelList meshEdgeToZone(mesh.nEdges(), -1);
// - faceZone orientation
bitSet meshEdgeToFlip(mesh.nEdges());
//if (useInternalFaces)
{
const bitSet isInternalOrCoupled
(
syncTools::getInternalOrCoupledFaces(mesh)
);
// Loop over edges of the face to find any faceZone.
// Edges kept as point pair so we don't construct mesh.faceEdges etc.
for (const label facei : isInternalOrCoupled)
{
const face& f = mesh.faces()[facei];
label prevPointi = f.last();
for (const label pointi : f)
{
const edge e(prevPointi, pointi);
// Check if edge is internal to extrusion. Take over faceZone
// etc from internal face.
const auto eFnd = isExtrudeEdgeSet.cfind(e);
if (eFnd)
{
const label edgei = eFnd();
if (faceToZone[facei] != -1)
{
// Found a zoned internal face. Use.
meshEdgeToFace[edgei] = globalFaces.toGlobal(facei);
meshEdgeToZone[edgei] = faceToZone[facei];
const edge& meshE = mesh.edges()[edgei];
const int d = edge::compare(e, meshE);
if (d == 1)
{
meshEdgeToFlip[edgei] = faceToFlip[facei];
}
else if (d == -1)
{
meshEdgeToFlip[edgei] = !faceToFlip[facei];
}
else
{
FatalErrorInFunction << "big problem"
<< exit(FatalError);
}
}
}
prevPointi = pointi;
}
}
}
//if (useBoundaryFaces)
{
// Loop over all patches and find 'best' one (non-coupled,
// non-extrusion, non-constraint(?)). Note that logic is slightly
// different from internal faces loop above - first patch face
// is being used instead of first zoned face for internal faces
const polyBoundaryMesh& patches = mesh.boundaryMesh();
bitSet isPpFace(mesh.nFaces());
isPpFace.set(pp.addressing());
// Note: no need to sync ppFace since does not include processor patches
for (const polyPatch& pp : patches)
{
if (!pp.coupled())
{
// TBD. Check for constraint? This is usually a geometric
// constraint and not a topological one so should
// be handled in the extrusion vector calculation instead?
forAll(pp, i)
{
const label facei = pp.start()+i;
if (!isPpFace[facei])
{
const face& f = pp[i];
label prevPointi = f.last();
for (const label pointi : f)
{
const edge e(prevPointi, pointi);
const auto eFnd =
(
zoneFromAnyFace
? isExtrudeEdgeSet.cfind(e)
: isBoundaryEdgeSet.cfind(e)
);
if (eFnd)
{
const label edgei = eFnd();
if (meshEdgeToFace[edgei] == -1)
{
// Found unassigned face. Use its
// information.
// Note that we use the lowest numbered
// patch face.
meshEdgeToFace[edgei] =
globalFaces.toGlobal(facei);
// Override any patch info
if (meshEdgeToPatch[edgei] == -1)
{
meshEdgeToPatch[edgei] = pp.index();
}
// Override any zone info
if (meshEdgeToZone[edgei] == -1)
{
meshEdgeToZone[edgei] =
faceToZone[facei];
const edge& meshE = mesh.edges()[edgei];
const int d = edge::compare(e, meshE);
if (d == 1)
{
meshEdgeToFlip[edgei] =
faceToFlip[facei];
}
else if (d == -1)
{
meshEdgeToFlip[edgei] =
!faceToFlip[facei];
}
else
{
FatalErrorInFunction
<< "big problem"
<< exit(FatalError);
}
}
}
}
prevPointi = pointi;
}
}
}
}
}
}
// Synchronise across coupled edges. Max patch/face/faceZone wins
syncTools::syncEdgeList
(
mesh,
meshEdgeToFace,
maxEqOp<label>(),
-1
);
syncTools::syncEdgeList
(
mesh,
meshEdgeToPatch,
maxEqOp<label>(),
-1
);
syncTools::syncEdgeList
(
mesh,
meshEdgeToZone,
maxEqOp<label>(),
-1
);
// // Note: flipMap not yet done. Needs edge orientation. This is handled
// // later on.
// if (Pstream::parRun())
// {
// const globalMeshData& gd = mesh.globalData();
// const indirectPrimitivePatch& cpp = gd.coupledPatch();
//
// labelList patchEdges;
// labelList coupledEdges;
// bitSet sameEdgeOrientation;
// PatchTools::matchEdges
// (
// pp,
// cpp,
// patchEdges,
// coupledEdges,
// sameEdgeOrientation
// );
//
// // Convert data on pp edges to data on coupled patch
// labelList cppEdgeZoneID(cpp.nEdges(), -1);
// boolList cppEdgeFlip(cpp.nEdges(), false);
// forAll(coupledEdges, i)
// {
// label cppEdgei = coupledEdges[i];
// label ppEdgei = patchEdges[i];
//
// cppEdgeZoneID[cppEdgei] = edgeZoneID[ppEdgei];
// if (sameEdgeOrientation[i])
// {
// cppEdgeFlip[cppEdgei] = edgeFlip[ppEdgei];
// }
// else
// {
// cppEdgeFlip[cppEdgei] = !edgeFlip[ppEdgei];
// }
// }
//
// // Sync
// const globalIndexAndTransform& git = gd.globalTransforms();
// const mapDistribute& edgeMap = gd.globalEdgeSlavesMap();
//
// globalMeshData::syncData
// (
// cppEdgeZoneID,
// gd.globalEdgeSlaves(),
// gd.globalEdgeTransformedSlaves(),
// edgeMap,
// git,
// maxEqOp<label>(),
// dummyTransform()
// );
// globalMeshData::syncData
// (
// cppEdgeFlip,
// gd.globalEdgeSlaves(),
// gd.globalEdgeTransformedSlaves(),
// edgeMap,
// git,
// andEqOp<bool>(),
// dummyTransform()
// );
//
// // Convert data on coupled edges to pp edges
// forAll(coupledEdges, i)
// {
// label cppEdgei = coupledEdges[i];
// label ppEdgei = patchEdges[i];
//
// edgeZoneID[ppEdgei] = cppEdgeZoneID[cppEdgei];
// if (sameEdgeOrientation[i])
// {
// edgeFlip[ppEdgei] = cppEdgeFlip[cppEdgei];
// }
// else
// {
// edgeFlip[ppEdgei] = !cppEdgeFlip[cppEdgei];
// }
// }
// }
syncTools::syncEdgeList
(
mesh,
meshEdgeToFlip,
orEqOp<unsigned int>(),
0
);
// Extract pp info
patchEdgeToFace = UIndirectList<label>(meshEdgeToFace, meshEdges);
patchEdgeToPatch = UIndirectList<label>(meshEdgeToPatch, meshEdges);
patchEdgeToZone = UIndirectList<label>(meshEdgeToZone, meshEdges);
patchEdgeToFlip.setSize(meshEdges.size());
patchEdgeToFlip = false;
forAll(meshEdges, i)
{
patchEdgeToFlip[i] = meshEdgeToFlip[meshEdges[i]];
}
}
void Foam::addPatchCellLayer::calcExtrudeInfo
(
const bool zoneFromAnyFace,
......@@ -715,10 +1112,12 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
edgePatchID.setSize(pp.nEdges());
edgePatchID = -1;
nPatches = patches.size();
edgeZoneID.setSize(pp.nEdges());
edgeZoneID = -1;
edgeFlip.setSize(pp.nEdges());
edgeFlip = false;
inflateFaceID.setSize(pp.nEdges(), -1);
// Determine properties for faces extruded from edges
......@@ -729,16 +1128,6 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
// - edge internal to patch (so edgeFaces.size() == 2):
// These also get determined but not (yet) exported:
// - whether face is created from other face or edge
inflateFaceID.setSize(pp.nEdges(), -1);
nPatches = patches.size();
// Pass1:
// For all edges inbetween two processors: see if matches to existing
// processor patch or create interprocessor-patch if necessary.
......@@ -804,6 +1193,27 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
// Pass2: determine face properties for all other edges
// ----------------------------------------------------
// Info for edges of pp
labelList edgeToFace;
labelList edgeToPatch;
labelList edgeToZone;
bitSet edgeToFlip;
globalEdgeInfo
(
zoneFromAnyFace, // internal edge info also from boundary faces
mesh,
globalFaces,
globalEdgeFaces,
pp,
meshEdges,
edgeToFace, // face (in globalFaces index)
edgeToPatch, // patch on face (or -1 for internal faces)
edgeToZone, // zone on face
edgeToFlip // flip orientation on face
);
const labelListList& edgeFaces = pp.edgeFaces();
DynamicList<label> dynMeshEdgeFaces;
......@@ -812,63 +1222,32 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
{
if (edgePatchID[edgei] == -1)
{
labelUIndList ppFaces(pp.addressing(), edgeFaces[edgei]);
label meshEdgei = meshEdges[edgei];
const labelList& meshFaces = mesh.edgeFaces
(
meshEdgei,
dynMeshEdgeFaces
);
if (edgeFaces[edgei].size() == 2)
{
// Internal edge. Look at any face (internal or boundary) to
// determine extrusion properties. First one that has zone
// info wins
label dummyPatchi = -1;
findZoneFace
(
true, // useInternalFaces,
zoneFromAnyFace, // useBoundaryFaces,
mesh,
pp,
edgei,
ppFaces, // excludeFaces,
meshFaces, // meshFaces,
inflateFaceID[edgei],
dummyPatchi, // do not use patch info
edgeZoneID[edgei],
edgeFlip[edgei]
);
if (globalFaces.isLocal(edgeToFace[edgei]))
{
inflateFaceID[edgei] =
globalFaces.toLocal(edgeToFace[edgei]);
}
edgeZoneID[edgei] = edgeToZone[edgei];
edgeFlip[edgei] = edgeToFlip[edgei];
}
else
{
// Proper, uncoupled patch edge
findZoneFace
(
false, // useInternalFaces,
true, // useBoundaryFaces,
mesh,
pp,
edgei,
// Proper, uncoupled patch edge. Boundary to get info from
// might be on a different processor!
ppFaces, // excludeFaces,
meshFaces, // meshFaces,
inflateFaceID[edgei],
edgePatchID[edgei],
edgeZoneID[edgei],
edgeFlip[edgei]
);
if (globalFaces.isLocal(edgeToFace[edgei]))
{
inflateFaceID[edgei] =
globalFaces.toLocal(edgeToFace[edgei]);
}
edgePatchID[edgei] = edgeToPatch[edgei];
edgeZoneID[edgei] = edgeToZone[edgei];
edgeFlip[edgei] = edgeToFlip[edgei];
}
}
}
......@@ -901,11 +1280,12 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
if
(
edgeFaces[edgei].size() == 1
&& globalEdgeFaces[edgei].size() == 2
&& edgePatchID[edgei] != -1
&& inflateFaceID[edgei] == -1
)
{
// 1. Do we have a boundary face to inflate from
// 1. Do we have a local boundary face to inflate from
label myFaceI = pp.addressing()[edgeFaces[edgei][0]];
......
......@@ -248,6 +248,39 @@ class addPatchCellLayer
bool& zoneFlip
);
//- Mark internal and boundary edges of patch. In mesh edges
//- since processor might not have pp but does have edge.
static void markPatchEdges
(
const polyMesh& mesh,
const indirectPrimitivePatch& pp,
const labelListList& edgeGlobalFaces,
const labelList& meshEdges,
bitSet& isPatchEdge,
bitSet& isPatchBoundaryEdge
);
//- For every edge on pp return
// - patchEdgeToFace : face (in global indexing) to inflate from
// - patchEdgeToPatch : patch (only for boundary edges of pp)
// - patchEdgeToZone,flip : zone info
static void globalEdgeInfo
(
const bool zoneFromAnyFace,
const polyMesh& mesh,
const globalIndex& globalFaces,
const labelListList& edgeGlobalFaces,
const indirectPrimitivePatch& pp,
const labelList& meshEdges,