Commit e81813a9 authored by laurence's avatar laurence
Browse files

ENH: Add edgeCollapser utility and libraries.

edgeCollapser collapses small edges and faces.
Works in parallel by using PointEdgeWave.
parent a2c8736f
collapseEdges.C
pointEdgeCollapse/pointEdgeCollapse.C
EXE = $(FOAM_APPBIN)/collapseEdges
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-IpointEdgeCollapse
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-ldynamicMesh \
......
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: http://www.openfoam.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
root "";
case "";
instance "";
local "";
class dictionary;
object collapseDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
collapseEdgesCoeffs
{
// Edges shorter than this absolute value will be merged
minimumEdgeLength 1e-8;
// The maximum angle between two edges that share a point attached to
// no other edges
maximumMergeAngle 30;
// The amount that minimumEdgeLength will be reduced by for each
// edge if that edge's collapse generates a poor quality face
reductionFactor 0.5;
}
collapseFacesCoeffs
{
// The initial face length factor
initialFaceLengthFactor 0.5;
// The amount that initialFaceLengthFactor will be reduced by for each
// face if its collapse generates a poor quality face
reductionFactor $initialFaceLengthFactor;
// If the face can't be collapsed to an edge, and it has a span less than
// the target face length multiplied by this coefficient, collapse it
// to a point.
maxCollapseFaceToPointSideLengthCoeff 0.3;
// Allow early collapse of edges to a point
allowEarlyCollapseToPoint on;
// Fraction to premultiply maxCollapseFaceToPointSideLengthCoeff by if
// allowEarlyCollapseToPoint is enabled
allowEarlyCollapseCoeff 0.2;
// Defining how close to the midpoint (M) of the projected
// vertices line a projected vertex (X) can be before making this
// an invalid edge collapse
//
// X---X-g----------------M----X-----------g----X--X
//
// Only allow a collapse if all projected vertices are outwith
// guardFraction (g) of the distance form the face centre to the
// furthest vertex in the considered direction
guardFraction 0.1;
}
meshQualityCoeffs
{
// Name of the dictionary that has the mesh quality coefficients used
// by motionSmoother::checkMesh
meshQualityCoeffDict meshQualityDict;
// Maximum number of outer iterations is mesh quality checking is enabled
maximumIterations 30;
}
// ************************************************************************* //
......@@ -55,6 +55,7 @@ Description
#include "edgeCollapser.H"
#include "meshTools.H"
#include "Pair.H"
#include "globalIndex.H"
using namespace Foam;
......@@ -569,26 +570,47 @@ int main(int argc, char *argv[])
// Mesh change engine
edgeCollapser cutter(mesh);
pointField newPoints(mesh.points());
const edgeList& edges = mesh.edges();
const pointField& points = mesh.points();
pointField newPoints(points);
PackedBoolList collapseEdge(mesh.nEdges());
Map<point> collapsePointToLocation(mesh.nPoints());
// Get new positions and construct collapse network
forAllConstIter(Map<point>, edgeToPos, iter)
{
label edgeI = iter.key();
const edge& e = mesh.edges()[edgeI];
const edge& e = edges[edgeI];
collapseEdge[edgeI] = true;
collapsePointToLocation.set(e[1], points[e[0]]);
cutter.collapseEdge(edgeI, e[0]);
newPoints[e[0]] = iter();
}
// Move master point to destination.
mesh.movePoints(newPoints);
List<pointEdgeCollapse> allPointInfo;
const globalIndex globalPoints(mesh.nPoints());
labelList pointPriority(mesh.nPoints(), 0);
cutter.consistentCollapse
(
globalPoints,
pointPriority,
collapsePointToLocation,
collapseEdge,
allPointInfo
);
// Topo change container
polyTopoChange meshMod(mesh);
// Insert
cutter.setRefinement(meshMod);
cutter.setRefinement(allPointInfo, meshMod);
// Do changes
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
......
......@@ -473,6 +473,7 @@ int main(int argc, char *argv[])
)
{
label nbrProcI = patchToNbrProc[patchI];
word name =
"procBoundary"
+ Foam::name(Pstream::myProcNo())
......@@ -755,6 +756,9 @@ int main(int argc, char *argv[])
const edgeList& edges = mesh.edges();
const pointField& points = mesh.points();
PackedBoolList collapseEdge(mesh.nEdges());
Map<point> collapsePointToLocation(mesh.nPoints());
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
......@@ -766,15 +770,29 @@ int main(int argc, char *argv[])
Info<< "Merging edge " << e << " since length " << d
<< " << " << mergeDim << nl;
// Collapse edge to e[0]
collapser.collapseEdge(edgeI, e[0]);
collapseEdge[edgeI] = true;
collapsePointToLocation.set(e[1], points[e[0]]);
}
}
List<pointEdgeCollapse> allPointInfo;
const globalIndex globalPoints(mesh.nPoints());
labelList pointPriority(mesh.nPoints(), 0);
collapser.consistentCollapse
(
globalPoints,
pointPriority,
collapsePointToLocation,
collapseEdge,
allPointInfo
);
// Topo change container
polyTopoChange meshMod(mesh);
// Put all modifications into meshMod
bool anyChange = collapser.setRefinement(meshMod);
bool anyChange = collapser.setRefinement(allPointInfo, meshMod);
if (anyChange)
{
......
......@@ -43,6 +43,7 @@ Note
#include "edgeCollapser.H"
#include "addPatchCellLayer.H"
#include "patchToPoly2DMesh.H"
#include "globalIndex.H"
using namespace Foam;
......@@ -260,6 +261,9 @@ int main(int argc, char *argv[])
const boundBox& bb = mesh().bounds();
const scalar mergeDim = 1e-4 * bb.minDim();
PackedBoolList collapseEdge(mesh().nEdges());
Map<point> collapsePointToLocation(mesh().nPoints());
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
......@@ -271,14 +275,27 @@ int main(int argc, char *argv[])
Info<< "Merging edge " << e << " since length " << d
<< " << " << mergeDim << nl;
// Collapse edge to e[0]
collapser.collapseEdge(edgeI, e[0]);
collapseEdge[edgeI] = true;
collapsePointToLocation.set(e[1], points[e[0]]);
}
}
List<pointEdgeCollapse> allPointInfo;
const globalIndex globalPoints(mesh().nPoints());
labelList pointPriority(mesh().nPoints(), 0);
collapser.consistentCollapse
(
globalPoints,
pointPriority,
collapsePointToLocation,
collapseEdge,
allPointInfo
);
polyTopoChange meshModCollapse(mesh());
collapser.setRefinement(meshModCollapse);
collapser.setRefinement(allPointInfo, meshModCollapse);
// Create a mesh from topo changes.
autoPtr<mapPolyMesh> morphMap
......
......@@ -25,6 +25,7 @@ polyTopoChange/polyTopoChange/topoAction/topoActions.C
polyTopoChange/polyTopoChanger/polyTopoChanger.C
polyTopoChange/polyTopoChange/polyTopoChange.C
polyTopoChange/polyTopoChange/addPatchCellLayer.C
polyTopoChange/polyTopoChange/pointEdgeCollapse/pointEdgeCollapse.C
polyTopoChange/polyTopoChange/edgeCollapser.C
polyTopoChange/polyTopoChange/faceCollapser.C
polyTopoChange/polyTopoChange/hexRef8.C
......@@ -97,5 +98,6 @@ createShellMesh/createShellMesh.C
extrudePatchMesh/extrudePatchMesh.C
polyMeshFilter/polyMeshFilter.C
LIB = $(FOAM_LIBBIN)/libdynamicMesh
This diff is collapsed.
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::polyMeshFilter
Description
SourceFiles
polyMeshFilter.C
\*---------------------------------------------------------------------------*/
#ifndef polyMeshFilter_H
#define polyMeshFilter_H
#include "IOdictionary.H"
#include "Time.H"
#include "List.H"
#include "autoPtr.H"
#include "scalarField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class polyMesh;
class fvMesh;
class PackedBoolList;
/*---------------------------------------------------------------------------*\
Class polyMeshFilter Declaration
\*---------------------------------------------------------------------------*/
class polyMeshFilter
{
// Private data
//- Reference to the original mesh
const fvMesh& mesh_;
//- Copy of the original mesh to perform the filtering on
autoPtr<fvMesh> newMeshPtr_;
//- Dictionary containing the coefficient sub-dictionaries
const IOdictionary dict_;
//- Coefficients for collapsing edges
const dictionary& collapseEdgesCoeffDict_;
//- Coefficients for collapsing faces
const dictionary& collapseFacesCoeffDict_;
//- Coefficients for controlling the mesh quality
const dictionary& meshQualityCoeffDict_;
//- Remove edges shorter than this length
const scalar minLen_;
//- Merge points that are only attached to two edges and have an angle
// between the edge greater than this value
const scalar maxCos_;
//- The amount that the local minimum edge length will be reduced by if
// the edge is part of a collapse string that generates poor quality
// faces
const scalar edgeReductionFactor_;
//- Maximum number of outer iterations
const label maxIterations_;
//- Maximum number of smoothing iterations of minEdgeLen_ and
// faceFilterFactor_
const label maxSmoothIters_;
//- Initialisation value of faceFilterFactor_
const scalar initialFaceLengthFactor_;
//- The amount that the local face size factor will be reduced by if
// the face is part of a collapse string that generates poor quality
// faces
const scalar faceReductionFactor_;
//-
const label maxPointErrorCount_;
//- The minimum edge length for each edge
scalarField minEdgeLen_;
//- The face filter factor for each face
scalarField faceFilterFactor_;
// Private Member Functions
//- Increment pointErrorCount for points attached to a bad face
void updatePointErrorCount
(
const PackedBoolList& isErrorPoint,
const labelList& oldToNewMesh,
labelList& pointErrorCount
) const;
//- Given the new points that are part of bad faces, and a map from the
// old mesh points to the new mesh points, relax minEdgeLen_
void checkMeshEdgesAndRelaxEdges
(
const polyMesh& newMesh,
const labelList& oldToNewMesh,
const PackedBoolList& isErrorPoint,
const labelList& pointErrorCount
);
//- Given the new points that are part of bad faces, and a map from the
// old mesh points to the new mesh points, relax faceFilterFactor_
void checkMeshFacesAndRelaxEdges
(
const polyMesh& newMesh,
const labelList& oldToNewMesh,
const PackedBoolList& isErrorPoint,
const labelList& pointErrorCount
);
// Mark boundary points
// boundaryPoint:
// + -1 : point not on boundary
// + 0 : point on a real boundary
// + >0 : point on a processor patch with that ID
// @todo Need to mark boundaryEdges as well, as an edge may have two
// boundary points but not itself lie on a boundary
labelList findBoundaryPoints(const polyMesh& mesh) const;
//- Print min/mean/max data for a field
void printScalarFieldStats
(
const string desc,
const scalarField& fld
) const;
//- Update minEdgeLen_ for the new mesh based upon the movement of the
// old points to the new points
void mapOldMeshEdgeFieldToNewMesh
(
const polyMesh& newMesh,
const labelList& pointMap,
scalarField& newMeshMinEdgeLen
) const;
//- Update faceFilterFactor_ for the new mesh based upon the movement
// of the old faces to the new faces
void mapOldMeshFaceFieldToNewMesh
(
const polyMesh& newMesh,
const labelList& faceMap,
scalarField& newMeshFaceFilterFactor
) const;
//- Maintain a map of the original mesh points to the latest version of
// the filtered mesh.
void updateOldToNewPointMap
(
const labelList& currToNew,
labelList& origToCurrentPointMap
) const;
//- Disallow default bitwise copy construct
polyMeshFilter(const polyMeshFilter&);
//- Disallow default bitwise assignment
void operator=(const polyMeshFilter&);
public:
// Constructors
//- Construct from fvMesh
explicit polyMeshFilter(const fvMesh& mesh);
//- Destructor
~polyMeshFilter();
// Member Functions
// Access
//- Return reference to the filtered mesh. Does not check if the
// mesh has actually been filtered.
const autoPtr<fvMesh>& filteredMesh() const;
// Edit
//- Return a copy of an fvMesh
static autoPtr<fvMesh> copyMesh(const fvMesh& mesh);
//- Filter edges and faces
label filter(const label nOriginalBadFaces);
//- Filter edges only.
label filterEdges(const label nOriginalBadFaces);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -37,10 +37,15 @@ SourceFiles
#ifndef edgeCollapser_H
#define edgeCollapser_H
#include "labelList.H"
#include "pointEdgeCollapse.H"
#include "DynamicList.H"
#include "point.H"
#include "Field.H"
#include "pointFieldFwd.H"
#include "Map.H"
#include "labelPair.H"
#include "HashSet.H"
#include "typeInfo.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -49,9 +54,11 @@ namespace Foam
// Forward declaration of classes
class polyMesh;
class PackedBoolList;
class polyTopoChange;
class globalIndex;
class face;
class mapPolyMesh;
class edge;
/*---------------------------------------------------------------------------*\
Class edgeCollapser Declaration
......@@ -59,59 +66,169 @@ class mapPolyMesh;
class edgeCollapser
{
public:
// The type of collapse of a face
enum collapseType
{
noCollapse = 0,
toPoint = 1,
toEdge = 2
};
private:
// Private data
//- Reference to mesh
const polyMesh& mesh_;
//- For every point -1 or region number
labelList pointRegion_;
const scalar guardFraction_;
//- 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_;
const scalar maxCollapseFaceToPointSideLengthCoeff_;
//- -1 or master vertex for region number
DynamicList<label> pointRegionMaster_;
const Switch allowEarlyCollapseToPoint_;
//- Stack of free region numbers. Corresponds to -1 in pointRegionMaster
SLList<label> freeRegions_;
const scalar allowEarlyCollapseCoeff_;
// Static Functions
// Private Member Functions
//- Find val in list. Search starts at start, continues to size-1.
static label findIndex
//- Create an edgeList of edges in faceI which have both their points
// in pointLabels
labelList edgesFromPoints
(
const labelList&,
const label start,
const label size,