ENH: collapseEdges: WIP to extend to work in parallel

This commit is contained in:
laurence 2012-04-17 16:48:44 +01:00
parent 6dd2afe2e2
commit df636c4082
4 changed files with 587 additions and 238 deletions

View File

@ -1,5 +1,6 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude -I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-ldynamicMesh \ -ldynamicMesh \

View File

@ -50,6 +50,11 @@ Description
#include "PackedBoolList.H" #include "PackedBoolList.H"
#include "SortableList.H" #include "SortableList.H"
#include "unitConversion.H" #include "unitConversion.H"
#include "globalMeshData.H"
#include "globalIndex.H"
#include "OFstream.H"
#include "meshTools.H"
using namespace Foam; using namespace Foam;
@ -174,37 +179,74 @@ label mergeEdges
// Return master point edge needs to be collapsed to (or -1) // Return master point edge needs to be collapsed to (or -1)
label edgeMaster(const PackedBoolList& boundaryPoint, const edge& e) label edgeMaster
(
const labelList& boundaryPoint,
const bool flipEdge,
const edge& e
)
{ {
label masterPoint = -1; label masterPoint = -1;
// Collapse edge to boundary point. label e0 = e[0];
if (boundaryPoint.get(e[0])) label e1 = e[1];
if (flipEdge)
{ {
if (boundaryPoint.get(e[1])) e0 = e[1];
e1 = e[0];
}
// Check if one of the points is on a processor
if
(
boundaryPoint[e0] > 0
&& boundaryPoint[e1] > 0
)
{
if (boundaryPoint[e0] != boundaryPoint[e1])
{
return -1;
}
}
if (boundaryPoint[e0] > 0)
{
return e0;
}
else if (boundaryPoint[e1] > 0)
{
return e1;
}
// Collapse edge to boundary point.
if (boundaryPoint[e0] == 0)
{
if (boundaryPoint[e1] == 0)
{ {
// Both points on boundary. Choose one to collapse to. // Both points on boundary. Choose one to collapse to.
// Note: should look at feature edges/points! // Note: should look at feature edges/points!
masterPoint = e[0]; masterPoint = e0;
} }
else else
{ {
masterPoint = e[0]; masterPoint = e0;
} }
} }
else else
{ {
if (boundaryPoint.get(e[1])) if (boundaryPoint[e1] == 0)
{ {
masterPoint = e[1]; masterPoint = e1;
} }
else else
{ {
// None on boundary. Choose arbitrary. // None on boundary. Choose arbitrary.
// Note: should look at geometry? // Note: should look at geometry?
masterPoint = e[0]; masterPoint = e0;
} }
} }
return masterPoint; return masterPoint;
} }
@ -212,7 +254,7 @@ label edgeMaster(const PackedBoolList& boundaryPoint, const edge& e)
label collapseSmallEdges label collapseSmallEdges
( (
const polyMesh& mesh, const polyMesh& mesh,
const PackedBoolList& boundaryPoint, const labelList& boundaryPoint,
const scalar minLen, const scalar minLen,
edgeCollapser& collapser edgeCollapser& collapser
) )
@ -223,7 +265,17 @@ label collapseSmallEdges
// Collapse all edges that are too small. Choose intelligently which // Collapse all edges that are too small. Choose intelligently which
// point to collapse edge to. // point to collapse edge to.
label nCollapsed = 0; const globalMeshData& globalData = mesh.globalData();
const mapDistribute& map = globalData.globalEdgeSlavesMap();
const labelList& coupledMeshEdges = globalData.coupledPatchMeshEdges();
const indirectPrimitivePatch& coupledPatch = globalData.coupledPatch();
const PackedBoolList& cppOrientation = globalData.globalEdgeOrientation();
// Store collapse direction in collapseEdge
// -1 -> Do not collapse
// 0 -> Collapse to start point
// 1 -> Collapse to end point
labelList collapseEdge(edges.size(), -1);
forAll(edges, edgeI) forAll(edges, edgeI)
{ {
@ -231,15 +283,121 @@ label collapseSmallEdges
if (e.mag(points) < minLen) if (e.mag(points) < minLen)
{ {
label master = edgeMaster(boundaryPoint, e); collapseEdge[edgeI] = 0;
}
}
if (master != -1) // && collapser.unaffectedEdge(edgeI)) // Check whether edge point order is reversed from mesh to coupledPatch
PackedBoolList meshToPatchSameOrientation(coupledMeshEdges.size(), true);
forAll(coupledMeshEdges, eI)
{
const label meshEdgeIndex = coupledMeshEdges[eI];
if (collapseEdge[meshEdgeIndex] != -1)
{
const edge& meshEdge = edges[meshEdgeIndex];
const edge& coupledPatchEdge = coupledPatch.edges()[eI];
if
(
meshEdge[0] == coupledPatch.meshPoints()[coupledPatchEdge[1]]
&& meshEdge[1] == coupledPatch.meshPoints()[coupledPatchEdge[0]]
)
{
meshToPatchSameOrientation[eI] = false;
}
}
}
labelList cppEdgeData(coupledMeshEdges.size(), -1);
forAll(coupledMeshEdges, eI)
{
const label meshEdgeIndex = coupledMeshEdges[eI];
if (collapseEdge[meshEdgeIndex] != -1)
{
if (meshToPatchSameOrientation[eI] == cppOrientation[eI])
{
cppEdgeData[eI] = 0;
}
else
{
cppEdgeData[eI] = 1;
}
}
}
// Synchronise cppEdgeData
// Use minEqOp reduction, so that edge will only be collapsed on processor
// boundary if both processors agree to collapse it
globalData.syncData
(
cppEdgeData,
globalData.globalEdgeSlaves(),
globalData.globalEdgeTransformedSlaves(),
map,
minEqOp<label>()
);
forAll(coupledMeshEdges, eI)
{
const label meshEdgeIndex = coupledMeshEdges[eI];
if (collapseEdge[meshEdgeIndex] != -1)
{
if (meshToPatchSameOrientation[eI] == cppOrientation[eI])
{
collapseEdge[meshEdgeIndex] = 0;
}
else
{
collapseEdge[meshEdgeIndex] = 1;
}
}
}
OFstream str1("collapsedPoints_" + name(Pstream::myProcNo()) + ".obj");
label nCollapsed = 0;
forAll(edges, edgeI)
{
if (collapseEdge[edgeI] != -1)
{
const edge& e = edges[edgeI];
const label master =
edgeMaster
(
boundaryPoint,
collapseEdge[edgeI],
e
);
if (e[0] == master)
{
meshTools::writeOBJ(str1, points[e[1]], points[e[0]]);
}
else if (e[1] == master)
{
meshTools::writeOBJ(str1, points[e[0]], points[e[1]]);
}
if (master != -1)
{ {
collapser.collapseEdge(edgeI, master); collapser.collapseEdge(edgeI, master);
nCollapsed++; nCollapsed++;
} }
} }
} }
return nCollapsed; return nCollapsed;
} }
@ -248,86 +406,88 @@ label collapseSmallEdges
// are very small. This one tries to collapse them if it can be done with // are very small. This one tries to collapse them if it can be done with
// edge collapse. For faces where a face gets replace by two edges use // edge collapse. For faces where a face gets replace by two edges use
// collapseFaces // collapseFaces
label collapseHighAspectFaces //label collapseHighAspectFaces
( //(
const polyMesh& mesh, // const polyMesh& mesh,
const PackedBoolList& boundaryPoint, // const PackedBoolList& boundaryPoint,
const scalar areaFac, // const Map<label>& processorPoints,
const scalar edgeRatio, // const scalar areaFac,
edgeCollapser& collapser // const scalar edgeRatio,
) // edgeCollapser& collapser
{ //)
const pointField& points = mesh.points(); //{
const edgeList& edges = mesh.edges(); // const pointField& points = mesh.points();
const faceList& faces = mesh.faces(); // const edgeList& edges = mesh.edges();
const labelListList& faceEdges = mesh.faceEdges(); // const faceList& faces = mesh.faces();
// const labelListList& faceEdges = mesh.faceEdges();
scalarField magArea(mag(mesh.faceAreas())); //
// scalarField magArea(mag(mesh.faceAreas()));
label maxIndex = findMax(magArea); //
// label maxIndex = findMax(magArea);
scalar minArea = areaFac * magArea[maxIndex]; //
// scalar minArea = areaFac * magArea[maxIndex];
Info<< "Max face area:" << magArea[maxIndex] << endl //
<< "Collapse area factor:" << areaFac << endl // Info<< "Max face area:" << magArea[maxIndex] << endl
<< "Collapse area:" << minArea << endl; // << "Collapse area factor:" << areaFac << endl
// << "Collapse area:" << minArea << endl;
label nCollapsed = 0; //
// label nCollapsed = 0;
forAll(faces, faceI) //
{ // forAll(faces, faceI)
if (magArea[faceI] < minArea) // {
{ // if (magArea[faceI] < minArea)
const face& f = faces[faceI]; // {
// const face& f = faces[faceI];
// Get the edges in face point order //
labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI])); // // Get the edges in face point order
// labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI]));
SortableList<scalar> lengths(fEdges.size()); //
forAll(fEdges, i) // SortableList<scalar> lengths(fEdges.size());
{ // forAll(fEdges, i)
lengths[i] = edges[fEdges[i]].mag(points); // {
} // lengths[i] = edges[fEdges[i]].mag(points);
lengths.sort(); // }
// lengths.sort();
//
label edgeI = -1; //
// label edgeI = -1;
if (f.size() == 4) //
{ // if (f.size() == 4)
// Compare second largest to smallest // {
if (lengths[2] > edgeRatio*lengths[0]) // // Compare second largest to smallest
{ // if (lengths[2] > edgeRatio*lengths[0])
// Collapse smallest only. Triangle should be cleared // {
// next time around. // // Collapse smallest only. Triangle should be cleared
edgeI = fEdges[lengths.indices()[0]]; // // next time around.
} // edgeI = fEdges[lengths.indices()[0]];
} // }
else if (f.size() == 3) // }
{ // else if (f.size() == 3)
// Compare second largest to smallest // {
if (lengths[1] > edgeRatio*lengths[0]) // // Compare second largest to smallest
{ // if (lengths[1] > edgeRatio*lengths[0])
edgeI = fEdges[lengths.indices()[0]]; // {
} // edgeI = fEdges[lengths.indices()[0]];
} // }
// }
//
if (edgeI != -1) //
{ // if (edgeI != -1)
label master = edgeMaster(boundaryPoint, edges[edgeI]); // {
// label master =
if (master != -1)// && collapser.unaffectedEdge(edgeI)) // edgeMaster(boundaryPoint, processorPoints, false, edges[edgeI]);
{ //
collapser.collapseEdge(edgeI, master); // if (master != -1)// && collapser.unaffectedEdge(edgeI))
nCollapsed++; // {
} // collapser.collapseEdge(edgeI, master);
} // nCollapsed++;
} // }
} // }
// }
return nCollapsed; // }
} //
// return nCollapsed;
//}
void set(const labelList& elems, const bool val, boolList& status) void set(const labelList& elems, const bool val, boolList& status)
@ -340,112 +500,113 @@ void set(const labelList& elems, const bool val, boolList& status)
// Tries to simplify polygons to face of minSize (4=quad, 3=triangle) // Tries to simplify polygons to face of minSize (4=quad, 3=triangle)
label simplifyFaces //label simplifyFaces
( //(
const polyMesh& mesh, // const polyMesh& mesh,
const PackedBoolList& boundaryPoint, // const PackedBoolList& boundaryPoint,
const label minSize, // const Map<label>& processorPoints,
const scalar lenGap, // const label minSize,
edgeCollapser& collapser // const scalar lenGap,
) // edgeCollapser& collapser
{ //)
const pointField& points = mesh.points(); //{
const edgeList& edges = mesh.edges(); // const pointField& points = mesh.points();
const faceList& faces = mesh.faces(); // const edgeList& edges = mesh.edges();
const cellList& cells = mesh.cells(); // const faceList& faces = mesh.faces();
const labelListList& faceEdges = mesh.faceEdges(); // const cellList& cells = mesh.cells();
const labelList& faceOwner = mesh.faceOwner(); // const labelListList& faceEdges = mesh.faceEdges();
const labelList& faceNeighbour = mesh.faceNeighbour(); // const labelList& faceOwner = mesh.faceOwner();
const labelListList& pointCells = mesh.pointCells(); // const labelList& faceNeighbour = mesh.faceNeighbour();
const labelListList& cellEdges = mesh.cellEdges(); // const labelListList& pointCells = mesh.pointCells();
// const labelListList& cellEdges = mesh.cellEdges();
label nCollapsed = 0; //
// label nCollapsed = 0;
boolList protectedEdge(mesh.nEdges(), false); //
// boolList protectedEdge(mesh.nEdges(), false);
forAll(faces, faceI) //
{ // forAll(faces, faceI)
const face& f = faces[faceI]; // {
// const face& f = faces[faceI];
if //
( // if
f.size() > minSize // (
&& cells[faceOwner[faceI]].size() >= 6 // f.size() > minSize
&& ( // && cells[faceOwner[faceI]].size() >= 6
mesh.isInternalFace(faceI) // && (
&& cells[faceNeighbour[faceI]].size() >= 6 // mesh.isInternalFace(faceI)
) // && cells[faceNeighbour[faceI]].size() >= 6
) // )
{ // )
// Get the edges in face point order // {
labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI])); // // Get the edges in face point order
// labelList fEdges(getSortedEdges(edges, f, faceEdges[faceI]));
SortableList<scalar> lengths(fEdges.size()); //
forAll(fEdges, i) // SortableList<scalar> lengths(fEdges.size());
{ // forAll(fEdges, i)
lengths[i] = edges[fEdges[i]].mag(points); // {
} // lengths[i] = edges[fEdges[i]].mag(points);
lengths.sort(); // }
// lengths.sort();
//
// Now find a gap in length between consecutive elements greater //
// than lenGap. // // Now find a gap in length between consecutive elements greater
// // than lenGap.
label gapPos = -1; //
// label gapPos = -1;
for (label i = f.size()-1-minSize; i >= 0; --i) //
{ // for (label i = f.size()-1-minSize; i >= 0; --i)
if (lengths[i+1] > lenGap*lengths[i]) // {
{ // if (lengths[i+1] > lenGap*lengths[i])
gapPos = i; // {
// gapPos = i;
break; //
} // break;
} // }
// }
if (gapPos != -1) //
{ // if (gapPos != -1)
//for (label i = gapPos; i >= 0; --i) // {
label i = 0; // Hack: collapse smallest edge only. // //for (label i = gapPos; i >= 0; --i)
{ // label i = 0; // Hack: collapse smallest edge only.
label edgeI = fEdges[lengths.indices()[i]]; // {
// label edgeI = fEdges[lengths.indices()[i]];
if (!protectedEdge[edgeI]) //
{ // if (!protectedEdge[edgeI])
const edge& e = edges[edgeI]; // {
// const edge& e = edges[edgeI];
label master = edgeMaster(boundaryPoint, e); //
// label master = edgeMaster(boundaryPoint, processorPoints, false, e);
if (master != -1) //
{ // if (master != -1)
collapser.collapseEdge(edgeI, master); // {
// collapser.collapseEdge(edgeI, master);
// Protect all other edges on all cells using edge //
// points. // // Protect all other edges on all cells using edge
// // points.
const labelList& pCells0 = pointCells[e[0]]; //
// const labelList& pCells0 = pointCells[e[0]];
forAll(pCells0, i) //
{ // forAll(pCells0, i)
set(cellEdges[pCells0[i]], true, protectedEdge); // {
} // set(cellEdges[pCells0[i]], true, protectedEdge);
const labelList& pCells1 = pointCells[e[1]]; // }
// const labelList& pCells1 = pointCells[e[1]];
forAll(pCells1, i) //
{ // forAll(pCells1, i)
set(cellEdges[pCells1[i]], true, protectedEdge); // {
} // set(cellEdges[pCells1[i]], true, protectedEdge);
// }
nCollapsed++; //
} // nCollapsed++;
} // }
} // }
} // }
} // }
} // }
// }
return nCollapsed; //
} // return nCollapsed;
//}
// Main program: // Main program:
@ -453,7 +614,7 @@ label simplifyFaces
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "addOverwriteOption.H" # include "addOverwriteOption.H"
argList::noParallel();
argList::validArgs.append("edge length [m]"); argList::validArgs.append("edge length [m]");
argList::validArgs.append("merge angle (degrees)"); argList::validArgs.append("merge angle (degrees)");
@ -475,16 +636,26 @@ int main(int argc, char *argv[])
<< " degrees" << nl << " degrees" << nl
<< endl; << endl;
bool meshChanged = false; bool meshChanged = false;
// Edge collapsing engine
edgeCollapser collapser(mesh);
label nIterations = 0;
while (true) while (true)
{ {
Info<< "Iteration " << nIterations << incrIndent << endl;
const faceList& faces = mesh.faces(); const faceList& faces = mesh.faces();
// Get all points on the boundary // boundaryPoint:
PackedBoolList boundaryPoint(mesh.nPoints()); // + -1 : point not on boundary
// + 0 : point on a real boundary
// + >0 : point on a processor patch with that ID
labelList boundaryPoint(mesh.nPoints(), -1);
// Get all points on a boundary
label nIntFaces = mesh.nInternalFaces(); label nIntFaces = mesh.nInternalFaces();
for (label faceI = nIntFaces; faceI < mesh.nFaces(); faceI++) for (label faceI = nIntFaces; faceI < mesh.nFaces(); faceI++)
{ {
@ -492,16 +663,37 @@ int main(int argc, char *argv[])
forAll(f, fp) forAll(f, fp)
{ {
boundaryPoint.set(f[fp], 1); boundaryPoint[f[fp]] = 0;
} }
} }
// Edge collapsing engine // Get all processor boundary points and the processor patch label that
edgeCollapser collapser(mesh); // they are on.
const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
forAll(bMesh, patchI)
{
const polyPatch& patch = bMesh[patchI];
if (isA<processorPolyPatch>(patch))
{
const processorPolyPatch& pPatch =
refCast<const processorPolyPatch>(patch);
forAll(pPatch, fI)
{
const face& f = pPatch[fI];
forAll(f, fp)
{
boundaryPoint[f[fp]] = patchI;
}
}
}
}
// Collapse all edges that are too small. // Collapse all edges that are too small.
label nCollapsed = label nSmallCollapsed =
collapseSmallEdges collapseSmallEdges
( (
mesh, mesh,
@ -509,34 +701,57 @@ int main(int argc, char *argv[])
minLen, minLen,
collapser collapser
); );
Info<< "Collapsing " << nCollapsed << " small edges" << endl;
reduce(nSmallCollapsed, sumOp<label>());
Info<< indent << "Collapsing " << nSmallCollapsed
<< " small edges" << endl;
label nMerged = 0;
// Remove midpoints on straight edges. // Remove midpoints on straight edges.
if (nCollapsed == 0) if (nSmallCollapsed == 0)
{ {
nCollapsed = mergeEdges(mesh, maxCos, collapser); //nMerged = mergeEdges(mesh, maxCos, collapser);
Info<< "Collapsing " << nCollapsed << " in line edges" << endl;
} }
reduce(nMerged, sumOp<label>());
Info<< indent << "Collapsing " << nMerged << " in line edges" << endl;
label nSliversCollapsed = 0;
// Remove small sliver faces that can be collapsed to single edge // Remove small sliver faces that can be collapsed to single edge
if (nCollapsed == 0) if (nSmallCollapsed == 0 && nMerged == 0)
{ {
nCollapsed = // nSliversCollapsed =
collapseHighAspectFaces // collapseHighAspectFaces
( // (
mesh, // mesh,
boundaryPoint, // boundaryPoint,
1e-9, // factor of largest face area // processorPoints,
5, // factor between smallest and largest edge on // 1E-9, // factor of largest face area
// face // 5, // factor between smallest and largest edge on
collapser // // face
); // collapser
Info<< "Collapsing " << nCollapsed // );
<< " small high aspect ratio faces" << endl;
} }
reduce(nSliversCollapsed, sumOp<label>());
Info<< indent << "Collapsing " << nSliversCollapsed
<< " small high aspect ratio faces" << endl;
// Simplify faces to quads wherever possible // Simplify faces to quads wherever possible
//if (nCollapsed == 0) //if (nCollapsed == 0)
//{ //{
@ -553,7 +768,12 @@ int main(int argc, char *argv[])
//} //}
if (nCollapsed == 0) label totalCollapsed =
nSmallCollapsed
+ nMerged
+ nSliversCollapsed;
if (totalCollapsed == 0)
{ {
break; break;
} }
@ -564,7 +784,7 @@ int main(int argc, char *argv[])
collapser.setRefinement(meshMod); collapser.setRefinement(meshMod);
// Do all changes // Do all changes
Info<< "Morphing ..." << endl; Info<< indent << "Applying changes to the mesh" << nl << endl;
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false); autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
@ -576,6 +796,10 @@ int main(int argc, char *argv[])
} }
meshChanged = true; meshChanged = true;
Info<< decrIndent;
nIterations++;
} }
if (meshChanged) if (meshChanged)
@ -590,7 +814,8 @@ int main(int argc, char *argv[])
mesh.setInstance(oldInstance); mesh.setInstance(oldInstance);
} }
Info<< "Writing collapsed mesh to time " << runTime.timeName() << endl; Info<< nl << "Writing collapsed mesh to time "
<< runTime.timeName() << nl << endl;
mesh.write(); mesh.write();
} }

