ENH: foamyHexMesh: Include baffle handling

This commit is contained in:
laurence
2013-09-25 12:37:19 +01:00
parent e656bb49c5
commit 615a74626e
42 changed files with 2444 additions and 1380 deletions

View File

@ -52,6 +52,7 @@ Usage
#include "polyTopoChange.H"
#include "fvMesh.H"
#include "polyMeshFilter.H"
#include "faceSet.H"
using namespace Foam;
@ -74,9 +75,9 @@ int main(int argc, char *argv[])
argList::addOption
(
"collapseFaceZone",
"zoneName",
"Collapse faces that are in the supplied face zone"
"collapseFaceSet",
"faceSet",
"Collapse faces that are in the supplied face set"
);
# include "addOverwriteOption.H"
@ -93,15 +94,15 @@ int main(int argc, char *argv[])
const bool overwrite = args.optionFound("overwrite");
const bool collapseFaces = args.optionFound("collapseFaces");
const bool collapseFaceZone = args.optionFound("collapseFaceZone");
const bool collapseFaceSet = args.optionFound("collapseFaceSet");
if (collapseFaces && collapseFaceZone)
if (collapseFaces && collapseFaceSet)
{
FatalErrorIn("main(int, char*[])")
<< "Both face zone collapsing and face collapsing have been"
<< "selected. Choose only one of:" << nl
<< " -collapseFaces" << nl
<< " -collapseFaceZone <faceZoneName>"
<< " -collapseFaceSet <faceSet>"
<< abort(FatalError);
}
@ -117,7 +118,6 @@ int main(int argc, char *argv[])
),
labelList(mesh.nPoints(), labelMin)
);
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
@ -128,6 +128,14 @@ int main(int argc, char *argv[])
label nBadFaces = 0;
faceSet indirectPatchFaces
(
mesh,
"indirectPatchFaces",
IOobject::MUST_READ,
IOobject::AUTO_WRITE
);
{
meshFilterPtr.set(new polyMeshFilter(mesh, pointPriority));
polyMeshFilter& meshFilter = meshFilterPtr();
@ -139,19 +147,26 @@ int main(int argc, char *argv[])
// the face filtering is sped up.
nBadFaces = meshFilter.filterEdges(0);
{
polyTopoChange meshMod(newMesh);
polyTopoChange meshMod(newMesh());
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();
}
if (collapseFaceZone)
if (collapseFaceSet)
{
const word faceZoneName = args.optionRead<word>("collapseFaceZone");
const faceZone& fZone = mesh.faceZones()[faceZoneName];
const word faceSetName(args.optionRead<word>("collapseFaceSet"));
faceSet fSet
(
mesh,
faceSetName,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
);
meshFilterPtr.reset(new polyMeshFilter(mesh, pointPriority));
polyMeshFilter& meshFilter = meshFilterPtr();
@ -160,11 +175,13 @@ int main(int argc, char *argv[])
// Filter faces. Pass in the number of bad faces that are present
// from the previous edge filtering to use as a stopping criterion.
meshFilter.filter(fZone);
meshFilter.filter(fSet);
{
polyTopoChange meshMod(newMesh);
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();
@ -184,6 +201,8 @@ int main(int argc, char *argv[])
polyTopoChange meshMod(newMesh);
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();

View File

@ -10,6 +10,7 @@ include $(GENERAL_RULES)/CGAL
EXE_INC = \
${EXE_FROUNDING_MATH} \
${EXE_NDEBUG} \
${CGAL_EXACT} \
${CGAL_INEXACT} \
${CGAL_INC} \
-IconformalVoronoiMesh/lnInclude \

View File

@ -190,20 +190,25 @@ void Foam::DelaunayMesh<Triangulation>::reset()
resetVertexCount();
resetCellCount();
insertPoints(vertices);
insertPoints(vertices, false);
Info<< "Inserted " << vertexCount() << " fixed points" << endl;
}
template<class Triangulation>
void Foam::DelaunayMesh<Triangulation>::insertPoints(const List<Vb>& vertices)
Foam::Map<Foam::label> Foam::DelaunayMesh<Triangulation>::insertPoints
(
const List<Vb>& vertices,
const bool reIndex
)
{
rangeInsertWithInfo
return rangeInsertWithInfo
(
vertices.begin(),
vertices.end(),
false
false,
reIndex
);
}
@ -268,7 +273,7 @@ const
template<class Triangulation>
template<class PointIterator>
void Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
Foam::Map<Foam::label> Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
(
PointIterator begin,
PointIterator end,
@ -307,6 +312,10 @@ void Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
Vertex_handle hint;
Map<label> oldToNewIndex(points.size());
label maxIndex = -1;
for
(
typename vectorPairPointIndex::const_iterator p = points.begin();
@ -335,11 +344,14 @@ void Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
{
if (reIndex)
{
const label oldIndex = vert.index();
hint->index() = getNewVertexIndex();
oldToNewIndex.insert(oldIndex, hint->index());
}
else
{
hint->index() = vert.index();
maxIndex = max(maxIndex, vert.index());
}
hint->type() = vert.type();
hint->procIndex() = vert.procIndex();
@ -347,6 +359,13 @@ void Foam::DelaunayMesh<Triangulation>::rangeInsertWithInfo
hint->alignment() = vert.alignment();
}
}
if (!reIndex)
{
vertexCount_ = maxIndex + 1;
}
return oldToNewIndex;
}

View File

@ -228,7 +228,11 @@ public:
void reset();
//- Insert the list of vertices (calls rangeInsertWithInfo)
void insertPoints(const List<Vb>& vertices);
Map<label> insertPoints
(
const List<Vb>& vertices,
const bool reIndex
);
//- Function inserting points into a triangulation and setting the
// index and type data of the point in the correct order. This is
@ -237,7 +241,7 @@ public:
// Adapted from a post on the CGAL lists: 2010-01/msg00004.html by
// Sebastien Loriot (Geometry Factory).
template<class PointIterator>
void rangeInsertWithInfo
Map<label> rangeInsertWithInfo
(
PointIterator begin,
PointIterator end,

View File

@ -536,7 +536,8 @@ Foam::label Foam::DistributedDelaunayMesh<Triangulation>::referVertices
labelPairHashSet pointsNotInserted = rangeInsertReferredWithInfo
(
referredVertices.begin(),
referredVertices.end()
referredVertices.end(),
true
);
if (!pointsNotInserted.empty())

View File

@ -76,6 +76,7 @@ faceAreaWeightModel/piecewiseLinearRamp/piecewiseLinearRamp.C
searchableSurfaceFeatures/searchableSurfaceFeatures.C
searchableSurfaceFeatures/searchableBoxFeatures.C
searchableSurfaceFeatures/searchablePlateFeatures.C
searchableSurfaceFeatures/triSurfaceMeshFeatures.C
LIB = $(FOAM_LIBBIN)/libconformalVoronoiMesh

View File

@ -11,6 +11,7 @@ FFLAGS = -DCGAL_FILES='"${CGAL_ARCH_PATH}/share/files"'
EXE_INC = \
${EXE_FROUNDING_MATH} \
${EXE_NDEBUG} \
${CGAL_EXACT} \
${CGAL_INEXACT} \
${CGAL_INC} \
-I$(LIB_SRC)/finiteVolume/lnInclude \

View File

@ -628,49 +628,6 @@ Foam::tensorField Foam::cellShapeControlMesh::dumpAlignments() const
}
void Foam::cellShapeControlMesh::insertBoundingPoints
(
const boundBox& bb,
const cellSizeAndAlignmentControls& sizeControls
)
{
// Loop over bound box points and get cell size and alignment
const pointField bbPoints(bb.points());
forAll(bbPoints, pI)
{
const Foam::point& pt = bbPoints[pI];
// Cell size here will return default cell size
const scalar cellSize = sizeControls.cellSize(pt);
if (debug)
{
Info<< "Insert Bounding Point: " << pt << " " << cellSize << endl;
}
// Get the cell size of the nearest surface.
// geometryToConformTo_.findSurfaceNearest
// (
// pt,
// GREAT,
// surfHit,
// hitSurface
// );
const tensor alignment = tensor::I;
insert
(
pt,
cellSize,
alignment,
Vb::vtInternalNearBoundary
);
}
}
void Foam::cellShapeControlMesh::write() const
{
Info<< "Writing " << meshSubDir << endl;
@ -781,4 +738,78 @@ void Foam::cellShapeControlMesh::write() const
}
Foam::label Foam::cellShapeControlMesh::estimateCellCount
(
const autoPtr<backgroundMeshDecomposition>& decomposition
) const
{
// Loop over all the tets and estimate the cell count in each one
scalar cellCount = 0;
for
(
Finite_cells_iterator cit = finite_cells_begin();
cit != finite_cells_end();
++cit
)
{
if (!cit->hasFarPoint() && !is_infinite(cit))
{
// @todo Check if tet centre is on the processor..
CGAL::Tetrahedron_3<baseK> tet
(
cit->vertex(0)->point(),
cit->vertex(1)->point(),
cit->vertex(2)->point(),
cit->vertex(3)->point()
);
pointFromPoint centre = topoint(CGAL::centroid(tet));
if
(
Pstream::parRun()
&& !decomposition().positionOnThisProcessor(centre)
)
{
continue;
}
scalar volume = CGAL::to_double(tet.volume());
scalar averagedPointCellSize = 0;
//scalar averagedPointCellSize = 1;
// Get an average volume by averaging the cell size of the vertices
for (label vI = 0; vI < 4; ++vI)
{
averagedPointCellSize += cit->vertex(vI)->targetCellSize();
//averagedPointCellSize *= cit->vertex(vI)->targetCellSize();
}
averagedPointCellSize /= 4;
//averagedPointCellSize = ::sqrt(averagedPointCellSize);
// if (averagedPointCellSize < SMALL)
// {
// Pout<< "Volume = " << volume << endl;
//
// for (label vI = 0; vI < 4; ++vI)
// {
// Pout<< "Point " << vI
// << ", point = " << topoint(cit->vertex(vI)->point())
// << ", size = " << cit->vertex(vI)->targetCellSize()
// << endl;
// }
// }
cellCount += volume/pow(averagedPointCellSize, 3);
}
}
return cellCount;
}
// ************************************************************************* //

View File

@ -153,15 +153,14 @@ public:
tensorField dumpAlignments() const;
void insertBoundingPoints
(
const boundBox& bb,
const cellSizeAndAlignmentControls& sizeControls
);
void writeTriangulation();
void write() const;
label estimateCellCount
(
const autoPtr<backgroundMeshDecomposition>& decomposition
) const;
};

View File

@ -429,6 +429,11 @@ void Foam::searchableSurfaceControl::initialVertices
vectorField normals(1);
searchableSurface_.getNormal(infoList, normals);
if (mag(normals[0]) < SMALL)
{
normals[0] = vector(1, 1, 1);
}
pointAlignment.set(new triad(normals[0]));
if (infoList[0].hit())

View File

@ -768,7 +768,7 @@ Foam::label Foam::controlMeshRefinement::refineMesh
}
}
mesh_.insertPoints(verts);
mesh_.insertPoints(verts, false);
return verts.size();
}

View File