View File

@ -27,6 +27,10 @@ License
#include "polyMesh.H" #include "polyMesh.H"
#include "polyTopoChange.H" #include "polyTopoChange.H"
#include "ListOps.H" #include "ListOps.H"
#include "globalMeshData.H"
#include "OFstream.H"
#include "meshTools.H"
#include "syncTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -121,6 +125,7 @@ void Foam::edgeCollapser::filterFace(const label faceI, face& f) const
} }
} }
// Check for pinched face. Tries to correct // Check for pinched face. Tries to correct
// - consecutive duplicate vertex. Removes duplicate vertex. // - consecutive duplicate vertex. Removes duplicate vertex.
// - duplicate vertex with one other vertex in between (spike). // - duplicate vertex with one other vertex in between (spike).
@ -190,15 +195,15 @@ void Foam::edgeCollapser::printRegions() const
if (master != -1) if (master != -1)
{ {
Info<< "Region:" << regionI << nl Pout<< "Region:" << regionI << nl
<< " master:" << master << " master:" << master
<< ' ' << mesh_.points()[master] << nl; << ' ' << pointRegionMasterLocation_[regionI] << nl;
forAll(pointRegion_, pointI) forAll(pointRegion_, pointI)
{ {
if (pointRegion_[pointI] == regionI && pointI != master) if (pointRegion_[pointI] == regionI && pointI != master)
{ {
Info<< " slave:" << pointI Pout<< " slave:" << pointI
<< ' ' << mesh_.points()[pointI] << nl; << ' ' << mesh_.points()[pointI] << nl;
} }
} }
@ -272,6 +277,7 @@ Foam::edgeCollapser::edgeCollapser(const polyMesh& mesh)
: :
mesh_(mesh), mesh_(mesh),
pointRegion_(mesh.nPoints(), -1), pointRegion_(mesh.nPoints(), -1),
pointRegionMasterLocation_(mesh.nPoints() / 100),
pointRegionMaster_(mesh.nPoints() / 100), pointRegionMaster_(mesh.nPoints() / 100),
freeRegions_() freeRegions_()
{} {}
@ -289,6 +295,8 @@ bool Foam::edgeCollapser::unaffectedEdge(const label edgeI) const
bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master) bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
{ {
const pointField& points = mesh_.points();
const edge& e = mesh_.edges()[edgeI]; const edge& e = mesh_.edges()[edgeI];
label pointRegion0 = pointRegion_[e[0]]; label pointRegion0 = pointRegion_[e[0]];
@ -310,7 +318,7 @@ bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
{ {
FatalErrorIn FatalErrorIn
("edgeCollapser::collapseEdge(const label, const label)") ("edgeCollapser::collapseEdge(const label, const label)")
<< "Problem : freeed region :" << freeRegion << "Problem : freed region :" << freeRegion
<< " has already master " << " has already master "
<< pointRegionMaster_[freeRegion] << pointRegionMaster_[freeRegion]
<< abort(FatalError); << abort(FatalError);
@ -327,13 +335,22 @@ bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
pointRegion_[e[1]] = freeRegion; pointRegion_[e[1]] = freeRegion;
pointRegionMaster_(freeRegion) = master; pointRegionMaster_(freeRegion) = master;
pointRegionMasterLocation_(freeRegion) = points[master];
} }
else else
{ {
// e[1] is part of collapse network, e[0] not. Add e0 to e1 region. // e[1] is part of collapse network, e[0] not. Add e0 to e1 region.
pointRegion_[e[0]] = pointRegion1; pointRegion_[e[0]] = pointRegion1;
pointRegionMaster_[pointRegion1] = master; if
(
pointRegionMaster_[pointRegion1] == e[0]
|| pointRegionMaster_[pointRegion1] == e[1]
)
{
pointRegionMaster_[pointRegion1] = master;
pointRegionMasterLocation_[pointRegion1] = points[master];
}
} }
} }
else else
@ -343,7 +360,15 @@ bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
// e[0] is part of collapse network. Add e1 to e0 region // e[0] is part of collapse network. Add e1 to e0 region
pointRegion_[e[1]] = pointRegion0; pointRegion_[e[1]] = pointRegion0;
pointRegionMaster_[pointRegion0] = master; if
(
pointRegionMaster_[pointRegion0] == e[0]
|| pointRegionMaster_[pointRegion0] == e[1]
)
{
pointRegionMaster_[pointRegion0] = master;
pointRegionMasterLocation_[pointRegion0] = points[master];
}
} }
else if (pointRegion0 != pointRegion1) else if (pointRegion0 != pointRegion1)
{ {
@ -356,6 +381,9 @@ bool Foam::edgeCollapser::collapseEdge(const label edgeI, const label master)
// Use minRegion as region for combined net, free maxRegion. // Use minRegion as region for combined net, free maxRegion.
pointRegionMaster_[minRegion] = master; pointRegionMaster_[minRegion] = master;
pointRegionMaster_[maxRegion] = -1; pointRegionMaster_[maxRegion] = -1;
pointRegionMasterLocation_[minRegion] = points[master];
pointRegionMasterLocation_[maxRegion] = point(0, 0, 0);
freeRegions_.insert(maxRegion); freeRegions_.insert(maxRegion);
if (minRegion != pointRegion0) if (minRegion != pointRegion0)
@ -380,12 +408,61 @@ bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
const labelList& faceNeighbour = mesh_.faceNeighbour(); const labelList& faceNeighbour = mesh_.faceNeighbour();
const labelListList& pointFaces = mesh_.pointFaces(); const labelListList& pointFaces = mesh_.pointFaces();
const labelListList& cellEdges = mesh_.cellEdges(); const labelListList& cellEdges = mesh_.cellEdges();
const pointZoneMesh& pointZones = mesh_.pointZones();
// Print regions:
//printRegions()
bool meshChanged = false; bool meshChanged = false;
// Synchronise pointRegionMasterLocation_
const globalMeshData& globalData = mesh_.globalData();
const mapDistribute& map = globalData.globalPointSlavesMap();
const indirectPrimitivePatch& coupledPatch = globalData.coupledPatch();
const labelList& meshPoints = coupledPatch.meshPoints();
const Map<label>& meshPointMap = coupledPatch.meshPointMap();
List<point> newPoints = coupledPatch.localPoints();
for (label pI = 0; pI < coupledPatch.nPoints(); ++pI)
{
const label pointRegionMaster = pointRegion_[meshPoints[pI]];
if (pointRegionMaster != -1)
{
newPoints[pI]
= pointRegionMasterLocation_[pointRegionMaster];
}
}
globalData.syncData
(
newPoints,
globalData.globalPointSlaves(),
globalData.globalPointTransformedSlaves(),
map,
minMagSqrEqOp<point>()
);
OFstream str1("newPoints_" + name(Pstream::myProcNo()) + ".obj");
forAll(pointRegion_, pI)
{
if (meshPointMap.found(pI))
{
meshTools::writeOBJ(str1, newPoints[meshPointMap[pI]]);
}
}
for (label pI = 0; pI < coupledPatch.nPoints(); ++pI)
{
const label pointRegionMaster = pointRegion_[meshPoints[pI]];
if (pointRegionMaster != -1)
{
pointRegionMasterLocation_[pointRegionMaster]
= newPoints[pI];
}
}
// Current faces (is also collapseStatus: f.size() < 3) // Current faces (is also collapseStatus: f.size() < 3)
faceList newFaces(mesh_.faces()); faceList newFaces(mesh_.faces());
@ -393,7 +470,6 @@ bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
// Current cellCollapse status // Current cellCollapse status
boolList cellRemoved(mesh_.nCells(), false); boolList cellRemoved(mesh_.nCells(), false);
do do
{ {
// Update face collapse from edge collapses // Update face collapse from edge collapses
@ -521,12 +597,49 @@ bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
} }
} }
// Modify the point location of the remaining points
forAll(pointRegion_, pointI)
{
const label pointRegion = pointRegion_[pointI];
if
(
!pointRemoved(pointI)
&& meshPointMap.found(pointI)
)
{
meshMod.modifyPoint
(
pointI,
newPoints[meshPointMap[pointI]],
pointZones.whichZone(pointI),
false
);
}
else if
(
pointRegion != -1
&& !pointRemoved(pointI)
&& !meshPointMap.found(pointI)
)
{
const point& collapsePoint
= pointRegionMasterLocation_[pointRegion];
meshMod.modifyPoint
(
pointI,
collapsePoint,
pointZones.whichZone(pointI),
false
);
}
}
const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh(); const polyBoundaryMesh& boundaryMesh = mesh_.boundaryMesh();
const faceZoneMesh& faceZones = mesh_.faceZones(); const faceZoneMesh& faceZones = mesh_.faceZones();
// Renumber faces that use points // Renumber faces that use points
forAll(pointRegion_, pointI) forAll(pointRegion_, pointI)
{ {
@ -585,6 +698,9 @@ bool Foam::edgeCollapser::setRefinement(polyTopoChange& meshMod)
} }
} }
// Print regions:
// printRegions();
return meshChanged; return meshChanged;
} }
@ -593,8 +709,10 @@ void Foam::edgeCollapser::updateMesh(const mapPolyMesh& map)
{ {
pointRegion_.setSize(mesh_.nPoints()); pointRegion_.setSize(mesh_.nPoints());
pointRegion_ = -1; pointRegion_ = -1;
// Reset count, do not remove underlying storage // Reset count, do not remove underlying storage
pointRegionMaster_.clear(); pointRegionMaster_.clear();
pointRegionMasterLocation_.clear();
freeRegions_.clear(); freeRegions_.clear();
} }

View File

@ -39,6 +39,7 @@ SourceFiles
#include "labelList.H" #include "labelList.H"
#include "DynamicList.H" #include "DynamicList.H"
#include "point.H"
#include "typeInfo.H" #include "typeInfo.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -66,6 +67,10 @@ class edgeCollapser
//- For every point -1 or region number //- For every point -1 or region number
labelList pointRegion_; labelList pointRegion_;
//- Actual location of the point to collapse to for every region master
// point. This will be forced to be consistent across processors
DynamicList<point> pointRegionMasterLocation_;
//- -1 or master vertex for region number //- -1 or master vertex for region number
DynamicList<label> pointRegionMaster_; DynamicList<label> pointRegionMaster_;