@ -179,16 +179,24 @@ void Foam::conformalVoronoiMesh::insertInternalPoints
}
void Foam::conformalVoronoiMesh::insertPoints
Foam::Map<Foam::label> Foam::conformalVoronoiMesh::insertPointPairs
(
List<Vb>& vertices,
bool distribute
bool distribute,
bool reIndex
)
{
if (Pstream::parRun() && distribute)
{
autoPtr<mapDistribute> mapDist =
decomposition_().distributePoints(vertices);
// Re-index the point pairs if one or both have been distributed.
// If both, remove
// If added a point, then need to know its point pair
// If one moved, then update procIndex locally
forAll(vertices, vI)
{
vertices[vI].procIndex() = Pstream::myProcNo();
@ -197,7 +205,8 @@ void Foam::conformalVoronoiMesh::insertPoints
label preReinsertionSize(number_of_vertices());
this->DelaunayMesh<Delaunay>::insertPoints(vertices);
Map<label> oldToNewIndices =
this->DelaunayMesh<Delaunay>::insertPoints(vertices, reIndex);
const label nReinserted = returnReduce
(
@ -208,17 +217,18 @@ void Foam::conformalVoronoiMesh::insertPoints
Info<< " Reinserted " << nReinserted << " vertices out of "
<< returnReduce(vertices.size(), sumOp<label>())
<< endl;
return oldToNewIndices;
}
void Foam::conformalVoronoiMesh::insertSurfacePointPairs
(
const pointIndexHitAndFeatureList& surfaceHits,
const fileName fName
const fileName fName,
DynamicList<Vb>& pts
)
{
DynamicList<Vb> pts(2.0*surfaceHits.size());
forAll(surfaceHits, i)
{
vectorField norm(1);
@ -246,6 +256,7 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
pointPairDistance(surfacePt),
surfacePt,
normal,
true,
pts
);
}
@ -256,6 +267,7 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
pointPairDistance(surfacePt),
surfacePt,
normal,
true,
pts
);
}
@ -266,6 +278,7 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
pointPairDistance(surfacePt),
surfacePt,
-normal,
true,
pts
);
}
@ -280,8 +293,6 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
}
}
insertPoints(pts, true);
if (foamyHexMeshControls().objOutput() && fName != fileName::null)
{
DelaunayMeshTools::writeOBJ(time().path()/fName, pts);
@ -292,11 +303,10 @@ void Foam::conformalVoronoiMesh::insertSurfacePointPairs
void Foam::conformalVoronoiMesh::insertEdgePointGroups
(
const pointIndexHitAndFeatureList& edgeHits,
const fileName fName
const fileName fName,
DynamicList<Vb>& pts
)
{
DynamicList<Vb> pts(3.0*edgeHits.size());
forAll(edgeHits, i)
{
if (edgeHits[i].first().hit())
@ -318,10 +328,6 @@ void Foam::conformalVoronoiMesh::insertEdgePointGroups
}
}
pts.shrink();
insertPoints(pts, true);
if (foamyHexMeshControls().objOutput() && fName != fileName::null)
{
DelaunayMeshTools::writeOBJ(time().path()/fName, pts);
@ -859,6 +865,7 @@ Foam::conformalVoronoiMesh::conformalVoronoiMesh
geometryToConformTo_
),
limitBounds_(),
ptPairs_(*this),
ftPtConformer_(*this),
edgeLocationTreePtr_(),
surfacePtLocationTreePtr_(),
@ -1108,7 +1115,7 @@ void Foam::conformalVoronoiMesh::move()
vB->alignment().T() & cartesianDirections
);
Field<vector> alignmentDirs(3);
Field<vector> alignmentDirs(alignmentDirsA);
forAll(alignmentDirsA, aA)
{
@ -1332,14 +1339,19 @@ void Foam::conformalVoronoiMesh::move()
{
// Point removal
if
(
(
vA->internalPoint()
&& !vA->referred()
&& !vA->fixed()
&& vB->internalPoint()
)
&&
(
vB->internalPoint()
&& !vB->referred()
&& !vB->fixed()
)
)
{
// Only insert a point at the midpoint of
// the short edge if neither attached
@ -1507,9 +1519,7 @@ void Foam::conformalVoronoiMesh::move()
Info<< "Writing point displacement vectors to file." << endl;
OFstream str
(
time().path()
+ "displacements_" + runTime_.timeName()
+ ".obj"
time().path()/"displacements_" + runTime_.timeName() + ".obj"
);
for
@ -1607,6 +1617,74 @@ void Foam::conformalVoronoiMesh::move()
time().path()/"boundaryPoints_" + time().timeName() + ".obj",
*this
);
DelaunayMeshTools::writeOBJ
(
time().path()/"internalBoundaryPoints_" + time().timeName()
+ ".obj",
*this,
Foam::indexedVertexEnum::vtInternalSurface,
Foam::indexedVertexEnum::vtInternalFeaturePoint
);
DelaunayMeshTools::writeOBJ
(
time().path()/"externalBoundaryPoints_" + time().timeName()
+ ".obj",
*this,
Foam::indexedVertexEnum::vtExternalSurface,
Foam::indexedVertexEnum::vtExternalFeaturePoint
);
OBJstream multipleIntersections
(
"multipleIntersections_"
+ time().timeName()
+ ".obj"
);
for
(
Delaunay::Finite_edges_iterator eit = finite_edges_begin();
eit != finite_edges_end();
++eit
)
{
Cell_handle c = eit->first;
Vertex_handle vA = c->vertex(eit->second);
Vertex_handle vB = c->vertex(eit->third);
Foam::point ptA(topoint(vA->point()));
Foam::point ptB(topoint(vB->point()));
List<pointIndexHit> surfHits;
labelList hitSurfaces;
geometryToConformTo().findSurfaceAllIntersections
(
ptA,
ptB,
surfHits,
hitSurfaces
);
if
(
surfHits.size() >= 2
|| (
surfHits.size() == 0
&& (
(vA->externalBoundaryPoint()
&& vB->internalBoundaryPoint())
|| (vB->externalBoundaryPoint()
&& vA->internalBoundaryPoint())
)
)
)
{
multipleIntersections.write(linePointRef(ptA, ptB));
}
}
}
}
@ -1629,49 +1707,6 @@ void Foam::conformalVoronoiMesh::move()
}
//Foam::labelListList Foam::conformalVoronoiMesh::overlapsProc
//(
// const List<Foam::point>& centres,
// const List<scalar>& radiusSqrs
//) const
//{
// if (!Pstream::parRun())
// {
// return labelListList(centres.size(), labelList(0));
// }
//
//// DynamicList<Foam::point> pts(number_of_vertices());
//
//// for
//// (
//// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
//// vit != finite_vertices_end();
//// vit++
//// )
//// {
//// pts.append(topoint(vit->point()));
//// }
////
//// dynamicIndexedOctree<dynamicTreeDataPoint> vertexOctree
//// (
//// dynamicTreeDataPoint(pts),
//// treeBoundBox(min(pts), max(pts)),
//// 10, // maxLevel
//// 10, // leafSize
//// 3.0 // duplicity
//// );
//
// return decomposition_().overlapsProcessors
// (
// centres,
// radiusSqrs,
// *this,
// false//,
//// vertexOctree
// );
//}
void Foam::conformalVoronoiMesh::checkCoPlanarCells() const
{
typedef CGAL::Exact_predicates_exact_constructions_kernel Kexact;

View File

@ -77,7 +77,7 @@ SourceFiles
#include "Pair.H"
#include "DistributedDelaunayMesh.H"
#include "featurePointConformer.H"
#include "pointPairs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -86,12 +86,10 @@ namespace Foam
// Forward declaration of classes
class initialPointsMethod;
class relaxationModel;
class faceAreaWeightModel;
class backgroundMeshDecomposition;
class OBJstream;
/*---------------------------------------------------------------------------*\
Class conformalVoronoiMesh Declaration
@ -165,6 +163,9 @@ private:
//- Limiting bound box before infinity begins
treeBoundBox limitBounds_;
//-
mutable pointPairs<Delaunay> ptPairs_;
//-
featurePointConformer ftPtConformer_;
@ -229,10 +230,11 @@ private:
const bool distribute = false
);
void insertPoints
Map<label> insertPointPairs
(
List<Vb>& vertices,
bool distribute
bool distribute,
bool reIndex
);
//- Create a point-pair at a ppDist distance either side of
@ -242,6 +244,7 @@ private:
const scalar ppDist,
const Foam::point& surfPt,
const vector& n,
const bool ptPair,
DynamicList<Vb>& pts
) const;
@ -254,24 +257,20 @@ private:
const scalar ppDist,
const Foam::point& surfPt,
const vector& n,
const bool ptPair,
DynamicList<Vb>& pts
) const;
//- Check internal point is completely inside the meshable region
inline bool internalPointIsInside(const Foam::point& pt) const;
inline bool isPointPair
(
const Vertex_handle& vA,
const Vertex_handle& vB
) const;
//- Insert pairs of points on the surface with the given normals, at the
// specified spacing
void insertSurfacePointPairs
(
const pointIndexHitAndFeatureList& surfaceHits,
const fileName fName = fileName::null
const fileName fName,
DynamicList<Vb>& pts
);
//- Insert groups of points to conform to an edge given a list of
@ -280,7 +279,8 @@ private:
void insertEdgePointGroups
(
const pointIndexHitAndFeatureList& edgeHits,
const fileName fName = fileName::null
const fileName fName,
DynamicList<Vb>& pts
);
void createEdgePointGroupByCirculating
@ -474,14 +474,11 @@ private:
label& hitSurface
) const;
//- Find the "worst" incursion of the dual cell of a non-internal or
// boundary point through the surface, subject to the
// maxSurfaceProtrusion tolerance
void dualCellLargestSurfaceIncursion
(
const Delaunay::Finite_vertices_iterator& vit,
pointIndexHit& surfHitLargest,
label& hitSurfaceLargest
pointIndexHit& surfHit,
label& hitSurface
) const;
//- Write out vertex-processor occupancy information for debugging
@ -695,7 +692,8 @@ private:
//- Merge vertices that are identical
void mergeIdenticalDualVertices
(
const pointField& pts
const pointField& pts,
labelList& boundaryPts
);
label mergeIdenticalDualVertices
@ -736,7 +734,11 @@ private:
);
//- Re-index all of the Delaunay cells
void reindexDualVertices(const Map<label>& dualPtIndexMap);
void reindexDualVertices
(
const Map<label>& dualPtIndexMap,
labelList& boundaryPts
);
label createPatchInfo
(
@ -846,6 +848,8 @@ private:
const PtrList<dictionary>& patchDicts
) const;
void writePointPairs(const fileName& fName) const;
//- Disallow default bitwise copy construct
conformalVoronoiMesh(const conformalVoronoiMesh&);
@ -992,7 +996,7 @@ public:
const wordList& patchNames,
const PtrList<dictionary>& patchDicts,
const pointField& cellCentres,
const PackedBoolList& boundaryFacesToRemove
PackedBoolList& boundaryFacesToRemove
) const;
//- Calculate and write a field of the target cell size,

View File

@ -30,487 +30,11 @@ License
#include "indexedCellChecks.H"
#include "OBJstream.H"
#include "indexedCellOps.H"
#include "ListOps.H"
#include "DelaunayMeshTools.H"
#include "CGAL/Exact_predicates_exact_constructions_kernel.h"
#include "CGAL/Gmpq.h"
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::conformalVoronoiMesh::checkCells()
{
List<List<FixedList<Foam::point, 4> > > cellListList(Pstream::nProcs());
List<FixedList<Foam::point, 4> > cells(number_of_finite_cells());
globalIndex gIndex(number_of_vertices());
label count = 0;
for
(
Delaunay::Finite_cells_iterator cit = finite_cells_begin();
cit != finite_cells_end();
++cit
)
{
if (tetrahedron(cit).volume() == 0)
{
Pout<< "ZERO VOLUME TET" << endl;
Pout<< cit->info();
Pout<< cit->dual();
}
if (cit->hasFarPoint())
{
continue;
}
List<labelPair> cellVerticesPair(4);
List<Foam::point> cellVertices(4);
for (label vI = 0; vI < 4; ++vI)
{
cellVerticesPair[vI] = labelPair
(
cit->vertex(vI)->procIndex(),
cit->vertex(vI)->index()
);
cellVertices[vI] = topoint(cit->vertex(vI)->point());
}
List<Foam::point> cellVerticesOld(cellVertices);
labelList oldToNew;
sortedOrder(cellVerticesPair, oldToNew);
oldToNew = invert(oldToNew.size(), oldToNew);
inplaceReorder(oldToNew, cellVerticesPair);
inplaceReorder(oldToNew, cellVertices);
// FixedList<label, 4> globalTetCell
// (
// cit->globallyOrderedCellVertices(gIndex)
// );
//
// FixedList<Point, 4> cellVertices(Point(0,0,0));
//
// forAll(globalTetCell, gvI)
// {
// label gI = globalTetCell[gvI];
//
// cellVertices[gvI] = cit->vertex(gI)->point();
// }
// if (cit->hasFarPoint())
// {
// continue;
// }
for (label i = 0; i < 4; ++i)
{
//cells[count][i] = topoint(cit->vertex(i)->point());
cells[count][i] = cellVertices[i];
}
count++;
}
cells.setSize(count);
cellListList[Pstream::myProcNo()] = cells;
Pstream::gatherList(cellListList);
if (Pstream::master())
{
Info<< "Checking on master processor the cells of each " << nl
<< "processor point list against the master cell list." << nl
<< "There are " << cellListList.size() << " processors" << nl
<< "The size of each processor's cell list is:" << endl;
forAll(cellListList, cfI)
{
Info<< " Proc " << cfI << " has " << cellListList[cfI].size()
<< " cells" << endl;
}
label nMatches = 0, nMatchFoundDiffOrder = 0;
forAll(cellListList[0], cmI)
{
const FixedList<Foam::point, 4>& masterCell = cellListList[0][cmI];
bool matchFound = false;
bool matchFoundDiffOrder = false;
forAll(cellListList, cpI)
{
if (cpI == 0)
{
continue;
}
forAll(cellListList[cpI], csI)
{
const FixedList<Foam::point, 4>& slaveCell
= cellListList[cpI][csI];
if (masterCell == slaveCell)
{
matchFound = true;
break;
}
else
{
label samePt = 0;
forAll(masterCell, mI)
{
const Foam::point& mPt = masterCell[mI];
forAll(slaveCell, sI)
{
const Foam::point& sPt = slaveCell[sI];
if (mPt == sPt)
{
samePt++;
}
}
}
if (samePt == 4)
{
matchFoundDiffOrder = true;
Pout<< masterCell << nl << slaveCell << endl;
break;
}
}
}
}
if (matchFound)
{
nMatches++;
}
if (matchFoundDiffOrder)
{
nMatchFoundDiffOrder++;
}
}
Info<< "Found " << nMatches << " matching cells and "
<< nMatchFoundDiffOrder << " matching cells with different "
<< "vertex ordering"<< endl;
}
}
//void Foam::conformalVoronoiMesh::checkDuals()
//{
// List<List<Point> > pointFieldList(Pstream::nProcs());
//
// List<Point> duals(number_of_finite_cells());
//
// typedef CGAL::Exact_predicates_exact_constructions_kernel EK2;
// typedef CGAL::Regular_triangulation_euclidean_traits_3<EK2> EK;
// typedef CGAL::Cartesian_converter<baseK::Kernel, EK2> To_exact;
// typedef CGAL::Cartesian_converter<EK2, baseK::Kernel> Back_from_exact;
//
//// PackedBoolList bPoints(number_of_finite_cells());
//
//// indexDualVertices(duals, bPoints);
//
// label count = 0;//duals.size();
//
// duals.setSize(number_of_finite_cells());
//
// globalIndex gIndex(number_of_vertices());
//
// for
// (
// Delaunay::Finite_cells_iterator cit = finite_cells_begin();
// cit != finite_cells_end();
// ++cit
// )
// {
// if (cit->hasFarPoint())
// {
// continue;
// }
//
// duals[count++] = cit->circumcenter();
//
//// List<labelPair> cellVerticesPair(4);
//// List<Point> cellVertices(4);
////
//// for (label vI = 0; vI < 4; ++vI)
//// {
//// cellVerticesPair[vI] = labelPair
//// (
//// cit->vertex(vI)->procIndex(),
//// cit->vertex(vI)->index()
//// );
//// cellVertices[vI] = cit->vertex(vI)->point();
//// }
////
//// labelList oldToNew;
//// sortedOrder(cellVerticesPair, oldToNew);
//// oldToNew = invert(oldToNew.size(), oldToNew);
//// inplaceReorder(oldToNew, cellVerticesPair);
//// inplaceReorder(oldToNew, cellVertices);
////
//// duals[count++] = CGAL::circumcenter
//// (
//// cellVertices[0],
//// cellVertices[1],
//// cellVertices[2],
//// cellVertices[3]
//// );
//
//// To_exact to_exact;
//// Back_from_exact back_from_exact;
//// EK::Construct_circumcenter_3 exact_circumcenter =
//// EK().construct_circumcenter_3_object();
////
//// duals[count++] = topoint
//// (
//// back_from_exact
//// (
//// exact_circumcenter
//// (
//// to_exact(cit->vertex(0)->point()),
//// to_exact(cit->vertex(1)->point()),
//// to_exact(cit->vertex(2)->point()),
//// to_exact(cit->vertex(3)->point())
//// )
//// )
//// );
// }
//
// Pout<< "Duals Calculated " << count << endl;
//
// duals.setSize(count);
//
// pointFieldList[Pstream::myProcNo()] = duals;
//
// Pstream::gatherList(pointFieldList);
//
// if (Pstream::master())
// {
// Info<< "Checking on master processor the dual locations of each" << nl
// << " processor point list against the master dual list." << nl
// << "There are " << pointFieldList.size() << " processors" << nl
// << "The size of each processor's dual list is:" << endl;
//
// forAll(pointFieldList, pfI)
// {
// Info<< " Proc " << pfI << " has " << pointFieldList[pfI].size()
// << " duals" << endl;
// }
//
// label nNonMatches = 0;
// label nNearMatches = 0;
// label nExactMatches = 0;
//
// forAll(pointFieldList[0], pI)
// {
// const Point& masterPoint = pointFieldList[0][pI];
//
// bool foundMatch = false;
// bool foundNearMatch = false;
//
// scalar minCloseness = GREAT;
// Point closestPoint(0, 0, 0);
//
// forAll(pointFieldList, pfI)
// {
// if (pfI == 0)
// {
// continue;
// }
//
//// label pfI = 1;
//
// forAll(pointFieldList[pfI], pISlave)
// {
// const Point& slavePoint
// = pointFieldList[pfI][pISlave];
//
// if (masterPoint == slavePoint)
// {
// foundMatch = true;
// break;
// }
//
// const scalar closeness = mag
// (
// topoint(masterPoint) - topoint(slavePoint)
// );
//
// if (closeness < 1e-12)
// {
// foundNearMatch = true;
// }
// else
// {
// if (closeness < minCloseness)
// {
// minCloseness = closeness;
// closestPoint = slavePoint;
// }
// }
// }
//
// if (!foundMatch)
// {
// if (foundNearMatch)
// {
// CGAL::Gmpq x(CGAL::to_double(masterPoint.x()));
// CGAL::Gmpq y(CGAL::to_double(masterPoint.y()));
// CGAL::Gmpq z(CGAL::to_double(masterPoint.z()));
//
// std::cout<< "master = " << x << " " << y << " " << z
// << std::endl;
//
// CGAL::Gmpq xs(CGAL::to_double(closestPoint.x()));
// CGAL::Gmpq ys(CGAL::to_double(closestPoint.y()));
// CGAL::Gmpq zs(CGAL::to_double(closestPoint.z()));
// std::cout<< "slave = " << xs << " " << ys << " "
// << zs
// << std::endl;
//
// nNearMatches++;
// }
// else
// {
// nNonMatches++;
// Info<< "Closest point to " << masterPoint << " is "
// << closestPoint << nl
// << " Separation is " << minCloseness << endl;
//
// CGAL::Gmpq x(CGAL::to_double(masterPoint.x()));
// CGAL::Gmpq y(CGAL::to_double(masterPoint.y()));
// CGAL::Gmpq z(CGAL::to_double(masterPoint.z()));
//
// std::cout<< "master = " << x << " " << y << " " << z
// << std::endl;
//
// CGAL::Gmpq xs(CGAL::to_double(closestPoint.x()));
// CGAL::Gmpq ys(CGAL::to_double(closestPoint.y()));
// CGAL::Gmpq zs(CGAL::to_double(closestPoint.z()));
// std::cout<< "slave = " << xs << " " << ys << " "
// << zs
// << std::endl;
// }
// }
// else
// {
// nExactMatches++;
// }
// }
// }
//
// Info<< "Found " << nNonMatches << " non-matching duals" << nl
// << " and " << nNearMatches << " near matches"
// << " and " << nExactMatches << " exact matches" << endl;
// }
//}
void Foam::conformalVoronoiMesh::checkVertices()
{
List<pointField> pointFieldList(Pstream::nProcs());
pointField points(number_of_vertices());
labelPairHashSet duplicateVertices;
label count = 0;
for
(
Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
vit != finite_vertices_end();
++vit
)
{
if (duplicateVertices.found(labelPair(vit->procIndex(), vit->index())))
{
Pout<< "DUPLICATE " << vit->procIndex() << vit->index() << endl;
}
else
{
duplicateVertices.insert(labelPair(vit->procIndex(), vit->index()));
}
points[count++] = topoint(vit->point());
}
pointFieldList[Pstream::myProcNo()] = points;
Pstream::gatherList(pointFieldList);
OFstream str("missingPoints.obj");
if (Pstream::master())
{
Info<< "Checking on master processor the point locations of each " << nl
<< "processor point list against the master point list." << nl
<< "There are " << pointFieldList.size() << " processors" << nl
<< "The size of each processor's point list is:" << endl;
forAll(pointFieldList, pfI)
{
Info<< " Proc " << pfI << " has " << pointFieldList[pfI].size()
<< " points" << endl;
}
label nNonMatches = 0;
forAll(pointFieldList[0], pI)
{
const Foam::point& masterPoint = pointFieldList[0][pI];
forAll(pointFieldList, pfI)
{
if (pI == 0)
{
continue;
}
bool foundMatch = false;
forAll(pointFieldList[pfI], pISlave)
{
const Foam::point& slavePoint
= pointFieldList[pfI][pISlave];
if (masterPoint == slavePoint)
{
foundMatch = true;
break;
}
}
if (!foundMatch)
{
Info<< " Proc " << pfI << " Master != Slave -> "
<< masterPoint << endl;
meshTools::writeOBJ(str, masterPoint);
nNonMatches++;
}
}
}
Info<< "Found a total of " << nNonMatches << " non-matching points"
<< endl;
}
}
void Foam::conformalVoronoiMesh::calcDualMesh
(
pointField& points,
@ -528,53 +52,6 @@ void Foam::conformalVoronoiMesh::calcDualMesh
{
timeCheck("Start calcDualMesh");
// if (debug)
// {
// Pout<< nl << "Perfoming some checks . . ." << nl << nl
// << "Total number of vertices = " << number_of_vertices() << nl
// << "Total number of cells = " << number_of_finite_cells()
// << endl;
//
// checkVertices();
// checkCells();
// checkDuals();
//
// Info<< nl << "Finished checks" << nl << endl;
// }
// OFstream str("attachedToFeature.obj");
// label offset = 0;
//
// for
// (
// Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
// vit != finite_vertices_end();
// ++vit
// )
// {
// if (vit->featurePoint())
// {
// std::list<Cell_handle> adjacentCells;
//
// finite_incident_cells(vit, std::back_inserter(adjacentCells));
//
// for
// (
// std::list<Cell_handle>::iterator acit = adjacentCells.begin();
// acit != adjacentCells.end();
// ++acit
// )
// {
// if ((*acit)->real())
// {
// drawDelaunayCell(str, (*acit), offset);
// offset++;
//// meshTools::writeOBJ(str, topoint((*acit)->dual()));
// }
// }
// }
// }
setVertexSizeAndAlignment();
timeCheck("After setVertexSizeAndAlignment");
@ -585,7 +62,7 @@ void Foam::conformalVoronoiMesh::calcDualMesh
Info<< nl << "Merging identical points" << endl;
// There is no guarantee that a merge of close points is no-risk
mergeIdenticalDualVertices(points);
mergeIdenticalDualVertices(points, boundaryPts);
}
// Final dual face and owner neighbour construction
@ -820,7 +297,8 @@ void Foam::conformalVoronoiMesh::calcTetMesh
void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices
(
const pointField& pts
const pointField& pts,
labelList& boundaryPts
)
{
// Assess close points to be merged
@ -838,7 +316,7 @@ void Foam::conformalVoronoiMesh::mergeIdenticalDualVertices
dualPtIndexMap
);
reindexDualVertices(dualPtIndexMap);
reindexDualVertices(dualPtIndexMap, boundaryPts);
reduce(nPtsMerged, sumOp<label>());
@ -1245,7 +723,6 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
false
);
//createCellCentres(cellCentres);
cellCentres = DelaunayMeshTools::allPoints(*this);
labelList cellToDelaunayVertex(removeUnusedCells(owner, neighbour));
@ -1327,24 +804,6 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
pMesh.addPatches(patches);
// Info<< "ADDPATCHES NOT IN PARALLEL" << endl;
// forAll(patches, p)
// {
// patches[p] = new polyPatch
// (
// patchNames[p],
// patchSizes[p],
// patchStarts[p],
// p,
// pMesh.boundaryMesh()
// );
// }
// pMesh.addPatches(patches, false);
// pMesh.overrideCellCentres(cellCentres);
return meshPtr;
}
@ -1361,7 +820,7 @@ void Foam::conformalVoronoiMesh::checkCellSizing()
indexDualVertices(ptsField, boundaryPts);
// Merge close dual vertices.
mergeIdenticalDualVertices(ptsField);
mergeIdenticalDualVertices(ptsField, boundaryPts);
autoPtr<polyMesh> meshPtr = createPolyMeshFromPoints(ptsField);
const polyMesh& pMesh = meshPtr();
@ -2004,23 +1463,10 @@ void Foam::conformalVoronoiMesh::indexDualVertices
boundaryPts[cit->cellIndex()] = surface;
}
}
else if
(
cit->baffleBoundaryDualVertex()
)
else if (cit->baffleBoundaryDualVertex())
{
boundaryPts[cit->cellIndex()] = surface;
}
else if
(
cit->vertex(0)->featureEdgePoint()
&& cit->vertex(1)->featureEdgePoint()
&& cit->vertex(2)->featureEdgePoint()
&& cit->vertex(3)->featureEdgePoint()
)
{
boundaryPts[cit->cellIndex()] = featureEdge;
}
else
{
boundaryPts[cit->cellIndex()] = internal;
@ -2040,7 +1486,8 @@ void Foam::conformalVoronoiMesh::indexDualVertices
void Foam::conformalVoronoiMesh::reindexDualVertices
(
const Map<label>& dualPtIndexMap
const Map<label>& dualPtIndexMap,
labelList& boundaryPts
)
{
for
@ -2053,6 +1500,12 @@ void Foam::conformalVoronoiMesh::reindexDualVertices
if (dualPtIndexMap.found(cit->cellIndex()))
{
cit->cellIndex() = dualPtIndexMap[cit->cellIndex()];
boundaryPts[cit->cellIndex()] =
max
(
boundaryPts[cit->cellIndex()],
boundaryPts[dualPtIndexMap[cit->cellIndex()]]
);
}
}
}
@ -2267,11 +1720,7 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
bool includeEmptyPatches
) const
{
const label defaultPatchIndex = createPatchInfo
(
patchNames,
patchDicts
);
const label defaultPatchIndex = createPatchInfo(patchNames, patchDicts);
const label nPatches = patchNames.size();
@ -2296,6 +1745,7 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
List<DynamicList<bool> > indirectPatchFace(nPatches, DynamicList<bool>(0));
faces.setSize(number_of_finite_edges());
owner.setSize(number_of_finite_edges());
neighbour.setSize(number_of_finite_edges());
@ -2765,7 +2215,13 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
// If the two vertices are a pair, then the patch face is
// a desired one.
if (!isPointPair(vA, vB))
if
(
vA->boundaryPoint() && vB->boundaryPoint()
&& !isProcBoundaryEdge(eit)
&& !ptPairs_.isPointPair(vA, vB)
&& !ftPtConformer_.featurePointPairs().isPointPair(vA, vB)
)
{
indirectPatchFace[patchIndex].append(true);
}
@ -2797,6 +2253,18 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
if (patchIndex != -1)
{
// if
// (
// vA->boundaryPoint() && vB->boundaryPoint()
// && !ptPairs_.isPointPair(vA, vB)
// )
// {
// indirectPatchFace[patchIndex].append(true);
// }
// else
// {
// indirectPatchFace[patchIndex].append(false);
// }
// patchFaces[patchIndex].append(newDualFace);
// patchOwners[patchIndex].append(own);
// indirectPatchFace[patchIndex].append(false);
@ -2813,8 +2281,6 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
// {
// patchPPSlaves[patchIndex].append(vA->index());
// }
// baffleFaces[dualFaceI] = patchIndex;
}
// else
{
@ -2989,7 +2455,6 @@ void Foam::conformalVoronoiMesh::sortProcPatches
faceList& faces = patchFaces[patchI];
labelList& owner = patchOwners[patchI];
DynamicList<label>& slaves = patchPointPairSlaves[patchI];
DynamicList<Pair<labelPair> >& sortingIndices
= patchSortingIndices[patchI];

View File

@ -62,11 +62,13 @@ void Foam::conformalVoronoiMesh::conformToSurface()
if (Pstream::parRun())
{
sync(decomposition_().procBounds());
sync(decomposition().procBounds());
}
}
else
{
ptPairs_.clear();
// Rebuild, insert and store new surface conformation
buildSurfaceConformation();
@ -74,7 +76,7 @@ void Foam::conformalVoronoiMesh::conformToSurface()
{
if (Pstream::parRun())
{
sync(decomposition_().procBounds());
sync(decomposition().procBounds());
}
}
@ -358,10 +360,13 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation()
synchroniseSurfaceTrees(surfaceToTreeShape, surfaceHits);
}
DynamicList<Vb> pts(2*surfaceHits.size() + 3*featureEdgeHits.size());
insertSurfacePointPairs
(
surfaceHits,
"surfaceConformationLocations_initial.obj"
"surfaceConformationLocations_initial.obj",
pts
);
// In parallel, synchronise the edge trees
@ -373,9 +378,21 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation()
insertEdgePointGroups
(
featureEdgeHits,
"edgeConformationLocations_initial.obj"
"edgeConformationLocations_initial.obj",
pts
);
pts.shrink();
Map<label> oldToNewIndices = insertPointPairs(pts, true, true);
// Re-index the point pairs
ptPairs_.reIndex(oldToNewIndices);
writePointPairs("pointPairs_initial.obj");
// Remove location from surface/edge tree
timeCheck("After initial conformation");
initialTotalHits = nSurfHits + nFeatEdHits;
@ -550,215 +567,6 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation()
}
}
// for
// (
// Delaunay::Finite_edges_iterator eit = finite_edges_begin();
// eit != finite_edges_end();
// ++eit
// )
// {
// Cell_handle c = eit->first;
// Vertex_handle vA = c->vertex(eit->second);
// Vertex_handle vB = c->vertex(eit->third);
//
// if
// (
// vA->referred()
// || vB->referred()
// )
// {
// continue;
// }
//
// if
// (
// (vA->internalPoint() && vA->referred())
// || (vB->internalPoint() && vB->referred())
// )
// {
// continue;
// }
//
// if
// (
// (vA->internalPoint() && vB->externalBoundaryPoint())
// || (vB->internalPoint() && vA->externalBoundaryPoint())
// || (vA->internalBoundaryPoint() && vB->internalBoundaryPoint())
// )
// {
// pointIndexHitAndFeatureDynList surfaceIntersections(0.5*AtoV);
// pointIndexHit surfHit;
// label hitSurface;
//
// geometryToConformTo_.findSurfaceNearest
// (
// (
// vA->internalPoint()
// ? topoint(vA->point())
// : topoint(vB->point())
// ),
// magSqr(topoint(vA->point()) - topoint(vB->point())),
// surfHit,
// hitSurface
// );
//
// if (surfHit.hit())
// {
// surfaceIntersections.append
// (
// pointIndexHitAndFeature(surfHit, hitSurface)
// );
//
// addSurfaceAndEdgeHits
// (
// (
// vA->internalPoint()
// ? topoint(vA->point())
// : topoint(vB->point())
// ),
// surfaceIntersections,
// surfacePtReplaceDistCoeffSqr,
// edgeSearchDistCoeffSqr,
// surfaceHits,
// featureEdgeHits,
// surfaceToTreeShape,
// edgeToTreeShape,
// surfacePtToEdgePtDist,
// false
// );
// }
// }
// }
for
(
Delaunay::Finite_cells_iterator cit = finite_cells_begin();
cit != finite_cells_end();
++cit
)
{
label nInternal = 0;
for (label vI = 0; vI < 4; vI++)
{
if (cit->vertex(vI)->internalPoint())
{
nInternal++;
}
}
if (nInternal == 1 && cit->hasBoundaryPoint())
//if (cit->boundaryDualVertex() && !cit->hasReferredPoint())
{
const Foam::point& pt = cit->dual();
const Foam::point cellCentre =
topoint
(
CGAL::centroid
(
CGAL::Tetrahedron_3<baseK>
(
cit->vertex(0)->point(),
cit->vertex(1)->point(),
cit->vertex(2)->point(),
cit->vertex(3)->point()
)
)
);
pointIndexHitAndFeatureDynList surfaceIntersections(0.5*AtoV);
pointIndexHit surfHit;
label hitSurface;
geometryToConformTo_.findSurfaceNearestIntersection
(
cellCentre,
pt,
surfHit,
hitSurface
);
if (surfHit.hit())
{
surfaceIntersections.append
(
pointIndexHitAndFeature(surfHit, hitSurface)
);
addSurfaceAndEdgeHits
(
pt,
surfaceIntersections,
surfacePtReplaceDistCoeffSqr,
edgeSearchDistCoeffSqr,
surfaceHits,
featureEdgeHits,
surfaceToTreeShape,
edgeToTreeShape,
surfacePtToEdgePtDist,
false
);
}
}
}
// for
// (
// Delaunay::Finite_cells_iterator cit = finite_cells_begin();
// cit != finite_cells_end();
// ++cit
// )
// {
// if (cit->boundaryDualVertex() && !cit->hasReferredPoint())
// {
// const Foam::point& pt = cit->dual();
//
// pointIndexHitAndFeatureDynList surfaceIntersections(0.5*AtoV);
// pointIndexHit surfHit;
// label hitSurface;
//
// geometryToConformTo_.findSurfaceNearest
// (
// pt,
// sqr(0.1*targetCellSize(pt)),
// surfHit,
// hitSurface
// );
//
// if (!surfHit.hit())
// {
// geometryToConformTo_.findSurfaceNearest
// (
// pt,
// GREAT,
// surfHit,
// hitSurface
// );
//
// if (surfHit.hit())
// {
// surfaceIntersections.append
// (
// pointIndexHitAndFeature(surfHit, hitSurface)
// );
//
// addSurfaceAndEdgeHits
// (
// pt,
// surfaceIntersections,
// surfacePtReplaceDistCoeffSqr,
// edgeSearchDistCoeffSqr,
// surfaceHits,
// featureEdgeHits,
// surfaceToTreeShape,
// edgeToTreeShape,
// false
// );
// }
// }
// }
// }
label nVerts = number_of_vertices();
label nSurfHits = surfaceHits.size();
label nFeatEdHits = featureEdgeHits.size();
@ -789,10 +597,16 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation()
synchroniseSurfaceTrees(surfaceToTreeShape, surfaceHits);
}
DynamicList<Vb> pts
(
2*surfaceHits.size() + 3*featureEdgeHits.size()
);
insertSurfacePointPairs
(
surfaceHits,
"surfaceConformationLocations_" + name(iterationNo) + ".obj"
"surfaceConformationLocations_" + name(iterationNo) + ".obj",
pts
);
// In parallel, synchronise the edge trees
@ -805,9 +619,19 @@ void Foam::conformalVoronoiMesh::buildSurfaceConformation()
insertEdgePointGroups
(
featureEdgeHits,
"edgeConformationLocations_" + name(iterationNo) + ".obj"
"edgeConformationLocations_" + name(iterationNo) + ".obj",
pts
);
pts.shrink();
Map<label> oldToNewIndices = insertPointPairs(pts, true, true);
// Reindex the point pairs
ptPairs_.reIndex(oldToNewIndices);
writePointPairs("pointPairs_" + name(iterationNo) + ".obj");
if (Pstream::parRun())
{
sync
@ -1155,8 +979,6 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
|| is_infinite(fit->first->neighbor(fit->second))
|| !fit->first->hasInternalPoint()
|| !fit->first->neighbor(fit->second)->hasInternalPoint()
// || fit->first->hasFarPoint()
// || fit->first->neighbor(fit->second)->hasFarPoint()
)
{
continue;
@ -1209,14 +1031,13 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
const scalar d = p.normalIntersect(r);
const Foam::point newPoint = vertex + d*n;
Foam::point newPoint = vertex + d*n;
pointIndexHitAndFeature info;
geometryToConformTo_.findSurfaceNearest
(
newPoint,
surfaceSearchDistanceSqr(newPoint),
4.0*magSqr(newPoint - vertex),
info.first(),
info.second()
);
@ -1359,7 +1180,10 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion
if
(
is_infinite(c1) || is_infinite(c2)
|| (!c1->hasInternalPoint() && !c2->hasInternalPoint())
|| (
!c1->internalOrBoundaryDualVertex()
|| !c2->internalOrBoundaryDualVertex()
)
|| !c1->real() || !c2->real()
)
{
@ -1369,19 +1193,24 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion
// Foam::point endPt = 0.5*(c1->dual() + c2->dual());
Foam::point endPt = c1->dual();
if
(
magSqr(vert - c1->dual())
< magSqr(vert - c2->dual())
)
if (magSqr(vert - c1->dual()) < magSqr(vert - c2->dual()))
{
endPt = c2->dual();
}
if
(
magSqr(vert - endPt)
> magSqr(geometryToConformTo().globalBounds().mag())
)
{
continue;
}
pointIndexHit surfHit;
label hitSurface;
geometryToConformTo_.findSurfaceAnyIntersection
geometryToConformTo_.findSurfaceNearestIntersection
(
vert,
endPt,
@ -1401,18 +1230,49 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceProtrusion
const vector& n = norm[0];
const scalar normalProtrusionDistance =
(endPt - surfHit.hitPoint()) & n;
const scalar normalProtrusionDistance
(
(endPt - surfHit.hitPoint()) & n
);
if (normalProtrusionDistance > maxProtrusionDistance)
{
surfHitLargest = surfHit;
hitSurfaceLargest = hitSurface;
const plane p(surfHit.hitPoint(), n);
const plane::ray r(endPt, -n);
const scalar d = p.normalIntersect(r);
Foam::point newPoint = endPt - d*n;
pointIndexHitAndFeature info;
geometryToConformTo_.findSurfaceNearest
(
newPoint,
4.0*magSqr(newPoint - endPt),
info.first(),
info.second()
);
if (info.first().hit())
{
if
(
surfaceLocationConformsToInside
(
pointIndexHitAndFeature(info.first(), info.second())
)
)
{
surfHitLargest = info.first();
hitSurfaceLargest = info.second();
maxProtrusionDistance = normalProtrusionDistance;
}
}
}
}
}
// Relying on short-circuit evaluation to not call for hitPoint when this
// is a miss
@ -1465,7 +1325,10 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion
if
(
is_infinite(c1) || is_infinite(c2)
|| (!c1->hasInternalPoint() && !c2->hasInternalPoint())
|| (
!c1->internalOrBoundaryDualVertex()
|| !c2->internalOrBoundaryDualVertex()
)
|| !c1->real() || !c2->real()
)
{
@ -1475,19 +1338,24 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion
// Foam::point endPt = 0.5*(c1->dual() + c2->dual());
Foam::point endPt = c1->dual();
if
(
magSqr(vert - c1->dual())
< magSqr(vert - c2->dual())
)
if (magSqr(vert - c1->dual()) < magSqr(vert - c2->dual()))
{
endPt = c2->dual();
}
if
(
magSqr(vert - endPt)
> magSqr(geometryToConformTo().globalBounds().mag())
)
{
continue;
}
pointIndexHit surfHit;
label hitSurface;
geometryToConformTo_.findSurfaceAnyIntersection
geometryToConformTo_.findSurfaceNearestIntersection
(
vert,
endPt,
@ -1507,19 +1375,46 @@ void Foam::conformalVoronoiMesh::dualCellLargestSurfaceIncursion
const vector& n = norm[0];
scalar normalIncursionDistance = (endPt - surfHit.hitPoint()) & n;
scalar normalIncursionDistance
(
(endPt - surfHit.hitPoint()) & n
);
if (normalIncursionDistance < minIncursionDistance)
{
surfHitLargest = surfHit;
hitSurfaceLargest = hitSurface;
const plane p(surfHit.hitPoint(), n);
const plane::ray r(endPt, n);
const scalar d = p.normalIntersect(r);
Foam::point newPoint = endPt + d*n;
pointIndexHitAndFeature info;
geometryToConformTo_.findSurfaceNearest
(
newPoint,
4.0*magSqr(newPoint - endPt),
info.first(),
info.second()
);
if (info.first().hit())
{
if
(
surfaceLocationConformsToInside
(
pointIndexHitAndFeature(info.first(), info.second())
)
)
{
surfHitLargest = info.first();
hitSurfaceLargest = info.second();
minIncursionDistance = normalIncursionDistance;
// Info<< nl << "# Incursion: " << endl;
// meshTools::writeOBJ(Info, vert);
// meshTools::writeOBJ(Info, edgeMid);
// Info<< "l Na Nb" << endl;
}
}
}
}
}
@ -2219,6 +2114,9 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
// feature edge, give control to edge control points
// instead, this will prevent "pits" forming.
// Allow if different surfaces
keepSurfacePoint = false;
}
@ -2298,11 +2196,13 @@ void Foam::conformalVoronoiMesh::addSurfaceAndEdgeHits
surfaceHits.append(surfHitI);
appendToSurfacePtTree(surfPt);
surfaceToTreeShape.append(existingSurfacePtLocations_.size() - 1);
// addedPoints.write(surfPt);
}
else
{
// removedPoints.write(surfPt);
}
// else
// {
// surfaceToTreeShape.remove();
// }
}
}
@ -2338,7 +2238,9 @@ void Foam::conformalVoronoiMesh::storeSurfaceConformation()
Vb
(
vit->point(),
vit->type()
vit->index(),
vit->type(),
Pstream::myProcNo()
)
);
}
@ -2362,24 +2264,40 @@ void Foam::conformalVoronoiMesh::reinsertSurfaceConformation()
{
Info<< nl << "Reinserting stored surface conformation" << endl;
const label preReinsertionSize(number_of_vertices());
Map<label> oldToNewIndices =
insertPointPairs(surfaceConformationVertices_, true, true);
// It is assumed that the stored surface conformation is on the correct
// processor and does not need distributed
rangeInsertWithInfo
ptPairs_.reIndex(oldToNewIndices);
PackedBoolList selectedElems(surfaceConformationVertices_.size(), true);
forAll(surfaceConformationVertices_, vI)
{
Vb& v = surfaceConformationVertices_[vI];
label& vIndex = v.index();
Map<label>::const_iterator iter = oldToNewIndices.find(vIndex);
if (iter != oldToNewIndices.end())
{
const label newIndex = iter();
if (newIndex != -1)
{
vIndex = newIndex;
}
else
{
selectedElems[vI] = false;
}
}
}
inplaceSubset<PackedBoolList, List<Vb> >
(
surfaceConformationVertices_.begin(),
surfaceConformationVertices_.end(),
true
selectedElems,
surfaceConformationVertices_
);
const label nInserted = label(number_of_vertices()) - preReinsertionSize;
const label nFailed = surfaceConformationVertices_.size() - nInserted;
Info<< " " << returnReduce(nInserted, sumOp<label>())
<< " points reinserted, failed to insert "
<< returnReduce(nFailed, sumOp<label>())
<< endl;
}

View File

@ -29,6 +29,7 @@ License
#include "tetrahedron.H"
#include "const_circulator.H"
#include "DelaunayMeshTools.H"
#include "OBJstream.H"
using namespace Foam::vectorTools;
@ -225,54 +226,53 @@ void Foam::conformalVoronoiMesh::createEdgePointGroupByCirculating
vector masterPtVec(normalDir + nextNormalDir);
masterPtVec /= mag(masterPtVec) + SMALL;
if (((normalDir ^ nextNormalDir) & edDir) < SMALL)
if
(
((normalDir ^ nextNormalDir) & edDir) < SMALL
|| mag(masterPtVec) < SMALL
)
{
// Info<< " IGNORE REGION" << endl;
addedMasterPreviously = false;
if (circ.size() == 2 && mag((normal & nextNormal) - 1) < SMALL)
if
(
circ.size() == 2
&& mag((normal & nextNormal) - 1) < SMALL
)
{
// Add an extra point
const vector n = 0.5*(normal + nextNormal);
vector s = ppDist*(edDir ^ n);
const vector s = ppDist*(edDir ^ n);
createPointPair(ppDist, edgePt + s, n, pts);
createPointPair(ppDist, edgePt - s, n, pts);
break;
}
continue;
}
if (mag(masterPtVec) < SMALL)
if (volType == extendedFeatureEdgeMesh::BOTH)
{
if (circ.size() == 2)
{
// Add an extra point
// Average normal to remove any bias to one side, although as
// it is a flat edge, the normals should be essentially the same
const vector n = 0.5*(normal + nextNormal);
// Direction along the surface to the control point, sense of
// direction not important, as +s and -s can be used because it
// is a flat edge
vector s = ppDist*(edDir ^ n);
createPointPair(ppDist, edgePt + s, n, pts);
createPointPair(ppDist, edgePt - s, n, pts);
break;
createBafflePointPair(ppDist, edgePt + s, n, true, pts);
createBafflePointPair(ppDist, edgePt - s, n, true, pts);
}
else
{
// Info<< " IGNORE REGION" << endl;
addedMasterPreviously = false;
continue;
WarningIn
(
"Foam::conformalVoronoiMesh::"
"createEdgePointGroupByCirculating"
"("
" const extendedFeatureEdgeMesh&,"
" const pointIndexHit&,"
" DynamicList<Vb>&"
")"
) << "Failed to insert flat/open edge as volType is "
<< extendedFeatureEdgeMesh::sideVolumeTypeNames_
[
volType
]
<< endl;
}
break;
}
continue;
}
const Foam::point masterPt = edgePt + ppDist*masterPtVec;
@ -490,11 +490,19 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
const vectorField& feNormals = feMesh.normals();
const labelList& edNormalIs = feMesh.edgeNormals()[edHit.index()];
const List<extendedFeatureEdgeMesh::sideVolumeType>& normalVolumeTypes =
feMesh.normalVolumeTypes();
// As this is an external edge, there are two normals by definition
const vector& nA = feNormals[edNormalIs[0]];
const vector& nB = feNormals[edNormalIs[1]];
const extendedFeatureEdgeMesh::sideVolumeType& volTypeA =
normalVolumeTypes[edNormalIs[0]];
const extendedFeatureEdgeMesh::sideVolumeType& volTypeB =
normalVolumeTypes[edNormalIs[1]];
if (areParallel(nA, nB))
{
// The normals are nearly parallel, so this is too sharp a feature to
@ -524,13 +532,6 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
// Convex. So refPt will be inside domain and hence a master point
Foam::point refPt = edgePt - ppDist*refVec;
// Result when the points are eventually inserted.
// Add number_of_vertices() at insertion of first vertex to all numbers:
// pt index type
// refPt 0 1
// reflectedA 1 0
// reflectedB 2 0
// Insert the master point pairing the the first slave
if (!geometryToConformTo_.inside(refPt))
@ -559,7 +560,11 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
(
reflectedA,
vertexCount() + pts.size(),
Vb::vtExternalFeatureEdge,
(
volTypeA == extendedFeatureEdgeMesh::BOTH
? Vb::vtInternalFeatureEdge
: Vb::vtExternalFeatureEdge
),
Pstream::myProcNo()
)
);
@ -571,10 +576,26 @@ void Foam::conformalVoronoiMesh::createExternalEdgePointGroup
(
reflectedB,
vertexCount() + pts.size(),
Vb::vtExternalFeatureEdge,
(
volTypeB == extendedFeatureEdgeMesh::BOTH
? Vb::vtInternalFeatureEdge
: Vb::vtExternalFeatureEdge
),
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(),
pts[pts.size() - 1].index()
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(),
pts[pts.size() - 2].index()
);
}
@ -591,11 +612,19 @@ void Foam::conformalVoronoiMesh::createInternalEdgePointGroup
const vectorField& feNormals = feMesh.normals();
const labelList& edNormalIs = feMesh.edgeNormals()[edHit.index()];
const List<extendedFeatureEdgeMesh::sideVolumeType>& normalVolumeTypes =
feMesh.normalVolumeTypes();
// As this is an external edge, there are two normals by definition
const vector& nA = feNormals[edNormalIs[0]];
const vector& nB = feNormals[edNormalIs[1]];
const extendedFeatureEdgeMesh::sideVolumeType& volTypeA =
normalVolumeTypes[edNormalIs[0]];
// const extendedFeatureEdgeMesh::sideVolumeType& volTypeB =
// normalVolumeTypes[edNormalIs[1]];
if (areParallel(nA, nB))
{
// The normals are nearly parallel, so this is too sharp a feature to
@ -705,14 +734,30 @@ void Foam::conformalVoronoiMesh::createInternalEdgePointGroup
(
reflMasterPt,
vertexCount() + pts.size(),
Vb::vtExternalFeatureEdge,
(
volTypeA == extendedFeatureEdgeMesh::BOTH
? Vb::vtInternalFeatureEdge
: Vb::vtExternalFeatureEdge
),
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(),
pts[pts.size() - 1].index()
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(),
pts[pts.size() - 1].index()
);
if (nAddPoints == 1)
{
// One additinal point is the reflection of the slave point,
// One additional point is the reflection of the slave point,
// i.e. the original reference point
pts.append
(
@ -767,6 +812,8 @@ void Foam::conformalVoronoiMesh::createFlatEdgePointGroup
const vectorField& feNormals = feMesh.normals();
const labelList& edNormalIs = feMesh.edgeNormals()[edHit.index()];
const List<extendedFeatureEdgeMesh::sideVolumeType>& normalVolumeTypes =
feMesh.normalVolumeTypes();
// As this is a flat edge, there are two normals by definition
const vector& nA = feNormals[edNormalIs[0]];
@ -781,8 +828,21 @@ void Foam::conformalVoronoiMesh::createFlatEdgePointGroup
// is a flat edge
vector s = ppDist*(feMesh.edgeDirections()[edHit.index()] ^ n);
createPointPair(ppDist, edgePt + s, n, pts);
createPointPair(ppDist, edgePt - s, n, pts);
if (normalVolumeTypes[edNormalIs[0]] == extendedFeatureEdgeMesh::OUTSIDE)
{
createPointPair(ppDist, edgePt + s, -n, true, pts);
createPointPair(ppDist, edgePt - s, -n, true, pts);
}
else if (normalVolumeTypes[edNormalIs[0]] == extendedFeatureEdgeMesh::BOTH)
{
createBafflePointPair(ppDist, edgePt + s, n, true, pts);
createBafflePointPair(ppDist, edgePt - s, n, true, pts);
}
else
{
createPointPair(ppDist, edgePt + s, n, true, pts);
createPointPair(ppDist, edgePt - s, n, true, pts);
}
}
@ -814,16 +874,23 @@ void Foam::conformalVoronoiMesh::createOpenEdgePointGroup
plane facePlane(edgePt, n);
Foam::point pt1 = edgePt + s + ppDist*n;
Foam::point pt2 = edgePt - s + ppDist*n;
const label initialPtsSize = pts.size();
Foam::point pt3 = facePlane.mirror(pt1);
Foam::point pt4 = facePlane.mirror(pt2);
if
(
!geometryToConformTo_.inside(edgePt)
)
{
return;
}
pts.append(Vb(pt1, Vb::vtInternalSurface));
pts.append(Vb(pt2, Vb::vtInternalSurface));
pts.append(Vb(pt3, Vb::vtInternalSurface));
pts.append(Vb(pt4, Vb::vtInternalSurface));
createBafflePointPair(ppDist, edgePt - s, n, true, pts);
createBafflePointPair(ppDist, edgePt + s, n, false, pts);
for (label ptI = initialPtsSize; ptI < pts.size(); ++ptI)
{
pts[ptI].type() = Vb::vtInternalFeatureEdge;
}
}
else
{
@ -846,26 +913,245 @@ void Foam::conformalVoronoiMesh::createMultipleEdgePointGroup
const scalar ppDist = pointPairDistance(edgePt);
const vector edDir = feMesh.edgeDirections()[edHit.index()];
const vectorField& feNormals = feMesh.normals();
const labelList& edNormalIs = feMesh.edgeNormals()[edHit.index()];
const labelList& normalDirs = feMesh.normalDirections()[edHit.index()];
Info<< edNormalIs.size() << endl;
const List<extendedFeatureEdgeMesh::sideVolumeType>& normalVolumeTypes =
feMesh.normalVolumeTypes();
// As this is a flat edge, there are two normals by definition
const vector& nA = feNormals[edNormalIs[0]];
const vector& nB = feNormals[edNormalIs[1]];
labelList nNormalTypes(4, 0);
// Average normal to remove any bias to one side, although as this
// is a flat edge, the normals should be essentially the same
const vector n = 0.5*(nA + nB);
forAll(edNormalIs, edgeNormalI)
{
const extendedFeatureEdgeMesh::sideVolumeType sType =
normalVolumeTypes[edNormalIs[edgeNormalI]];
// Direction along the surface to the control point, sense of edge
// direction not important, as +s and -s can be used because this
// is a flat edge
vector s = ppDist*(feMesh.edgeDirections()[edHit.index()] ^ n);
nNormalTypes[sType]++;
}
createPointPair(ppDist, edgePt + s, n, pts);
createPointPair(ppDist, edgePt - s, n, pts);
if (nNormalTypes[extendedFeatureEdgeMesh::BOTH] == 4)
{
label masterEdgeNormalIndex = -1;
forAll(edNormalIs, edgeNormalI)
{
const extendedFeatureEdgeMesh::sideVolumeType sType =
normalVolumeTypes[edNormalIs[edgeNormalI]];
if (sType == extendedFeatureEdgeMesh::BOTH)
{
masterEdgeNormalIndex = edgeNormalI;
break;
}
}
const vector& n = feNormals[edNormalIs[masterEdgeNormalIndex]];
label nDir = normalDirs[masterEdgeNormalIndex];
vector normalDir =
(feNormals[edNormalIs[masterEdgeNormalIndex]] ^ edDir);
normalDir *= nDir/mag(normalDir);
Foam::point pt1 = edgePt + ppDist*normalDir + ppDist*n;
Foam::point pt2 = edgePt + ppDist*normalDir - ppDist*n;
plane plane3(edgePt, normalDir);
Foam::point pt3 = plane3.mirror(pt1);
Foam::point pt4 = plane3.mirror(pt2);
pts.append
(
Vb
(
pt1,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
pts.append
(
Vb
(
pt2,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
pts.append
(
Vb
(
pt3,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
pts.append
(
Vb
(
pt4,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
}
else if
(
nNormalTypes[extendedFeatureEdgeMesh::BOTH] == 1
&& nNormalTypes[extendedFeatureEdgeMesh::INSIDE] == 2
)
{
label masterEdgeNormalIndex = -1;
forAll(edNormalIs, edgeNormalI)
{
const extendedFeatureEdgeMesh::sideVolumeType sType =
normalVolumeTypes[edNormalIs[edgeNormalI]];
if (sType == extendedFeatureEdgeMesh::BOTH)
{
masterEdgeNormalIndex = edgeNormalI;
break;
}
}
const vector& n = feNormals[edNormalIs[masterEdgeNormalIndex]];
label nDir = normalDirs[masterEdgeNormalIndex];
vector normalDir =
(feNormals[edNormalIs[masterEdgeNormalIndex]] ^ edDir);
normalDir *= nDir/mag(normalDir);
const label nextNormalI =
(masterEdgeNormalIndex + 1) % edNormalIs.size();
if ((normalDir & feNormals[edNormalIs[nextNormalI]]) > 0)
{
normalDir *= -1;
}
Foam::point pt1 = edgePt + ppDist*normalDir + ppDist*n;
Foam::point pt2 = edgePt + ppDist*normalDir - ppDist*n;
plane plane3(edgePt, normalDir);
Foam::point pt3 = plane3.mirror(pt1);
Foam::point pt4 = plane3.mirror(pt2);
pts.append
(
Vb
(
pt1,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
pts.append
(
Vb
(
pt2,
vertexCount() + pts.size(),
Vb::vtInternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
pts.append
(
Vb
(
pt3,
vertexCount() + pts.size(),
Vb::vtExternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
pts.append
(
Vb
(
pt4,
vertexCount() + pts.size(),
Vb::vtExternalSurface,
Pstream::myProcNo()
)
);
ptPairs_.addPointPair
(
pts[pts.size() - 3].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
}
// // As this is a flat edge, there are two normals by definition
// const vector& nA = feNormals[edNormalIs[0]];
// const vector& nB = feNormals[edNormalIs[1]];
//
// // Average normal to remove any bias to one side, although as this
// // is a flat edge, the normals should be essentially the same
// const vector n = 0.5*(nA + nB);
//
// // Direction along the surface to the control point, sense of edge
// // direction not important, as +s and -s can be used because this
// // is a flat edge
// vector s = ppDist*(feMesh.edgeDirections()[edHit.index()] ^ n);
//
// createBafflePointPair(ppDist, edgePt + s, n, true, pts);
// createBafflePointPair(ppDist, edgePt - s, n, true, pts);
}
@ -874,6 +1160,23 @@ void Foam::conformalVoronoiMesh::insertFeaturePoints(bool distribute)
Info<< nl
<< "Inserting feature points" << endl;
// Map<label> oldToNewIndices = insertPoints(featureVertices_, distribute);
// featurePtPairs_.reIndex(oldToNewIndices);
// forAll(featureVertices_, vI)
// {
// Map<label>::const_iterator iter =
// oldToNewIndices.find(featureVertices_[vI].index());
// if (iter != oldToNewIndices.end())
// {
// featureVertices_[vI].index() = iter();
// }
// }
const label preFeaturePointSize(number_of_vertices());
if (Pstream::parRun() && distribute)
@ -884,7 +1187,7 @@ void Foam::conformalVoronoiMesh::insertFeaturePoints(bool distribute)
const List<Vb>& ftPtVertices = ftPtConformer_.featurePointVertices();
// Insert the created points directly as already distributed.
this->DelaunayMesh<Delaunay>::insertPoints(ftPtVertices);
this->DelaunayMesh<Delaunay>::insertPoints(ftPtVertices, true);
label nFeatureVertices = number_of_vertices() - preFeaturePointSize;
reduce(nFeatureVertices, sumOp<label>());

View File

@ -225,6 +225,7 @@ inline void Foam::conformalVoronoiMesh::createPointPair
const scalar ppDist,
const Foam::point& surfPt,
const vector& n,
const bool ptPair,
DynamicList<Vb>& pts
) const
{
@ -260,14 +261,14 @@ inline void Foam::conformalVoronoiMesh::createPointPair
)
);
// if (ptPair)
// {
// ptPairs_.addPointPair
// (
// pts[pts.size() - 2].index(),
// pts[pts.size() - 1].index() // external 0 -> slave
// );
// }
if (ptPair)
{
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(),
pts[pts.size() - 1].index() // external 0 -> slave
);
}
}
// else
// {
@ -305,6 +306,7 @@ inline void Foam::conformalVoronoiMesh::createBafflePointPair
const scalar ppDist,
const Foam::point& surfPt,
const vector& n,
const bool ptPair,
DynamicList<Vb>& pts
) const
{
@ -315,8 +317,8 @@ inline void Foam::conformalVoronoiMesh::createBafflePointPair
Vb
(
surfPt - ppDistn,
vertexCount() + 1 + pts.size(),
Vb::vtInternalSurface,
vertexCount() + pts.size(),
Vb::vtInternalSurfaceBaffle,
Pstream::myProcNo()
)
);
@ -326,11 +328,20 @@ inline void Foam::conformalVoronoiMesh::createBafflePointPair
Vb
(
surfPt + ppDistn,
vertexCount() + 1 + pts.size(),
Vb::vtInternalSurface,
vertexCount() + pts.size(),
Vb::vtExternalSurfaceBaffle,
Pstream::myProcNo()
)
);
if (ptPair)
{
ptPairs_.addPointPair
(
pts[pts.size() - 2].index(), // external 0 -> slave
pts[pts.size() - 1].index()
);
}
}
@ -341,8 +352,8 @@ inline bool Foam::conformalVoronoiMesh::internalPointIsInside
{
if
(
!geometryToConformTo_.inside(pt)
|| !geometryToConformTo_.globalBounds().contains(pt)
!geometryToConformTo_.globalBounds().contains(pt)
|| !geometryToConformTo_.inside(pt)
)
{
return false;
@ -352,76 +363,6 @@ inline bool Foam::conformalVoronoiMesh::internalPointIsInside
}
inline bool Foam::conformalVoronoiMesh::isPointPair
(
const Vertex_handle& vA,
const Vertex_handle& vB
) const
{
// Want to do this topologically, but problem if vertices are redistributed
// so that one of the point pair is one processor and the other is on
// another.
const Foam::point& ptA = topoint(vA->point());
const Foam::point& ptB = topoint(vB->point());
if
(
(
vA->type() == Vb::vtInternalSurface
&& vB->type() == Vb::vtExternalSurface
)
||
(
vB->type() == Vb::vtInternalSurface
&& vA->type() == Vb::vtExternalSurface
)
||
(
vA->type() == Vb::vtInternalFeatureEdge
&& vB->type() == Vb::vtExternalFeatureEdge
)
||
(
vB->type() == Vb::vtInternalFeatureEdge
&& vA->type() == Vb::vtExternalFeatureEdge
)
||
(
vA->type() == Vb::vtInternalSurface
&& vB->type() == Vb::vtExternalFeatureEdge
)
||
(
vB->type() == Vb::vtInternalSurface
&& vA->type() == Vb::vtExternalFeatureEdge
)
||
(
vA->type() == Vb::vtExternalSurface
&& vB->type() == Vb::vtInternalFeatureEdge
)
||
(
vB->type() == Vb::vtExternalSurface
&& vA->type() == Vb::vtInternalFeatureEdge
)
)
{
const scalar distSqr = magSqr(ptA - ptB);
const scalar ppDistSqr = sqr(2*pointPairDistance(0.5*(ptA + ptB)));
if (distSqr > 1.001*ppDistSqr)
{
return false;
}
}
return true;
}
inline bool Foam::conformalVoronoiMesh::isBoundaryDualFace
(
const Delaunay::Finite_edges_iterator& eit

View File

@ -36,6 +36,8 @@ License
#include "indexedVertexOps.H"
#include "DelaunayMeshTools.H"
#include "syncTools.H"
#include "faceSet.H"
#include "OBJstream.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -114,7 +116,6 @@ void Foam::conformalVoronoiMesh::writeMesh(const fileName& instance)
wordList patchNames;
PtrList<dictionary> patchDicts;
pointField cellCentres;
PackedBoolList boundaryFacesToRemove;
calcDualMesh
@ -789,7 +790,7 @@ void Foam::conformalVoronoiMesh::writeMesh
const wordList& patchNames,
const PtrList<dictionary>& patchDicts,
const pointField& cellCentres,
const PackedBoolList& boundaryFacesToRemove
PackedBoolList& boundaryFacesToRemove
) const
{
if (foamyHexMeshControls().objOutput())
@ -912,18 +913,64 @@ void Foam::conformalVoronoiMesh::writeMesh
// Add indirectPatchFaces to a face zone
Info<< indent << "Add pointZones" << endl;
{
label sz = mesh.pointZones().size();
DynamicList<label> bPts(boundaryPts.size());
forAll(dualMeshPointTypeNames_, typeI)
{
forAll(boundaryPts, ptI)
{
const label& bPtType = boundaryPts[ptI];
if (bPtType == typeI)
{
bPts.append(ptI);
}
}
// syncTools::syncPointList(mesh, bPts, maxEqOp<label>(), -1);
Info<< incrIndent << indent
<< "Adding " << bPts.size()
<< " points of type " << dualMeshPointTypeNames_.words()[typeI]
<< decrIndent << endl;
mesh.pointZones().append
(
new pointZone
(
dualMeshPointTypeNames_.words()[typeI],
bPts,
sz + typeI,
mesh.pointZones()
)
);
bPts.clear();
}
}
// Add indirectPatchFaces to a face zone
Info<< indent << "Adding indirect patch faces set" << endl;
syncTools::syncFaceList
(
mesh,
boundaryFacesToRemove,
orOp<bool>()
);
labelList addr(boundaryFacesToRemove.count());
label count = 0;
forAll(boundaryFacesToRemove, faceI)
{
if
(
boundaryFacesToRemove[faceI]
&& mesh.faceZones().whichZone(faceI) == -1
)
if (boundaryFacesToRemove[faceI])
{
addr[count++] = faceI;
}
@ -931,22 +978,18 @@ void Foam::conformalVoronoiMesh::writeMesh
addr.setSize(count);
label sz = mesh.faceZones().size();
boolList flip(addr.size(), false);
mesh.faceZones().setSize(sz + 1);
mesh.faceZones().set
(
sz,
new faceZone
faceSet indirectPatchFaces
(
mesh,
"indirectPatchFaces",
addr,
flip,
sz,
mesh.faceZones()
)
IOobject::AUTO_WRITE
);
}
indirectPatchFaces.sync(mesh);
Info<< decrIndent;
timeCheck("Before fvMesh filtering");
@ -966,9 +1009,11 @@ void Foam::conformalVoronoiMesh::writeMesh
{
const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
polyTopoChange meshMod(newMesh);
polyTopoChange meshMod(newMesh());
meshMod.changeMesh(mesh, false);
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
}
@ -1001,9 +1046,11 @@ void Foam::conformalVoronoiMesh::writeMesh
{
const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
polyTopoChange meshMod(newMesh);
polyTopoChange meshMod(newMesh());
meshMod.changeMesh(mesh, false);
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
}
@ -1068,7 +1115,7 @@ void Foam::conformalVoronoiMesh::writeMesh
// writeCellCentres(mesh);
// findRemainingProtrusionSet(mesh);
findRemainingProtrusionSet(mesh);
}
@ -1375,4 +1422,33 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::findRemainingProtrusionSet
}
void Foam::conformalVoronoiMesh::writePointPairs
(
const fileName& fName
) const
{
OBJstream os(fName);
for
(
Delaunay::Finite_edges_iterator eit = finite_edges_begin();
eit != finite_edges_end();
++eit
)
{
Cell_handle c = eit->first;
Vertex_handle vA = c->vertex(eit->second);
Vertex_handle vB = c->vertex(eit->third);
if (ptPairs_.isPointPair(vA, vB))
{
os.write
(
linePointRef(topoint(vA->point()), topoint(vB->point()))
);
}
}
}
// ************************************************************************* //

View File

@ -146,7 +146,7 @@ void Foam::featurePointConformer::addMasterAndSlavePoints
)
);
// const label masterIndex = pts[pts.size() - 1].index();
const label masterIndex = pts.last().index();
//meshTools::writeOBJ(strMasters, masterPt);
@ -180,6 +180,11 @@ void Foam::featurePointConformer::addMasterAndSlavePoints
)
);
ftPtPairs_.addPointPair
(
masterIndex,
pts.last().index()
);
//meshTools::writeOBJ(strSlaves, slavePt);
}
@ -525,7 +530,8 @@ Foam::featurePointConformer::featurePointConformer
foamyHexMesh_(foamyHexMesh),
foamyHexMeshControls_(foamyHexMesh.foamyHexMeshControls()),
geometryToConformTo_(foamyHexMesh.geometryToConformTo()),
featurePointVertices_()
featurePointVertices_(),
ftPtPairs_(foamyHexMesh)
{
Info<< nl
<< "Conforming to feature points" << endl;
@ -598,6 +604,8 @@ void Foam::featurePointConformer::distribute
{
featurePointVertices_[vI].procIndex() = Pstream::myProcNo();
}
// Also update the feature point pairs
}

View File

@ -44,6 +44,7 @@ SourceFiles
#include "DynamicList.H"
#include "List.H"
#include "extendedFeatureEdgeMesh.H"
#include "pointPairs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -83,6 +84,9 @@ class featurePointConformer
// triangulation clear.
List<Vb> featurePointVertices_;
//-
mutable pointPairs<Delaunay> ftPtPairs_;
// Private Member Functions
@ -163,6 +167,9 @@ public:
// triangulation.
inline const List<Vb>& featurePointVertices() const;
//- Return the feature point pair table
inline const pointPairs<Delaunay>& featurePointPairs() const;
// Edit

View File

@ -28,5 +28,11 @@ const Foam::List<Vb>& Foam::featurePointConformer::featurePointVertices() const
return featurePointVertices_;
}
const Foam::pointPairs<Delaunay>&
Foam::featurePointConformer::featurePointPairs() const
{
return ftPtPairs_;
}
// ************************************************************************* //

View File

@ -168,9 +168,17 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtA, Vb::vtInternalFeaturePoint)
Vb
(
internalPtA,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
const label internalPtAIndex(pts.last().index());
const Foam::point internalPtB =
concaveEdgeExternalPt
- 2.0*planeB.distance(concaveEdgeExternalPt)
@ -178,9 +186,17 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtB, Vb::vtInternalFeaturePoint)
Vb
(
internalPtB,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
const label internalPtBIndex(pts.last().index());
// Add the external points
Foam::point externalPtD;
@ -288,7 +304,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtD, Vb::vtExternalFeaturePoint)
Vb
(
externalPtD,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtAIndex,
pts.last().index()
);
}
}
@ -319,7 +347,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtE, Vb::vtExternalFeaturePoint)
Vb
(
externalPtE,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtBIndex,
pts.last().index()
);
}
}
@ -328,9 +368,29 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(concaveEdgeExternalPt, Vb::vtExternalFeaturePoint)
Vb
(
concaveEdgeExternalPt,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtBIndex,
pts.last().index()
);
ftPtPairs_.addPointPair
(
internalPtAIndex,
pts.last().index()
);
const label concaveEdgeExternalPtIndex(pts.last().index());
const scalar totalAngle = radToDeg
(
constant::mathematical::pi
@ -377,7 +437,21 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtF, Vb::vtInternalFeaturePoint)
Vb
(
internalPtF,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
const label internalPtFIndex(pts.last().index());
ftPtPairs_.addPointPair
(
concaveEdgeExternalPtIndex,
pts.last().index()
);
const Foam::point externalPtG =
@ -386,7 +460,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtG, Vb::vtExternalFeaturePoint)
Vb
(
externalPtG,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtFIndex,
pts.last().index()
);
}
@ -520,9 +606,17 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtA, Vb::vtExternalFeaturePoint)
Vb
(
internalPtA,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
const label internalPtAIndex(pts.last().index());
const Foam::point internalPtB =
convexEdgeExternalPt
+ 2.0*planeB.distance(convexEdgeExternalPt)
@ -530,9 +624,17 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtB, Vb::vtExternalFeaturePoint)
Vb
(
internalPtB,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
const label internalPtBIndex(pts.last().index());
// Add the internal points
Foam::point externalPtD;
@ -643,7 +745,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtD, Vb::vtInternalFeaturePoint)
Vb
(
externalPtD,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtAIndex,
pts.last().index()
);
}
}
@ -674,7 +788,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtE, Vb::vtInternalFeaturePoint)
Vb
(
externalPtE,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtBIndex,
pts.last().index()
);
}
}
@ -683,7 +809,25 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(convexEdgeExternalPt, Vb::vtInternalFeaturePoint)
Vb
(
convexEdgeExternalPt,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
internalPtBIndex,
pts.last().index()
);
ftPtPairs_.addPointPair
(
internalPtAIndex,
pts.last().index()
);
const scalar totalAngle = radToDeg
@ -732,7 +876,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(internalPtF, Vb::vtExternalFeaturePoint)
Vb
(
internalPtF,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtExternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
pts[pts.size() - 2].index(),
pts.last().index()
);
const Foam::point externalPtG =
@ -741,7 +897,19 @@ bool Foam::featurePointConformer::createSpecialisedFeaturePoint
pts.append
(
Vb(externalPtG, Vb::vtInternalFeaturePoint)
Vb
(
externalPtG,
foamyHexMesh_.vertexCount() + pts.size(),
Vb::vtInternalFeaturePoint,
Pstream::myProcNo()
)
);
ftPtPairs_.addPointPair
(
pts[pts.size() - 2].index(),
pts.last().index()
);
}

View File

@ -193,6 +193,8 @@ public:
//- Does the Dual vertex form part of a processor patch
inline bool parallelDualVertex() const;
inline Foam::label vertexLowestProc() const;
//- Using the globalIndex object, return a list of four (sorted) global
// Delaunay vertex indices that uniquely identify this tet in parallel
inline Foam::tetCell vertexGlobalIndices

View File

@ -291,6 +291,23 @@ inline bool CGAL::indexedCell<Gt, Cb>::parallelDualVertex() const
}
template<class Gt, class Cb>
inline Foam::label CGAL::indexedCell<Gt, Cb>::vertexLowestProc() const
{
Foam::label lowestProc = -1;
for (int i = 0; i < 4; ++i)
{
if (this->vertex(i)->referred())
{
lowestProc = min(lowestProc, this->vertex(i)->procIndex());
}
}
return lowestProc;
}
template<class Gt, class Cb>
inline Foam::tetCell CGAL::indexedCell<Gt, Cb>::vertexGlobalIndices
(

View File

@ -83,6 +83,13 @@ void Foam::conformationSurfaces::hasBoundedVolume
const pointField& surfPts = triSurf.points();
Info<< " Checking " << surface.name() << endl;
label nBaffles = 0;
Info<< " Index = " << surfaces_[s] << endl;
Info<< " Offset = " << regionOffset_[s] << endl;
forAll(triSurf, sI)
{
const label patchID =
@ -98,7 +105,13 @@ void Foam::conformationSurfaces::hasBoundedVolume
{
sum += triSurf[sI].normal(surfPts);
}
else
{
nBaffles++;
}
}
Info<< " has " << nBaffles << " baffles out of "
<< triSurf.size() << " triangles" << endl;
totalTriangles += triSurf.size();
}
@ -153,8 +166,9 @@ void Foam::conformationSurfaces::readFeatures
{
const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
Info<< " features: " << surface.name() << " of type "
<< surface.type() << endl;
Info<< " features: " << surface.name()
<< " of type " << surface.type()
<< ", id: " << featureIndex << endl;
autoPtr<searchableSurfaceFeatures> ssFeatures
(
@ -210,7 +224,8 @@ void Foam::conformationSurfaces::readFeatures
{
fileName feMeshName(featureDict.lookup("extendedFeatureEdgeMesh"));
Info<< " features: " << feMeshName << endl;
Info<< " features: " << feMeshName << ", id: " << featureIndex
<< endl;
features_.set
(
@ -716,7 +731,11 @@ Foam::Field<bool> Foam::conformationSurfaces::wellInOutSide
const searchableSurface& surface(allGeometry_[surfaces_[s]]);
if (!surface.hasVolumeType())
if
(
!surface.hasVolumeType()
//&& surfaceVolumeTests[s][i] == volumeType::UNKNOWN
)
{
pointField sample(1, samplePts[i]);
scalarField nearestDistSqr(1, GREAT);
@ -733,7 +752,7 @@ Foam::Field<bool> Foam::conformationSurfaces::wellInOutSide
findSurfaceNearestIntersection
(
samplePts[i],
info[0].rawPoint(),
info[0].rawPoint() - 1e-3*mag(hitDir)*hitDir,
surfHit,
hitSurface
);

View File

@ -187,7 +187,7 @@ Foam::label Foam::autoDensity::recurseAndFill
word recursionName
) const
{
label maxDepth = 0;
label treeDepth = 0;
for (direction i = 0; i < 8; i++)
{
@ -201,10 +201,10 @@ Foam::label Foam::autoDensity::recurseAndFill
{
if (levelLimit > 0)
{
maxDepth =
treeDepth =
max
(
maxDepth,
treeDepth,
recurseAndFill
(
initialPoints,
@ -229,10 +229,10 @@ Foam::label Foam::autoDensity::recurseAndFill
if (!fillBox(initialPoints, subBB, true))
{
maxDepth =
treeDepth =
max
(
maxDepth,
treeDepth,
recurseAndFill
(
initialPoints,
@ -259,10 +259,10 @@ Foam::label Foam::autoDensity::recurseAndFill
if (!fillBox(initialPoints, subBB, false))
{
maxDepth =
treeDepth =
max
(
maxDepth,
treeDepth,
recurseAndFill
(
initialPoints,
@ -286,7 +286,7 @@ Foam::label Foam::autoDensity::recurseAndFill
}
}
return maxDepth + 1;
return treeDepth + 1;
}
@ -941,7 +941,7 @@ List<Vb::Point> autoDensity::initialPoints() const
Pout<< " Filling box " << hierBB << endl;
}
label maxDepth = recurseAndFill
label treeDepth = recurseAndFill
(
initialPoints,
hierBB,
@ -966,7 +966,7 @@ List<Vb::Point> autoDensity::initialPoints() const
<< scalar(nInitialPoints)/scalar(max(globalTrialPoints_, 1))
<< " success rate" << nl
<< indent
<< returnReduce(maxDepth, maxOp<label>())
<< returnReduce(treeDepth, maxOp<label>())
<< " levels of recursion (maximum)"
<< decrIndent << decrIndent
<< endl;

View File

@ -0,0 +1,244 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013 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/>.
\*---------------------------------------------------------------------------*/
#include "pointPairs.H"
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
template<class Triangulation>
inline Foam::Pair<Foam::labelPair>
Foam::pointPairs<Triangulation>::orderPointPair
(
const labelPair& vA,
const labelPair& vB
) const
{
return
(
(vA < vB)
? Pair<labelPair>(vA, vB)
: Pair<labelPair>(vB, vA)
);
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::findPointPair
(
const labelPair& vA,
const labelPair& vB
) const
{
if (vA == vB)
{
return false;
}
else if (find(orderPointPair(vA, vB)) == end())
{
return false;
}
return true;
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::insertPointPair
(
const labelPair& vA,
const labelPair& vB
)
{
if (vA == vB)
{
return false;
}
return insert(orderPointPair(vA, vB));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Triangulation>
Foam::pointPairs<Triangulation>::pointPairs(const Triangulation& triangulation)
:
ptPairTable(),
triangulation_(triangulation)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class Triangulation>
Foam::pointPairs<Triangulation>::~pointPairs()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::addPointPair
(
const labelPair& vA,
const labelPair& vB
)
{
return insertPointPair(vA, vB);
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::addPointPair
(
const labelPair& master,
const DynamicList<labelPair>& slaves
)
{
forAll(slaves, sI)
{
const labelPair& slave = slaves[sI];
addPointPair(master, slave);
}
return true;
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::addPointPair
(
const label vA,
const label vB
)
{
const label procNo = Pstream::myProcNo();
labelPair a(vA, procNo);
labelPair b(vB, procNo);
return addPointPair(a, b);
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::isPointPair
(
const Vertex_handle& vA,
const Vertex_handle& vB
) const
{
if (vA->boundaryPoint() && vB->boundaryPoint())
{
labelPair a(vA->index(), vA->procIndex());
labelPair b(vB->index(), vB->procIndex());
return findPointPair(a, b);
}
return false;
}
template<class Triangulation>
inline bool Foam::pointPairs<Triangulation>::isPointPair
(
const labelPair& vA,
const labelPair& vB
) const
{
return findPointPair(vA, vB);
}
template<class Triangulation>
void Foam::pointPairs<Triangulation>::reIndex(const Map<label>& oldToNewIndices)
{
pointPairs<Triangulation> newTable(triangulation_);
forAllConstIter(pointPairs, *this, iter)
{
Pair<labelPair> e = iter.key();
labelPair& start = e.first();
labelPair& end = e.second();
bool insert = true;
if (start.second() == Pstream::myProcNo())
{
Map<label>::const_iterator iter2 =
oldToNewIndices.find(start.first());
if (iter2 != oldToNewIndices.end())
{
if (iter2() != -1)
{
start.first() = iter2();
}
else
{
insert = false;
}
}
}
if (end.second() == Pstream::myProcNo())
{
Map<label>::const_iterator iter2 =
oldToNewIndices.find(end.first());
if (iter2 != oldToNewIndices.end())
{
if (iter2() != -1)
{
end.first() = iter2();
}
else
{
insert = false;
}
}
}
if (insert)
{
if (e.first() < e.second())
{
newTable.insert(e);
}
else if (e.first() > e.second())
{
newTable.insert(reverse(e));
}
}
}
this->transfer(newTable);
}
// ************************************************************************* //

View File

@ -0,0 +1,163 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013 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
pointPairs
Description
HashSet of unique edges. The edges are stored as a pair of pairs:
( (local index, processor index) (local index, processor index) )
e.g.,
( (0 1) (3 1) )
( (0 2) (5 1) )
\*---------------------------------------------------------------------------*/
#ifndef pointPairs_H
#define pointPairs_H
#include "labelPair.H"
#include "HashSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef HashSet
<
Pair<labelPair>,
FixedList<labelPair, 2>::Hash<>
> ptPairTable;
/*---------------------------------------------------------------------------*\
Class pointPairs Declaration
\*---------------------------------------------------------------------------*/
template<class Triangulation>
class pointPairs
:
public ptPairTable
{
// Private typedefs
typedef typename Triangulation::Vertex_handle Vertex_handle;
// Private data
const Triangulation& triangulation_;
// Private Member Functions
inline Pair<labelPair> orderPointPair
(
const labelPair& vA,
const labelPair& vB
) const;
inline bool insertPointPair
(
const labelPair& vA,
const labelPair& vB
);
inline bool findPointPair
(
const labelPair& vA,
const labelPair& vB
) const;
public:
// Constructors
//- Construct from triangulation
pointPairs(const Triangulation& triangulation);
//- Destructor
~pointPairs();
// Member Functions
// Access
inline bool isPointPair
(
const Vertex_handle& vA,
const Vertex_handle& vB
) const;
inline bool isPointPair
(
const labelPair& vA,
const labelPair& vB
) const;
// Edit
inline bool addPointPair
(
const labelPair& vA,
const labelPair& vB
);
inline bool addPointPair
(
const labelPair& master,
const DynamicList<labelPair>& slaves
);
inline bool addPointPair
(
const label vA,
const label vB
);
void reIndex(const Map<label>& oldToNewIndices);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "pointPairs.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -104,11 +104,14 @@ Foam::searchableBoxFeatures::features() const
edgeNormals[10][0] = 1; edgeNormals[10][1] = 3;
edgeNormals[11][0] = 3; edgeNormals[11][1] = 0;
tmp<pointField> surfacePointsTmp(surface().points());
pointField& surfacePoints = surfacePointsTmp();
forAll(edgeDirections, eI)
{
edgeDirections[eI] =
surface().points()()[treeBoundBox::edges[eI].end()]
- surface().points()()[treeBoundBox::edges[eI].start()];
surfacePoints[treeBoundBox::edges[eI].end()]
- surfacePoints[treeBoundBox::edges[eI].start()];
normalDirections[eI] = labelList(2, 0);
for (label j = 0; j < 2; ++j)
@ -116,8 +119,8 @@ Foam::searchableBoxFeatures::features() const
const vector cross =
(faceNormals[edgeNormals[eI][j]] ^ edgeDirections[eI]);
const vector fC0tofE0 =
0.5*(max(surface().points()() + min(surface().points()())))
- surface().points()()[treeBoundBox::edges[eI].start()];
0.5*(max(surfacePoints + min(surfacePoints)))
- surfacePoints[treeBoundBox::edges[eI].start()];
normalDirections[eI][j] =
(

View File

@ -0,0 +1,218 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013 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/>.
\*---------------------------------------------------------------------------*/
#include "searchablePlateFeatures.H"
#include "addToRunTimeSelectionTable.H"
#include "treeBoundBox.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(searchablePlateFeatures, 0);
addToRunTimeSelectionTable
(
searchableSurfaceFeatures,
searchablePlateFeatures,
dict
);
//! \cond - skip documentation : local scope only
const Foam::label edgesArray[4][2] =
{
{0, 1}, // 0
{0, 3},
{2, 1}, // 2
{2, 3}
};
//! \endcond
const edgeList searchablePlateFeatures::edges(calcEdges(edgesArray));
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::edgeList Foam::searchablePlateFeatures::calcEdges
(
const label edgesArray[4][2]
)
{
edgeList edges(4);
forAll(edges, edgeI)
{
edges[edgeI][0] = edgesArray[edgeI][0];
edges[edgeI][1] = edgesArray[edgeI][1];
}
return edges;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::searchablePlateFeatures::searchablePlateFeatures
(
const searchableSurface& surface,
const dictionary& dict
)
:
searchableSurfaceFeatures(surface, dict),
mode_
(
extendedFeatureEdgeMesh::sideVolumeTypeNames_
[
dict.lookupOrDefault<word>("meshableSide", "inside")
]
)
{
Info<< indent
<< " Meshable region = "
<< extendedFeatureEdgeMesh::sideVolumeTypeNames_[mode_]
<< endl;
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::searchablePlateFeatures::~searchablePlateFeatures()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::extendedFeatureEdgeMesh>
Foam::searchablePlateFeatures::features() const
{
autoPtr<extendedFeatureEdgeMesh> features;
vectorField faceNormals(1);
surface().getNormal(List<pointIndexHit>(1), faceNormals);
vectorField edgeDirections(4);
labelListList normalDirections(4);
labelListList edgeNormals(4);
forAll(edgeNormals, eI)
{
edgeNormals[eI].setSize(2, 0);
}
edgeNormals[0][0] = 0; edgeNormals[0][1] = 0;
edgeNormals[1][0] = 0; edgeNormals[1][1] = 0;
edgeNormals[2][0] = 0; edgeNormals[2][1] = 0;
edgeNormals[3][0] = 0; edgeNormals[3][1] = 0;
forAll(edgeDirections, eI)
{
edgeDirections[eI] =
surface().points()()[edges[eI].end()]
- surface().points()()[edges[eI].start()];
normalDirections[eI] = labelList(2, 0);
for (label j = 0; j < 2; ++j)
{
const vector cross =
(faceNormals[edgeNormals[eI][j]] ^ edgeDirections[eI]);
const vector fC0tofE0 =
0.5*(max(surface().points()() + min(surface().points()())))
- surface().points()()[edges[eI].start()];
normalDirections[eI][j] =
(
(
(cross/(mag(cross) + VSMALL))
& (fC0tofE0/(mag(fC0tofE0)+ VSMALL))
)
> 0.0
? 1
: -1
);
}
}
labelListList featurePointNormals(4);
labelListList featurePointEdges(4);
forAll(featurePointNormals, pI)
{
labelList& ftPtEdges = featurePointEdges[pI];
ftPtEdges.setSize(2, 0);
label edgeI = 0;
forAll(edges, eI)
{
const edge& e = edges[eI];
if (e.start() == pI)
{
ftPtEdges[edgeI++] = eI;
}
else if (e.end() == pI)
{
ftPtEdges[edgeI++] = eI;
}
}
labelList& ftPtNormals = featurePointNormals[pI];
ftPtNormals.setSize(1, 0);
ftPtNormals[0] = edgeNormals[ftPtEdges[0]][0];
}
labelList regionEdges;
features.set
(
new extendedFeatureEdgeMesh
(
IOobject
(
surface().name(),
surface().instance(),
"extendedFeatureEdgeMesh",
surface().db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
surface().points(),
edges,
4, 4, 4,
0, 0, 4, 4, // 4 flat edges
faceNormals,
List<extendedFeatureEdgeMesh::sideVolumeType>(4, mode_),
edgeDirections,
normalDirections,
edgeNormals,
featurePointNormals,
featurePointEdges,
regionEdges
)
);
return features;
}
// ************************************************************************* //

View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013 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::searchablePlateFeatures
Description
SourceFiles
searchablePlateFeatures.C
\*---------------------------------------------------------------------------*/
#ifndef searchablePlateFeatures_H
#define searchablePlateFeatures_H
#include "searchableSurfaceFeatures.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class searchablePlateFeatures Declaration
\*---------------------------------------------------------------------------*/
class searchablePlateFeatures
:
public searchableSurfaceFeatures
{
private:
//- To initialise edges.
static edgeList calcEdges(const label[4][2]);
// Private Member Data
//- Which side of the plate to mesh
const extendedFeatureEdgeMesh::sideVolumeType mode_;
// Private Member Functions
//- Disallow default bitwise copy construct
searchablePlateFeatures(const searchablePlateFeatures&);
//- Disallow default bitwise assignment
void operator=(const searchablePlateFeatures&);
public:
//- Runtime type information
TypeName("searchablePlateFeatures");
// Static data members
//- Edge to point addressing
static const edgeList edges;
// Constructors
//- Construct from searchable surface and dictionary
searchablePlateFeatures
(
const searchableSurface& surface,
const dictionary& dict
);
//- Destructor
virtual ~searchablePlateFeatures();
// Member Functions
//- Return true for a searchable plate having features
virtual bool hasFeatures() const
{
return true;
}
//- Return an extendedFeatureEdgeMesh containing the features
virtual autoPtr<extendedFeatureEdgeMesh> features() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -57,10 +57,19 @@ Foam::triSurfaceMeshFeatures::triSurfaceMeshFeatures
)
:
searchableSurfaceFeatures(surface, dict),
includedAngle_(readScalar(dict.lookup("includedAngle")))
includedAngle_(readScalar(dict.lookup("includedAngle"))),
mode_
(
extendedFeatureEdgeMesh::sideVolumeTypeNames_
[
dict.lookupOrDefault<word>("meshableSide", "inside")
]
)
{
Info<< indent
<< " Included angle = " << includedAngle_
<< " Included angle = " << includedAngle_ << nl
<< " Meshable region = "
<< extendedFeatureEdgeMesh::sideVolumeTypeNames_[mode_]
<< endl;
}
@ -82,7 +91,12 @@ Foam::triSurfaceMeshFeatures::features() const
surfaceFeatures sFeat(surfMesh, includedAngle_);
boolList surfBaffleRegions(surfMesh.patches().size(), false);
// @todo Need to read on a per region basis
boolList surfBaffleRegions
(
surfMesh.patches().size(),
(mode_ == extendedFeatureEdgeMesh::BOTH ? true : false)
);
features.set
(
@ -90,8 +104,8 @@ Foam::triSurfaceMeshFeatures::features() const
(
sFeat,
surface().db(),
surface().name() + ".extendedFeatureEdgeMesh"//,
//surfBaffleRegions
surface().name() + ".extendedFeatureEdgeMesh",
surfBaffleRegions
)
);

View File

@ -55,6 +55,9 @@ private:
const scalar includedAngle_;
//- Which side of the surface to mesh
const extendedFeatureEdgeMesh::sideVolumeType mode_;
// Private Member Functions

View File

@ -78,11 +78,79 @@ Description
#include "booleanSurface.H"
#include "edgeIntersections.H"
#include "meshTools.H"
#include "labelPair.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
bool intersectSurfaces
(
triSurface& surf,
edgeIntersections& edgeCuts
)
{
bool hasMoved = false;
for (label iter = 0; iter < 10; iter++)
{
Info<< "Determining intersections of surface edges with itself" << endl;
// Determine surface edge intersections. Allow surface to be moved.
// Number of iterations needed to resolve degenerates
label nIters = 0;
{
triSurfaceSearch querySurf(surf);
scalarField surfPointTol
(
1e-3*edgeIntersections::minEdgeLength(surf)
);
// Determine raw intersections
edgeCuts = edgeIntersections
(
surf,
querySurf,
surfPointTol
);
// Shuffle a bit to resolve degenerate edge-face hits
{
pointField points(surf.points());
nIters =
edgeCuts.removeDegenerates
(
5, // max iterations
surf,
querySurf,
surfPointTol,
points // work array
);
if (nIters != 0)
{
// Update geometric quantities
surf.movePoints(points);
hasMoved = true;
}
}
}
}
if (hasMoved)
{
fileName newFile("surf.obj");
Info<< "Surface has been moved. Writing to " << newFile << endl;
surf.write(newFile);
}
return hasMoved;
}
// Keep on shuffling surface points until no more degenerate intersections.
// Moves both surfaces and updates set of edge cuts.
bool intersectSurfaces
@ -238,6 +306,106 @@ label calcNormalDirection
}
void calcEdgeCuts
(
triSurface& surf1,
triSurface& surf2,
const bool perturb,
edgeIntersections& edge1Cuts,
edgeIntersections& edge2Cuts
)
{
if (perturb)
{
intersectSurfaces
(
surf1,
edge1Cuts,
surf2,
edge2Cuts
);
}
else
{
triSurfaceSearch querySurf2(surf2);
Info<< "Determining intersections of surf1 edges with surf2 faces"
<< endl;
edge1Cuts = edgeIntersections
(
surf1,
querySurf2,
1e-3*edgeIntersections::minEdgeLength(surf1)
);
triSurfaceSearch querySurf1(surf1);
Info<< "Determining intersections of surf2 edges with surf1 faces"
<< endl;
edge2Cuts = edgeIntersections
(
surf2,
querySurf1,
1e-3*edgeIntersections::minEdgeLength(surf2)
);
}
}
void calcFeaturePoints(const pointField& points, const edgeList& edges)
{
edgeMesh eMesh(points, edges);
const labelListList& pointEdges = eMesh.pointEdges();
// Get total number of feature points
label nFeaturePoints = 0;
forAll(pointEdges, pI)
{
const labelList& pEdges = pointEdges[pI];
if (pEdges.size() == 1)
{
nFeaturePoints++;
}
}
// Calculate addressing from feature point to cut point and cut edge
labelList featurePointToCutPoint(nFeaturePoints);
labelList featurePointToCutEdge(nFeaturePoints);
label nFeatPts = 0;
forAll(pointEdges, pI)
{
const labelList& pEdges = pointEdges[pI];
if (pEdges.size() == 1)
{
featurePointToCutPoint[nFeatPts] = pI;
featurePointToCutEdge[nFeatPts] = pEdges[0];
nFeatPts++;
}
}
label concaveStart = 0;
label mixedStart = 0;
label nonFeatureStart = nFeaturePoints;
labelListList featurePointNormals(nFeaturePoints);
labelListList featurePointEdges(nFeaturePoints);
labelList regionEdges;
}
int main(int argc, char *argv[])
{
argList::noParallel();
@ -319,52 +487,33 @@ int main(int argc, char *argv[])
<< exit(FatalError);
}
if (args.optionFound("perturb"))
{
intersectSurfaces
// Calculate the points where the edges are cut by the other surface
calcEdgeCuts
(
surf1,
surf2,
args.optionFound("perturb"),
edge1Cuts,
edge2Cuts
);
// Determine intersection edges from the edge cuts
surfaceIntersection inter
(
surf1,
edge1Cuts,
surf2,
edge2Cuts
);
}
else
{
triSurfaceSearch querySurf2(surf2);
Info<< "Determining intersections of surf1 edges with surf2 faces"
<< endl;
edge1Cuts = edgeIntersections
fileName sFeatFileName
(
surf1,
querySurf2,
1e-3*edgeIntersections::minEdgeLength(surf1)
);
triSurfaceSearch querySurf1(surf1);
Info<< "Determining intersections of surf2 edges with surf1 faces"
<< endl;
edge2Cuts = edgeIntersections
(
surf2,
querySurf1,
1e-3*edgeIntersections::minEdgeLength(surf2)
);
}
// Determine intersection edges
surfaceIntersection inter(surf1, edge1Cuts, surf2, edge2Cuts);
fileName sFeatFileName =
surf1Name.lessExt().name()
+ "_"
+ surf2Name.lessExt().name()
+ "_"
+ action;
+ action
);
label nFeatEds = inter.cutEdges().size();
@ -393,6 +542,7 @@ int main(int argc, char *argv[])
edgeDirections[cutEdgeI] = fE.vec(inter.cutPoints());
normals.append(norm1);
eNormals.append(normals.size() - 1);
if (surf1Baffle)
{
@ -416,9 +566,8 @@ int main(int argc, char *argv[])
);
}
eNormals.append(normals.size() - 1);
normals.append(norm2);
eNormals.append(normals.size() - 1);
if (surf2Baffle)
{
@ -443,8 +592,6 @@ int main(int argc, char *argv[])
);
}
eNormals.append(normals.size() - 1);
if (surf1Baffle)
{
@ -509,6 +656,38 @@ int main(int argc, char *argv[])
label internalStart = -1;
label nIntOrExt = 0;
label nFlat = 0;
label nOpen = 0;
label nMultiple = 0;
forAll(edgeNormals, eI)
{
label nEdNorms = edgeNormals[eI].size();
if (nEdNorms == 1)
{
nOpen++;
}
else if (nEdNorms == 2)
{
const vector& n0(normals[edgeNormals[eI][0]]);
const vector& n1(normals[edgeNormals[eI][1]]);
if ((n0 & n1) > extendedFeatureEdgeMesh::cosNormalAngleTol_)
{
nFlat++;
}
else
{
nIntOrExt++;
}
}
else if (nEdNorms > 2)
{
nMultiple++;
}
}
if (validActions[action] == booleanSurface::UNION)
{
@ -520,7 +699,7 @@ int main(int argc, char *argv[])
else
{
// All edges are external
internalStart = nFeatEds;
internalStart = nIntOrExt;
}
}
else if (validActions[action] == booleanSurface::INTERSECTION)
@ -528,7 +707,7 @@ int main(int argc, char *argv[])
if (!invertedSpace)
{
// All edges are external
internalStart = nFeatEds;
internalStart = nIntOrExt;
}
else
{
@ -539,7 +718,7 @@ int main(int argc, char *argv[])
else if (validActions[action] == booleanSurface::DIFFERENCE)
{
// All edges are external
internalStart = nFeatEds;
internalStart = nIntOrExt;
}
else
{
@ -569,6 +748,8 @@ int main(int argc, char *argv[])
normalDirectionsTmp[i] = normalDirections[i];
}
calcFeaturePoints(inter.cutPoints(), inter.cutEdges());
extendedFeatureEdgeMesh feMesh
(
IOobject
@ -582,18 +763,22 @@ int main(int argc, char *argv[])
),
inter.cutPoints(),
inter.cutEdges(),
0, // concaveStart,
0, // mixedStart,
0, // nonFeatureStart,
internalStart, // internalStart,
nFeatEds, // flatStart,
nFeatEds, // openStart,
nFeatEds, // multipleStart,
nIntOrExt, // flatStart,
nIntOrExt + nFlat, // openStart,
nIntOrExt + nFlat + nOpen, // multipleStart,
normalsTmp,
normalVolumeTypesTmp,
edgeDirections,
normalDirectionsTmp,
edgeNormalsTmp,
labelListList(0), // featurePointNormals,
labelListList(0), // featurePointEdges,
labelList(0) // regionEdges

View File

@ -925,7 +925,7 @@ void writeStats(const extendedFeatureEdgeMesh& fem, Ostream& os)
<< " open edges : "
<< (fem.multipleStart()- fem.openStart()) << nl
<< " multiply connected : "
<< (fem.edges().size()- fem.multipleStart()) << nl;
<< (fem.edges().size()- fem.multipleStart()) << endl;
}
@ -1223,17 +1223,34 @@ int main(int argc, char *argv[])
<< " internal edges : " << newSet.nInternalEdges() << nl
<< endl;
//if (writeObj)
//{
// newSet.writeObj("final");
//}
if (writeObj)
{
newSet.writeObj("final");
}
boolList surfBaffleRegions(surf.patches().size(), false);
wordList surfBaffleNames;
surfaceDict.readIfPresent("baffles", surfBaffleNames);
forAll(surf.patches(), pI)
{
const word& name = surf.patches()[pI].name();
if (findIndex(surfBaffleNames, name) != -1)
{
Info<< "Adding baffle region " << name << endl;
surfBaffleRegions[pI] = true;
}
}
// Extracting and writing a extendedFeatureEdgeMesh
extendedFeatureEdgeMesh feMesh
(
newSet,
runTime,
sFeatFileName + ".extendedFeatureEdgeMesh"
sFeatFileName + ".extendedFeatureEdgeMesh",
surfBaffleRegions
);

View File

@ -263,7 +263,8 @@ Foam::extendedFeatureEdgeMesh::extendedFeatureEdgeMesh
(
const surfaceFeatures& sFeat,
const objectRegistry& obr,
const fileName& sFeatFileName
const fileName& sFeatFileName,
const boolList& surfBaffleRegions
)
:
regIOobject
@ -337,7 +338,12 @@ Foam::extendedFeatureEdgeMesh::extendedFeatureEdgeMesh
// Check to see if the points have been already used
if (faceMap[eFI] == -1)
{
normalVolumeTypes_[nAdded++] = INSIDE;
normalVolumeTypes_[nAdded++] =
(
surfBaffleRegions[surf[eFI].region()]
? BOTH
: INSIDE
);
faceMap[eFI] = nAdded - 1;
}
@ -492,7 +498,7 @@ Foam::extendedFeatureEdgeMesh::classifyEdge
const List<vector>& norms,
const labelList& edNorms,
const vector& fC0tofC1
) const
)
{
label nEdNorms = edNorms.size();
@ -502,8 +508,8 @@ Foam::extendedFeatureEdgeMesh::classifyEdge
}
else if (nEdNorms == 2)
{
const vector n0(norms[edNorms[0]]);
const vector n1(norms[edNorms[1]]);
const vector& n0(norms[edNorms[0]]);
const vector& n1(norms[edNorms[1]]);
if ((n0 & n1) > cosNormalAngleTol_)
{
@ -1342,6 +1348,22 @@ void Foam::extendedFeatureEdgeMesh::writeObj
meshTools::writeOBJ(regionStr, points()[e[1]]); verti++;
regionStr << "l " << verti-1 << ' ' << verti << endl;
}
OFstream edgeDirsStr(prefix + "_edgeDirections.obj");
Info<< "Writing edge directions to " << edgeDirsStr.name() << endl;
forAll(edgeDirections_, i)
{
const vector& eVec = edgeDirections_[i];
const edge& e = edges()[i];
meshTools::writeOBJ
(
edgeDirsStr,
points()[e.start()],
eVec + points()[e.start()]
);
}
}

View File

@ -119,14 +119,14 @@ public:
static const Foam::NamedEnum<sideVolumeType, 4> sideVolumeTypeNames_;
//- Angular closeness tolerance for treating normals as the same
static scalar cosNormalAngleTol_;
private:
// Static data
//- Angular closeness tolerance for treating normals as the same
static scalar cosNormalAngleTol_;
//- Index of the start of the convex feature points - static as 0
static label convexStart_;
@ -202,15 +202,6 @@ private:
// data for edges and normals.
pointStatus classifyFeaturePoint(label ptI) const;
//- Classify the type of feature edge. Requires face centre 0 to face
// centre 1 vector to distinguish internal from external
edgeStatus classifyEdge
(
const List<vector>& norms,
const labelList& edNorms,
const vector& fC0tofC1
) const;
template<class Patch>
void sortPointsAndEdges
(
@ -259,7 +250,8 @@ public:
(
const surfaceFeatures& sFeat,
const objectRegistry& obr,
const fileName& sFeatFileName
const fileName& sFeatFileName,
const boolList& surfBaffleRegions
);
//- Construct from PrimitivePatch
@ -434,6 +426,9 @@ public:
//- Return the edgeStatus of a specified edge
inline edgeStatus getEdgeStatus(label edgeI) const;
//- Return the baffle faces of a specified edge
inline PackedList<2> edgeBaffles(label edgeI) const;
//- Demand driven construction of octree for feature points
const indexedOctree<treeDataPoint>& pointTree() const;
@ -468,6 +463,16 @@ public:
friend Istream& operator>>(Istream& is, sideVolumeType& vt);
friend Ostream& operator<<(Ostream& os, const sideVolumeType& vt);
//- Classify the type of feature edge. Requires face centre 0 to face
// centre 1 vector to distinguish internal from external
static edgeStatus classifyEdge
(
const List<vector>& norms,
const labelList& edNorms,
const vector& fC0tofC1
);
};

View File

@ -264,4 +264,27 @@ Foam::extendedFeatureEdgeMesh::getEdgeStatus(label edgeI) const
}
inline Foam::PackedList<2> Foam::extendedFeatureEdgeMesh::edgeBaffles
(
label edgeI
) const
{
const labelList& eNormals = edgeNormals_[edgeI];
DynamicList<label> edgeBaffles(eNormals.size());
forAll(eNormals, enI)
{
const label normI = eNormals[enI];
if (normalVolumeTypes_[normI])
{
edgeBaffles.append(normI);
}
}
return PackedList<2>(edgeBaffles);
}
// ************************************************************************* //

View File

@ -117,19 +117,16 @@ void Foam::edgeIntersections::intersectEdges
<< " triangles ..." << endl;
}
// Construct octree.
const indexedOctree<treeDataTriSurface>& tree = querySurf2.tree();
label nHits = 0;
pointField start(edgeLabels.size());
pointField end(edgeLabels.size());
vectorField edgeDirs(edgeLabels.size());
// Go through all edges, calculate intersections
forAll(edgeLabels, i)
{
label edgeI = edgeLabels[i];
if (debug && (i % 1000 == 0))
if (debug)// && (i % 1000 == 0))
{
Pout<< "Intersecting edge " << edgeI << " with surface" << endl;
}
@ -140,85 +137,81 @@ void Foam::edgeIntersections::intersectEdges
const point& pEnd = points1[meshPoints[e.end()]];
const vector eVec(pEnd - pStart);
const scalar eMag = mag(eVec);
const vector n(eVec/(eMag + VSMALL));
// Smallish length for intersection calculation errors.
const point tolVec = 1e-6*eVec;
const vector n(eVec/(mag(eVec) + VSMALL));
// Start tracking somewhat before pStart and up to somewhat after p1.
// Note that tolerances here are smaller than those used to classify
// hit below.
// This will cause this hit to be marked as degenerate and resolved
// later on.
point p0 = pStart - 0.5*surf1PointTol[e[0]]*n;
const point p1 = pEnd + 0.5*surf1PointTol[e[1]]*n;
const scalar maxS = mag(p1 - pStart);
start[i] = pStart - 0.5*surf1PointTol[e[0]]*n;
end[i] = pEnd + 0.5*surf1PointTol[e[1]]*n;
// Get all intersections of the edge with the surface
edgeDirs[i] = n;
}
DynamicList<pointIndexHit> currentIntersections(100);
DynamicList<label> currentIntersectionTypes(100);
List<List<pointIndexHit> > edgeIntersections;
querySurf2.findLineAll
(
start,
end,
edgeIntersections
);
while (true)
label nHits = 0;
// Classify the hits
forAll(edgeLabels, i)
{
pointIndexHit pHit = tree.findLine(p0, p1);
const label edgeI = edgeLabels[i];
if (pHit.hit())
labelList& intersectionTypes = classification_[edgeI];
intersectionTypes.setSize(edgeIntersections[i].size(), -1);
this->operator[](edgeI).transfer(edgeIntersections[i]);
forAll(intersectionTypes, hitI)
{
nHits++;
const pointIndexHit& pHit = this->operator[](edgeI)[hitI];
label& hitType = intersectionTypes[hitI];
currentIntersections.append(pHit);
if (!pHit.hit())
{
continue;
}
const edge& e = surf1.edges()[edgeI];
// Classify point on surface1 edge.
label edgeEnd = -1;
if (mag(pHit.hitPoint() - start[i]) < surf1PointTol[e[0]])
{
// Intersection is close to edge start
hitType = 0;
}
else if (mag(pHit.hitPoint() - end[i]) < surf1PointTol[e[1]])
{
// Intersection is close to edge end
hitType = 1;
}
else if (mag(edgeDirs[i] & normals2[pHit.index()]) < alignedCos_)
{
// Edge is almost coplanar with the face
if (mag(pHit.hitPoint() - pStart) < surf1PointTol[e[0]])
{
edgeEnd = 0;
}
else if (mag(pHit.hitPoint() - pEnd) < surf1PointTol[e[1]])
{
edgeEnd = 1;
}
else if (mag(n & normals2[pHit.index()]) < alignedCos_)
{
Pout<< "Flat angle edge:" << edgeI
<< " face:" << pHit.index()
<< " cos:" << mag(n & normals2[pHit.index()])
<< " cos:" << mag(edgeDirs[i] & normals2[pHit.index()])
<< endl;
edgeEnd = 2;
hitType = 2;
}
currentIntersectionTypes.append(edgeEnd);
if (edgeEnd == 1)
if (debug)
{
// Close to end
break;
}
else
{
// Continue tracking. Shift by a small amount.
p0 = pHit.hitPoint() + tolVec;
if (((p0-pStart) & n) >= maxS)
{
break;
}
}
}
else
{
// No hit.
break;
}
Info<< " hit " << pHit << " classify = " << hitType << endl;
}
// Done current edge. Transfer all data into *this
operator[](edgeI).transfer(currentIntersections);
classification_[edgeI].transfer(currentIntersectionTypes);
nHits++;
}
}
if (debug)
@ -226,7 +219,6 @@ void Foam::edgeIntersections::intersectEdges
Pout<< "Found " << nHits << " intersections of edges with surface ..."
<< endl;
}
}

View File

@ -202,7 +202,6 @@ void Foam::surfaceIntersection::storeIntersection
DynamicList<point>& allCutPoints
)
{
forAll(facesA, facesAI)
{
label faceA = facesA[facesAI];
@ -1147,6 +1146,12 @@ const Foam::edgeList& Foam::surfaceIntersection::cutEdges() const
}
const Foam::labelPairLookup& Foam::surfaceIntersection::facePairToVertex() const
{
return facePairToVertex_;
}
const Foam::labelPairLookup& Foam::surfaceIntersection::facePairToEdge() const
{
return facePairToEdge_;

View File

@ -273,7 +273,7 @@ public:
const edgeList& cutEdges() const;
//const labelPairLookup& facePairToVertex() const;
const labelPairLookup& facePairToVertex() const;
const labelPairLookup& facePairToEdge() const;

View File

@ -59,9 +59,9 @@ surfaceConformation
extendedFeatureEdgeMesh "vessel.extendedFeatureEdgeMesh";
regions
{
patch0 {}
patch1 {}
patch2 {}
patch3 {}
}
}
@ -118,7 +118,7 @@ motionControl
minimumCellSizeCoeff 0.1;
maxRefinementIterations 0;
maxRefinementIterations 1;
maxSmoothingIterations 100;
@ -142,7 +142,7 @@ motionControl
regions
{
patch1
patch0
{
surfaceCellSizeFunction uniformValue;
uniformValueCoeffs
@ -154,7 +154,7 @@ motionControl
uniformCoeffs{}
}
patch2
patch1
{
priority 2;
surfaceCellSizeFunction uniformValue;
@ -170,7 +170,7 @@ motionControl
}
}
patch3
patch2
{
priority 2;
surfaceCellSizeFunction uniformValue;