mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'master' of /home/dm4/OpenFOAM/OpenFOAM-dev
This commit is contained in:
@ -20,7 +20,8 @@ EXE_LIBS = \
|
||||
$(CGAL_LIBS) \
|
||||
-lconformalVoronoiMesh \
|
||||
-lmeshTools \
|
||||
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lscotchDecomp \
|
||||
-ldecompositionMethods \
|
||||
-L$(FOAM_LIBBIN)/dummy -lptscotchDecomp \
|
||||
-ledgeMesh \
|
||||
-ltriSurface \
|
||||
-ldynamicMesh
|
||||
|
||||
@ -19,7 +19,6 @@ EXE_INC = \
|
||||
|
||||
EXE_LIBS = \
|
||||
-lmeshTools \
|
||||
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lscotchDecomp \
|
||||
-ledgeMesh \
|
||||
-ltriSurface \
|
||||
-ldynamicMesh
|
||||
|
||||
@ -63,7 +63,7 @@ Foam::fieldFromFile::fieldFromFile
|
||||
|
||||
Foam::triSurfaceScalarField Foam::fieldFromFile::load()
|
||||
{
|
||||
Info<< "Loading: " << fileName_ << endl;
|
||||
Info<< indent << "Loading: " << fileName_ << endl;
|
||||
|
||||
triSurfaceScalarField surfaceCellSize
|
||||
(
|
||||
|
||||
@ -82,9 +82,9 @@ Foam::nonUniformField::nonUniformField
|
||||
Info<< decrIndent;
|
||||
|
||||
Info<< indent << "Cell size field statistics:" << nl
|
||||
<< indent << " Minimum: " << min(surfaceCellSize_).value() << nl
|
||||
<< indent << " Average: " << average(surfaceCellSize_).value() << nl
|
||||
<< indent << " Maximum: " << max(surfaceCellSize_).value() << endl;
|
||||
<< indent << " Minimum: " << min(surfaceCellSize_).value() << nl
|
||||
<< indent << " Average: " << average(surfaceCellSize_).value() << nl
|
||||
<< indent << " Maximum: " << max(surfaceCellSize_).value() << endl;
|
||||
|
||||
Info<< decrIndent;
|
||||
}
|
||||
|
||||
@ -46,7 +46,10 @@ Foam::surfaceCellSizeFunction::surfaceCellSizeFunction
|
||||
dictionary(surfaceCellSizeFunctionDict),
|
||||
surface_(surface),
|
||||
coeffsDict_(subDict(type + "Coeffs")),
|
||||
refinementFactor_(readScalar(lookup("refinementFactor")))
|
||||
refinementFactor_
|
||||
(
|
||||
lookupOrDefault<scalar>("refinementFactor", 1.0)
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@ -44,6 +44,142 @@ const Foam::scalar Foam::conformalVoronoiMesh::tolParallel = 1e-3;
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::conformalVoronoiMesh::requiredSize
|
||||
(
|
||||
const Foam::point& pt
|
||||
) const
|
||||
{
|
||||
pointIndexHit surfHit;
|
||||
label hitSurface;
|
||||
|
||||
DynamicList<scalar> cellSizeHits;
|
||||
|
||||
geometryToConformTo_.findSurfaceNearest
|
||||
(
|
||||
pt,
|
||||
sqr(GREAT),
|
||||
surfHit,
|
||||
hitSurface
|
||||
);
|
||||
|
||||
if (!surfHit.hit())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::tensor Foam::conformalVoronoiMesh::requiredAlignment"
|
||||
)
|
||||
<< "findSurfaceNearest did not find a hit across the surfaces."
|
||||
<< exit(FatalError) << endl;
|
||||
}
|
||||
|
||||
cellSizeHits.append(cellSizeControl().cellSize(pt));
|
||||
|
||||
// Primary alignment
|
||||
|
||||
vectorField norm(1);
|
||||
|
||||
allGeometry_[hitSurface].getNormal
|
||||
(
|
||||
List<pointIndexHit>(1, surfHit),
|
||||
norm
|
||||
);
|
||||
|
||||
const vector np = norm[0];
|
||||
|
||||
// Generate equally spaced 'spokes' in a circle normal to the
|
||||
// direction from the vertex to the closest point on the surface
|
||||
// and look for a secondary intersection.
|
||||
|
||||
const vector d = surfHit.hitPoint() - pt;
|
||||
|
||||
const tensor Rp = rotationTensor(vector(0,0,1), np);
|
||||
|
||||
const label s = cvMeshControls().alignmentSearchSpokes();
|
||||
|
||||
const scalar spanMag = geometryToConformTo_.globalBounds().mag();
|
||||
|
||||
scalar totalDist = 0;
|
||||
|
||||
for (label i = 0; i < s; i++)
|
||||
{
|
||||
vector spoke
|
||||
(
|
||||
Foam::cos(i*constant::mathematical::twoPi/s),
|
||||
Foam::sin(i*constant::mathematical::twoPi/s),
|
||||
0
|
||||
);
|
||||
|
||||
spoke *= spanMag;
|
||||
|
||||
spoke = Rp & spoke;
|
||||
|
||||
pointIndexHit spokeHit;
|
||||
|
||||
label spokeSurface = -1;
|
||||
|
||||
// internal spoke
|
||||
|
||||
geometryToConformTo_.findSurfaceNearestIntersection
|
||||
(
|
||||
pt,
|
||||
pt + spoke,
|
||||
spokeHit,
|
||||
spokeSurface
|
||||
);
|
||||
|
||||
if (spokeHit.hit())
|
||||
{
|
||||
const Foam::point& hitPt = spokeHit.hitPoint();
|
||||
|
||||
scalar spokeHitDistance = mag(hitPt - pt);
|
||||
|
||||
cellSizeHits.append
|
||||
(
|
||||
cellSizeControl().cellSize(hitPt)
|
||||
);
|
||||
|
||||
totalDist += spokeHitDistance;
|
||||
}
|
||||
|
||||
//external spoke
|
||||
|
||||
Foam::point mirrorPt = pt + 2*d;
|
||||
|
||||
geometryToConformTo_.findSurfaceNearestIntersection
|
||||
(
|
||||
mirrorPt,
|
||||
mirrorPt + spoke,
|
||||
spokeHit,
|
||||
spokeSurface
|
||||
);
|
||||
|
||||
if (spokeHit.hit())
|
||||
{
|
||||
const Foam::point& hitPt = spokeHit.hitPoint();
|
||||
|
||||
scalar spokeHitDistance = mag(hitPt - mirrorPt);
|
||||
|
||||
cellSizeHits.append
|
||||
(
|
||||
cellSizeControl().cellSize(hitPt)
|
||||
);
|
||||
|
||||
totalDist += spokeHitDistance;
|
||||
}
|
||||
}
|
||||
|
||||
scalar cellSize = 0;
|
||||
|
||||
forAll(cellSizeHits, hitI)
|
||||
{
|
||||
cellSize += cellSizeHits[hitI];
|
||||
}
|
||||
|
||||
return cellSize/cellSizeHits.size();
|
||||
//return cellSizeControl().cellSize(pt);
|
||||
}
|
||||
|
||||
|
||||
Foam::tensor Foam::conformalVoronoiMesh::requiredAlignment
|
||||
(
|
||||
const Foam::point& pt
|
||||
@ -828,10 +964,7 @@ void Foam::conformalVoronoiMesh::storeSizesAndAlignments
|
||||
{
|
||||
sizeAndAlignmentLocations_[i] = topoint(*pit);
|
||||
|
||||
storedSizes_[i] = cellSizeControl().cellSize
|
||||
(
|
||||
sizeAndAlignmentLocations_[i]
|
||||
);
|
||||
storedSizes_[i] = requiredSize(sizeAndAlignmentLocations_[i]);
|
||||
|
||||
storedAlignments_[i] = requiredAlignment(sizeAndAlignmentLocations_[i]);
|
||||
|
||||
|
||||
@ -268,6 +268,9 @@ private:
|
||||
//- Return the local maximum surface protrusion distance
|
||||
inline scalar maxSurfaceProtrusion(const Foam::point& pt) const;
|
||||
|
||||
//- Return the required cell size at the given location
|
||||
scalar requiredSize(const Foam::point& pt) const;
|
||||
|
||||
//- Return the required alignment directions at the given location
|
||||
tensor requiredAlignment(const Foam::point& pt) const;
|
||||
|
||||
@ -533,6 +536,11 @@ private:
|
||||
const Delaunay::Finite_edges_iterator& eit
|
||||
) const;
|
||||
|
||||
boolList dualFaceBoundaryPoints
|
||||
(
|
||||
const Delaunay::Finite_edges_iterator& eit
|
||||
) const;
|
||||
|
||||
//- Finds the maximum filterCount of the dual vertices
|
||||
// (Delaunay cells) that form the dual face produced by the
|
||||
// supplied edge
|
||||
@ -839,6 +847,13 @@ private:
|
||||
const Delaunay::Finite_facets_iterator& fit
|
||||
) const;
|
||||
|
||||
//- Merge adjacent edges that are not attached to other faces
|
||||
label mergeNearlyParallelEdges
|
||||
(
|
||||
const pointField& pts,
|
||||
const scalar maxCosAngle
|
||||
);
|
||||
|
||||
//- Merge vertices that are very close together
|
||||
void mergeCloseDualVertices
|
||||
(
|
||||
|
||||
@ -212,6 +212,20 @@ void Foam::conformalVoronoiMesh::calcDualMesh
|
||||
Info<< nl << "Collapsing unnecessary faces" << endl;
|
||||
|
||||
collapseFaces(points, boundaryPts, deferredCollapseFaces);
|
||||
|
||||
const scalar maxCosAngle
|
||||
= cos(degToRad(cvMeshControls().edgeMergeAngle()));
|
||||
|
||||
Info<< nl << "Merging adjacent edges which have an angle "
|
||||
<< "of greater than "
|
||||
<< cvMeshControls().edgeMergeAngle() << ": " << endl;
|
||||
|
||||
label nRemovedEdges =
|
||||
mergeNearlyParallelEdges(points, maxCosAngle);
|
||||
|
||||
reduce(nRemovedEdges, sumOp<label>());
|
||||
|
||||
Info<< " Merged " << nRemovedEdges << " edges" << endl;
|
||||
}
|
||||
|
||||
labelHashSet wrongFaces = checkPolyMeshQuality(points);
|
||||
@ -652,6 +666,113 @@ Foam::label Foam::conformalVoronoiMesh::mergeCloseDualVertices
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::conformalVoronoiMesh::mergeNearlyParallelEdges
|
||||
(
|
||||
const pointField& pts,
|
||||
const scalar maxCosAngle
|
||||
)
|
||||
{
|
||||
List<HashSet<label> > pointFaceCount(number_of_cells());
|
||||
labelList pointNeighbour(number_of_cells(), -1);
|
||||
|
||||
Map<label> dualPtIndexMap;
|
||||
|
||||
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 (isBoundaryDualFace(eit))
|
||||
{
|
||||
const face f = buildDualFace(eit);
|
||||
|
||||
forAll(f, pI)
|
||||
{
|
||||
const label pIndex = f[pI];
|
||||
|
||||
const label prevPointI = f.prevLabel(pI);
|
||||
const label nextPointI = f.nextLabel(pI);
|
||||
|
||||
pointFaceCount[pIndex].insert(prevPointI);
|
||||
pointFaceCount[pIndex].insert(nextPointI);
|
||||
pointNeighbour[pIndex] = nextPointI;
|
||||
}
|
||||
}
|
||||
else if
|
||||
(
|
||||
vA->internalOrBoundaryPoint()
|
||||
|| vB->internalOrBoundaryPoint()
|
||||
)
|
||||
{
|
||||
const face f = buildDualFace(eit);
|
||||
const boolList faceBoundaryPoints = dualFaceBoundaryPoints(eit);
|
||||
|
||||
forAll(f, pI)
|
||||
{
|
||||
const label pIndex = f[pI];
|
||||
|
||||
const label prevPointI = f.prevLabel(pI);
|
||||
const label nextPointI = f.nextLabel(pI);
|
||||
|
||||
pointFaceCount[pIndex].insert(prevPointI);
|
||||
pointFaceCount[pIndex].insert(nextPointI);
|
||||
|
||||
if (faceBoundaryPoints[pI] == false)
|
||||
{
|
||||
pointNeighbour[pIndex] = nextPointI;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (faceBoundaryPoints[prevPointI] == true)
|
||||
{
|
||||
pointNeighbour[pIndex] = prevPointI;
|
||||
}
|
||||
else if (faceBoundaryPoints[nextPointI] == true)
|
||||
{
|
||||
pointNeighbour[pIndex] = nextPointI;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointNeighbour[pIndex] = pIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forAll(pointFaceCount, pI)
|
||||
{
|
||||
if (pointFaceCount[pI].size() == 2)
|
||||
{
|
||||
List<vector> edges(2, vector(0, 0, 0));
|
||||
|
||||
label count = 0;
|
||||
forAllConstIter(HashSet<label>, pointFaceCount[pI], iter)
|
||||
{
|
||||
edges[count] = pts[pI] - pts[iter.key()];
|
||||
edges[count] /= mag(edges[count]) + VSMALL;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (mag(edges[0] & edges[1]) > maxCosAngle)
|
||||
{
|
||||
dualPtIndexMap.insert(pI, pointNeighbour[pI]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reindexDualVertices(dualPtIndexMap);
|
||||
|
||||
return dualPtIndexMap.size();
|
||||
}
|
||||
|
||||
|
||||
void Foam::conformalVoronoiMesh::smoothSurface
|
||||
(
|
||||
pointField& pts,
|
||||
@ -696,7 +817,6 @@ void Foam::conformalVoronoiMesh::smoothSurface
|
||||
} while (nCollapsedFaces > 0);
|
||||
|
||||
// Force all points of boundary faces to be on the surface
|
||||
|
||||
for
|
||||
(
|
||||
Delaunay::Finite_cells_iterator cit = finite_cells_begin();
|
||||
@ -917,6 +1037,7 @@ void Foam::conformalVoronoiMesh::collapseFaces
|
||||
|
||||
mergeCloseDualVertices(pts, boundaryPts);
|
||||
|
||||
|
||||
if (nCollapsedFaces > 0)
|
||||
{
|
||||
Info<< " Collapsed " << nCollapsedFaces << " faces" << endl;
|
||||
@ -932,6 +1053,7 @@ void Foam::conformalVoronoiMesh::collapseFaces
|
||||
}
|
||||
|
||||
} while (nCollapsedFaces > 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1064,6 +1186,25 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
|
||||
bool allowEarlyCollapseToPoint = true;
|
||||
|
||||
|
||||
// // Quick exit
|
||||
// label smallEdges = 0;
|
||||
// const edgeList& fEdges = f.edges();
|
||||
// forAll(fEdges, eI)
|
||||
// {
|
||||
// const edge& e = fEdges[eI];
|
||||
//
|
||||
// if (e.mag(pts) < 0.2*targetFaceSize)
|
||||
// {
|
||||
// smallEdges++;
|
||||
// }
|
||||
// }
|
||||
// if (smallEdges == 0)
|
||||
// {
|
||||
// return fcmNone;
|
||||
// }
|
||||
|
||||
|
||||
// if (maxFC > cvMeshControls().filterCountSkipThreshold() - 3)
|
||||
// {
|
||||
// limitToQuadsOrTris = true;
|
||||
@ -1071,6 +1212,7 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
// allowEarlyCollapseToPoint = false;
|
||||
// }
|
||||
|
||||
|
||||
collapseSizeLimitCoeff *= pow
|
||||
(
|
||||
cvMeshControls().filterErrorReductionCoeff(),
|
||||
@ -1158,6 +1300,91 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
scalar maxDist = 0;
|
||||
scalar minDist = GREAT;
|
||||
//
|
||||
// if (f.size() <= 3)
|
||||
// {
|
||||
// const edgeList& fEdges = f.edges();
|
||||
//
|
||||
// forAll(fEdges, eI)
|
||||
// {
|
||||
// const edge& e = fEdges[eI];
|
||||
// const scalar d = e.mag(pts);
|
||||
//
|
||||
// if (d > maxDist)
|
||||
// {
|
||||
// maxDist = d;
|
||||
// collapseAxis = e.vec(pts);
|
||||
// }
|
||||
// else if (d < minDist && d != 0)
|
||||
// {
|
||||
// minDist = d;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// forAll(f, pI)
|
||||
// {
|
||||
// for (label i = pI + 1; i < f.size(); ++i)
|
||||
// {
|
||||
// if
|
||||
// (
|
||||
// f[i] != f.nextLabel(pI)
|
||||
// && f[i] != f.prevLabel(pI)
|
||||
// )
|
||||
// {
|
||||
// scalar d = mag(pts[f[pI]] - pts[f[i]]);
|
||||
//
|
||||
// if (d > maxDist)
|
||||
// {
|
||||
// maxDist = d;
|
||||
// collapseAxis = pts[f[pI]] - pts[f[i]];
|
||||
// }
|
||||
// else if (d < minDist && d != 0)
|
||||
// {
|
||||
// minDist = d;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const edgeList& fEdges = f.edges();
|
||||
//
|
||||
// scalar perimeter = 0;
|
||||
//
|
||||
// forAll(fEdges, eI)
|
||||
// {
|
||||
// const edge& e = fEdges[eI];
|
||||
// const scalar d = e.mag(pts);
|
||||
//
|
||||
// perimeter += d;
|
||||
//
|
||||
//// collapseAxis += e.vec(pts);
|
||||
//
|
||||
// if (d > maxDist)
|
||||
// {
|
||||
// collapseAxis = e.vec(pts);
|
||||
// maxDist = d;
|
||||
// }
|
||||
// else if (d < minDist && d != 0)
|
||||
// {
|
||||
// minDist = d;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// collapseAxis /= mag(collapseAxis);
|
||||
//
|
||||
//// Info<< f.size() << " " << minDist << " " << maxDist << " | "
|
||||
//// << collapseAxis << endl;
|
||||
//
|
||||
// aspectRatio = maxDist/minDist;
|
||||
//
|
||||
// aspectRatio = min(aspectRatio, sqr(perimeter)/(16.0*fA));
|
||||
|
||||
if (magSqr(collapseAxis) < VSMALL)
|
||||
{
|
||||
WarningIn
|
||||
@ -1170,9 +1397,9 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
// Output face and collapse axis for visualisation
|
||||
|
||||
Pout<< "# Aspect ratio = " << aspectRatio << nl
|
||||
<< "# inertia = " << J << nl
|
||||
<< "# determinant = " << detJ << nl
|
||||
<< "# eigenvalues = " << eigenValues(J) << nl
|
||||
// << "# inertia = " << J << nl
|
||||
// << "# determinant = " << detJ << nl
|
||||
// << "# eigenvalues = " << eigenValues(J) << nl
|
||||
<< "# collapseAxis = " << collapseAxis << nl
|
||||
<< "# facePts = " << facePts << nl
|
||||
<< endl;
|
||||
@ -1280,8 +1507,6 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
{
|
||||
scalar guardFraction = cvMeshControls().edgeCollapseGuardFraction();
|
||||
|
||||
cvMeshControls().maxCollapseFaceToPointSideLengthCoeff();
|
||||
|
||||
if
|
||||
(
|
||||
allowEarlyCollapseToPoint
|
||||
@ -1337,6 +1562,8 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
Foam::point collapseToPt =
|
||||
collapseAxis*(sum(dNeg)/dNeg.size() - dShift) + fC;
|
||||
|
||||
// DynamicList<label> faceBoundaryPts(f.size());
|
||||
|
||||
forAll(facePtsNeg, fPtI)
|
||||
{
|
||||
if (boundaryPts[facePtsNeg[fPtI]] == true)
|
||||
@ -1351,9 +1578,36 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
collapseToPt = pts[collapseToPtI];
|
||||
|
||||
break;
|
||||
|
||||
// faceBoundaryPts.append(facePtsNeg[fPtI]);
|
||||
}
|
||||
}
|
||||
|
||||
// if (!faceBoundaryPts.empty())
|
||||
// {
|
||||
// if (faceBoundaryPts.size() == 2)
|
||||
// {
|
||||
// collapseToPtI = faceBoundaryPts[0];
|
||||
//
|
||||
// collapseToPt =
|
||||
// 0.5
|
||||
// *(
|
||||
// pts[faceBoundaryPts[0]]
|
||||
// + pts[faceBoundaryPts[1]]
|
||||
// );
|
||||
// }
|
||||
// else if (faceBoundaryPts.size() < f.size())
|
||||
// {
|
||||
// face bFace(faceBoundaryPts);
|
||||
//
|
||||
// collapseToPtI = faceBoundaryPts.first();
|
||||
//
|
||||
// collapseToPt = bFace.centre(pts);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// faceBoundaryPts.clear();
|
||||
|
||||
// ...otherwise arbitrarily choosing the most distant
|
||||
// point as the index to collapse to.
|
||||
|
||||
@ -1384,9 +1638,34 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
collapseToPt = pts[collapseToPtI];
|
||||
|
||||
break;
|
||||
|
||||
// faceBoundaryPts.append(facePtsNeg[fPtI]);
|
||||
}
|
||||
}
|
||||
|
||||
// if (!faceBoundaryPts.empty())
|
||||
// {
|
||||
// if (faceBoundaryPts.size() == 2)
|
||||
// {
|
||||
// collapseToPtI = faceBoundaryPts[0];
|
||||
//
|
||||
// collapseToPt =
|
||||
// 0.5
|
||||
// *(
|
||||
// pts[faceBoundaryPts[0]]
|
||||
// + pts[faceBoundaryPts[1]]
|
||||
// );
|
||||
// }
|
||||
// else if (faceBoundaryPts.size() < f.size())
|
||||
// {
|
||||
// face bFace(faceBoundaryPts);
|
||||
//
|
||||
// collapseToPtI = faceBoundaryPts.first();
|
||||
//
|
||||
// collapseToPt = bFace.centre(pts);
|
||||
// }
|
||||
// }
|
||||
|
||||
// ...otherwise arbitrarily choosing the most distant
|
||||
// point as the index to collapse to.
|
||||
|
||||
@ -1406,6 +1685,8 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
|
||||
Foam::point collapseToPt = fC;
|
||||
|
||||
DynamicList<label> faceBoundaryPts(f.size());
|
||||
|
||||
forAll(facePts, fPtI)
|
||||
{
|
||||
if (boundaryPts[facePts[fPtI]] == true)
|
||||
@ -1415,11 +1696,32 @@ Foam::conformalVoronoiMesh::collapseFace
|
||||
// use the first boundary point encountered if
|
||||
// there are multiple boundary points.
|
||||
|
||||
collapseToPtI = facePts[fPtI];
|
||||
// collapseToPtI = facePts[fPtI];
|
||||
//
|
||||
// collapseToPt = pts[collapseToPtI];
|
||||
//
|
||||
// break;
|
||||
|
||||
collapseToPt = pts[collapseToPtI];
|
||||
faceBoundaryPts.append(facePts[fPtI]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
if (!faceBoundaryPts.empty())
|
||||
{
|
||||
if (faceBoundaryPts.size() == 2)
|
||||
{
|
||||
collapseToPtI = faceBoundaryPts[0];
|
||||
|
||||
collapseToPt =
|
||||
0.5*(pts[faceBoundaryPts[0]] + pts[faceBoundaryPts[1]]);
|
||||
}
|
||||
else if (faceBoundaryPts.size() < f.size())
|
||||
{
|
||||
face bFace(faceBoundaryPts);
|
||||
|
||||
collapseToPtI = faceBoundaryPts.first();
|
||||
|
||||
collapseToPt = bFace.centre(pts);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1791,9 +2093,9 @@ void Foam::conformalVoronoiMesh::checkCellSizing()
|
||||
}
|
||||
|
||||
Info<< " Automatically re-sizing " << cellsToResize.size()
|
||||
<< " cells that are attached to the bad faces: DISABLED" << endl;
|
||||
<< " cells that are attached to the bad faces: " << endl;
|
||||
|
||||
//cellSizeControl_.setCellSizes(cellsToResize);
|
||||
cellSizeControl_.setCellSizes(cellsToResize);
|
||||
}
|
||||
|
||||
timeCheck("End of Cell Sizing");
|
||||
@ -1858,7 +2160,10 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::findOffsetPatchFaces
|
||||
}
|
||||
}
|
||||
|
||||
offsetBoundaryCells.write();
|
||||
if (cvMeshControls().objOutput())
|
||||
{
|
||||
offsetBoundaryCells.write();
|
||||
}
|
||||
|
||||
return offsetBoundaryCells;
|
||||
}
|
||||
@ -2092,13 +2397,7 @@ void Foam::conformalVoronoiMesh::indexDualVertices
|
||||
|
||||
pts[dualVertI] = cit->dual();
|
||||
|
||||
if
|
||||
(
|
||||
!cit->vertex(0)->internalOrBoundaryPoint()
|
||||
|| !cit->vertex(1)->internalOrBoundaryPoint()
|
||||
|| !cit->vertex(2)->internalOrBoundaryPoint()
|
||||
|| !cit->vertex(3)->internalOrBoundaryPoint()
|
||||
)
|
||||
if (cit->boundaryDualVertex())
|
||||
{
|
||||
// This is a boundary dual vertex
|
||||
boundaryPts[dualVertI] = true;
|
||||
|
||||
@ -719,12 +719,15 @@ bool Foam::conformalVoronoiMesh::dualCellSurfaceAllIntersections
|
||||
|
||||
const Foam::point& p = infoList[hitI].hitPoint();
|
||||
|
||||
const scalar separationDistance
|
||||
= mag(p - info.hitPoint());
|
||||
const scalar separationDistance =
|
||||
mag(p - info.hitPoint());
|
||||
|
||||
const scalar minSepDist
|
||||
= sqr(cvMeshControls().removalDistCoeff()
|
||||
*targetCellSize(p));
|
||||
const scalar minSepDist =
|
||||
sqr
|
||||
(
|
||||
cvMeshControls().removalDistCoeff()
|
||||
*targetCellSize(p)
|
||||
);
|
||||
|
||||
// Reject the point if it is too close to another
|
||||
// surface point.
|
||||
|
||||
@ -366,6 +366,49 @@ inline bool Foam::conformalVoronoiMesh::isBoundaryDualFace
|
||||
}
|
||||
|
||||
|
||||
inline Foam::List<bool> Foam::conformalVoronoiMesh::dualFaceBoundaryPoints
|
||||
(
|
||||
const Delaunay::Finite_edges_iterator& eit
|
||||
) const
|
||||
{
|
||||
Cell_circulator ccStart = incident_cells(*eit);
|
||||
Cell_circulator cc1 = ccStart;
|
||||
Cell_circulator cc2 = cc1;
|
||||
|
||||
// Advance the second circulator so that it always stays on the next
|
||||
// cell around the edge;
|
||||
cc2++;
|
||||
|
||||
DynamicList<bool> tmpFaceBoundaryPoints;
|
||||
|
||||
do
|
||||
{
|
||||
label cc1I = cc1->cellIndex();
|
||||
|
||||
label cc2I = cc2->cellIndex();
|
||||
|
||||
if (cc1I != cc2I)
|
||||
{
|
||||
if (cc1->boundaryDualVertex())
|
||||
{
|
||||
tmpFaceBoundaryPoints.append(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFaceBoundaryPoints.append(false);
|
||||
}
|
||||
}
|
||||
|
||||
cc1++;
|
||||
|
||||
cc2++;
|
||||
|
||||
} while (cc1 != ccStart);
|
||||
|
||||
return tmpFaceBoundaryPoints;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::List<Foam::label> Foam::conformalVoronoiMesh::processorsAttached
|
||||
(
|
||||
const Delaunay::Finite_facets_iterator& fit
|
||||
|
||||
@ -291,6 +291,11 @@ Foam::cvControls::cvControls
|
||||
filteringDict.lookup("mergeClosenessCoeff")
|
||||
);
|
||||
|
||||
edgeMergeAngle_ = readScalar
|
||||
(
|
||||
filteringDict.lookup("edgeMergeAngle")
|
||||
);
|
||||
|
||||
continueFilteringOnBadInitialPolyMesh_ = Switch
|
||||
(
|
||||
filteringDict.lookupOrDefault<Switch>
|
||||
|
||||
@ -234,6 +234,11 @@ class cvControls
|
||||
// being merged, fraction of the local target cell size
|
||||
scalar mergeClosenessCoeff_;
|
||||
|
||||
//- If the angle between two dual edges that are connected by a single
|
||||
// point is less than this angle, then the edges will be merged into a
|
||||
// single edge.
|
||||
scalar edgeMergeAngle_;
|
||||
|
||||
//- If the mesh quality criteria cannot be satisfied, continue
|
||||
// with filtering anyway?
|
||||
Switch continueFilteringOnBadInitialPolyMesh_;
|
||||
@ -405,6 +410,9 @@ public:
|
||||
//- Return the mergeClosenessCoeff
|
||||
inline scalar mergeClosenessCoeff() const;
|
||||
|
||||
//- Return the edgeMergeAngle
|
||||
inline scalar edgeMergeAngle() const;
|
||||
|
||||
//- Return the continueFilteringOnBadInitialPolyMesh Switch
|
||||
inline Switch continueFilteringOnBadInitialPolyMesh() const;
|
||||
|
||||
|
||||
@ -166,6 +166,12 @@ inline Foam::scalar Foam::cvControls::mergeClosenessCoeff() const
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::cvControls::edgeMergeAngle() const
|
||||
{
|
||||
return edgeMergeAngle_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::Switch
|
||||
Foam::cvControls::continueFilteringOnBadInitialPolyMesh() const
|
||||
{
|
||||
|
||||
@ -3,30 +3,25 @@ cd ${0%/*} || exit 1 # run from this directory
|
||||
|
||||
set -x
|
||||
|
||||
if [ ! -e "Make/files" ] || [ ! -e "Make/options" ]
|
||||
if [ -n "$CGAL_ARCH_PATH" ]
|
||||
then
|
||||
mkdir -p Make
|
||||
echo
|
||||
echo "Compiling surfaceFeatureExtract with CGAL curvature support"
|
||||
echo
|
||||
|
||||
if [ -n "$CGAL_ARCH_PATH" ]
|
||||
then
|
||||
cp -r MakeWithCGAL/* Make
|
||||
|
||||
echo
|
||||
echo Compiling surfaceFeatureExtract with CGAL support for curvature
|
||||
echo
|
||||
|
||||
wmake
|
||||
else
|
||||
cp -r MakeWithoutCGAL/* Make
|
||||
|
||||
echo
|
||||
echo Compiling surfaceFeatureExtract without CGAL support for curvature
|
||||
echo
|
||||
|
||||
wmake
|
||||
fi
|
||||
wmake "ENABLE_CURVATURE=-DENABLE_CURVATURE \
|
||||
EXE_FROUNDING_MATH=-frounding-math \
|
||||
USE_F2C=-DCGAL_USE_F2C \
|
||||
CGAL_LIBDIR=-L$CGAL_ARCH_PATH/lib \
|
||||
LAPACK_LIB=-llapack \
|
||||
BLAS_LIB=-lblas \
|
||||
CGAL_LIB=-lCGAL"
|
||||
else
|
||||
echo surfaceFeatureExtract already has a Make folder
|
||||
echo
|
||||
echo "Compiling surfaceFeatureExtract without CGAL curvature support"
|
||||
echo
|
||||
|
||||
wmake
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class buildCGALPolyhedron Declaration
|
||||
Class buildCGALPolyhedron Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class buildCGALPolyhedron
|
||||
@ -80,18 +80,56 @@ public:
|
||||
// Constructors
|
||||
|
||||
//- Construct with reference to triSurface
|
||||
buildCGALPolyhedron(const triSurface& surf);
|
||||
explicit buildCGALPolyhedron(const triSurface& surf)
|
||||
:
|
||||
CGAL::Modifier_base<HalfedgeDS>(),
|
||||
surf_(surf)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
~buildCGALPolyhedron();
|
||||
~buildCGALPolyhedron(){}
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- operator() of this `modifier' called by delegate function of
|
||||
// Polyhedron
|
||||
void operator()(HalfedgeDS& hds);
|
||||
void operator()(HalfedgeDS& hds)
|
||||
{
|
||||
typedef HalfedgeDS::Traits Traits;
|
||||
typedef Traits::Point_3 Point;
|
||||
|
||||
// Postcondition: `hds' is a valid polyhedral surface.
|
||||
CGAL::Polyhedron_incremental_builder_3<HalfedgeDS> B(hds, false);
|
||||
|
||||
B.begin_surface
|
||||
(
|
||||
surf_.points().size(), // n points
|
||||
surf_.size(), // n facets
|
||||
2*surf_.edges().size() // n halfedges
|
||||
);
|
||||
|
||||
forAll(surf_.points(), pI)
|
||||
{
|
||||
const Foam::point& p = surf_.points()[pI];
|
||||
|
||||
B.add_vertex(Point(p.x(), p.y(), p.z()));
|
||||
}
|
||||
|
||||
forAll(surf_, fI)
|
||||
{
|
||||
B.begin_facet();
|
||||
|
||||
B.add_vertex_to_facet(surf_[fI][0]);
|
||||
B.add_vertex_to_facet(surf_[fI][1]);
|
||||
B.add_vertex_to_facet(surf_[fI][2]);
|
||||
|
||||
B.end_facet();
|
||||
}
|
||||
|
||||
B.end_surface();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,11 @@
|
||||
include $(GENERAL_RULES)/CGAL
|
||||
|
||||
EXE_INC = \
|
||||
${ENABLE_CURVATURE}\
|
||||
${EXE_FROUNDING_MATH} \
|
||||
${USE_F2C} \
|
||||
${CGAL_INC} \
|
||||
-ICGALPolyhedron \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/edgeMesh/lnInclude \
|
||||
@ -7,6 +14,11 @@ EXE_INC = \
|
||||
-I$(LIB_SRC)/sampling/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
$(CGAL_LIBS) \
|
||||
${CGAL_LIBDIR} \
|
||||
${LAPACK_LIB} \
|
||||
${BLAS_LIB} \
|
||||
${CGAL_LIB} \
|
||||
-lmeshTools \
|
||||
-ledgeMesh \
|
||||
-ltriSurface \
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
surfaceFeatureExtract.C
|
||||
CGALPolyhedron/buildCGALPolyhedron.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/surfaceFeatureExtract
|
||||
@ -1,29 +0,0 @@
|
||||
EXE_FROUNDING_MATH = -frounding-math
|
||||
EXE_NDEBUG = -DNDEBUG
|
||||
USE_F2C = -DCGAL_USE_F2C
|
||||
include $(GENERAL_RULES)/CGAL
|
||||
|
||||
EXE_INC = \
|
||||
-DENABLE_CURVATURE \
|
||||
${EXE_FROUNDING_MATH} \
|
||||
${EXE_NDEBUG} \
|
||||
${USE_F2C} \
|
||||
${CGAL_INC} \
|
||||
-ICGALPolyhedron \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/edgeMesh/lnInclude \
|
||||
-I$(LIB_SRC)/triSurface/lnInclude \
|
||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
$(CGAL_LIBS) \
|
||||
-L$(CGAL_ARCH_PATH)/lib \
|
||||
-llapack \
|
||||
-lblas \
|
||||
-lCGAL \
|
||||
-lmeshTools \
|
||||
-ledgeMesh \
|
||||
-ltriSurface \
|
||||
-lsampling
|
||||
@ -1,3 +0,0 @@
|
||||
surfaceFeatureExtract.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/surfaceFeatureExtract
|
||||
@ -1,13 +0,0 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/edgeMesh/lnInclude \
|
||||
-I$(LIB_SRC)/triSurface/lnInclude \
|
||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lmeshTools \
|
||||
-ledgeMesh \
|
||||
-ltriSurface \
|
||||
-lsampling
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,86 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: dev |
|
||||
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object surfaceFeatureExtractDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
surface1.stl
|
||||
{
|
||||
// extractFromFile || extractFromSurface
|
||||
extractionMethod extractFromFile;
|
||||
|
||||
extractFromFile
|
||||
{
|
||||
// Load from an existing feature edge file
|
||||
featureEdgeFile "constant/triSurface/featureEdges.nas";
|
||||
}
|
||||
|
||||
trimFeatures
|
||||
{
|
||||
// Remove features with fewer than the specified number of edges
|
||||
minElem 0;
|
||||
|
||||
// Remove features shorter than the specified cumulative length
|
||||
minLen 0.0;
|
||||
}
|
||||
|
||||
subsetFeatures
|
||||
{
|
||||
// Use a plane to select feature edges
|
||||
// (normal)(basePoint)
|
||||
plane (1 0 0)(0 0 0);
|
||||
|
||||
// Select feature edges using a box
|
||||
// (minPt)(maxPt)
|
||||
insideBox (0 0 0)(1 1 1);
|
||||
outsideBox (0 0 0)(1 1 1);
|
||||
|
||||
// Remove any non-manifold (open or > 2 connected faces) edges
|
||||
manifoldEdges no;
|
||||
}
|
||||
|
||||
// Output the curvature of the surface
|
||||
curvature no;
|
||||
|
||||
// Output the proximity of feature points and edges to each other
|
||||
featureProximity no;
|
||||
// The maximum search distance to use when looking for other feature
|
||||
// points and edges
|
||||
maxFeatureProximity 1;
|
||||
|
||||
// Out put the closeness of surface elements to other surface elements.
|
||||
closeness no;
|
||||
|
||||
// Write options
|
||||
writeVTK no;
|
||||
writeObj yes;
|
||||
writeFeatureEdgeMesh no;
|
||||
}
|
||||
|
||||
|
||||
surface2.nas
|
||||
{
|
||||
extractionMethod extractFromSurface;
|
||||
|
||||
extractFromSurface
|
||||
{
|
||||
// Mark edges whose adjacent surface normals are at an angle less
|
||||
// than includedAngle as features
|
||||
// - 0 : selects no edges
|
||||
// - 180: selects all edges
|
||||
includedAngle 120;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -2832,7 +2832,7 @@ Foam::pointIndexHit Foam::indexedOctree<Type>::findNearest
|
||||
) const
|
||||
{
|
||||
label nearestShapeI = -1;
|
||||
point nearestPoint;
|
||||
point nearestPoint = vector::zero;
|
||||
|
||||
if (nodes_.size())
|
||||
{
|
||||
@ -2847,10 +2847,6 @@ Foam::pointIndexHit Foam::indexedOctree<Type>::findNearest
|
||||
nearestPoint
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
nearestPoint = vector::zero;
|
||||
}
|
||||
|
||||
return pointIndexHit(nearestShapeI != -1, nearestPoint, nearestShapeI);
|
||||
}
|
||||
|
||||
@ -113,6 +113,17 @@ bool Foam::fileFormats::NASedgeFormat::read
|
||||
// discard groupID
|
||||
dynEdges.append(e);
|
||||
}
|
||||
else if (cmd == "PLOTEL")
|
||||
{
|
||||
edge e;
|
||||
|
||||
// label groupId = readLabel(IStringStream(line.substr(16,8))());
|
||||
e[0] = readLabel(IStringStream(line.substr(16,8))());
|
||||
e[1] = readLabel(IStringStream(line.substr(24,8))());
|
||||
|
||||
// discard groupID
|
||||
dynEdges.append(e);
|
||||
}
|
||||
else if (cmd == "GRID")
|
||||
{
|
||||
label index = readLabel(IStringStream(line.substr(8,8))());
|
||||
|
||||
@ -28,6 +28,7 @@ License
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
#include "ListOps.H"
|
||||
#include "EdgeMap.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -327,10 +328,7 @@ void Foam::edgeMesh::mergePoints(const scalar mergeDist)
|
||||
}
|
||||
|
||||
// Compact using a hashtable and commutative hash of edge.
|
||||
HashTable<label, edge, Hash<edge> > edgeToLabel
|
||||
(
|
||||
2*edges_.size()
|
||||
);
|
||||
EdgeMap<label> edgeToLabel(2*edges_.size());
|
||||
|
||||
label newEdgeI = 0;
|
||||
|
||||
@ -349,13 +347,7 @@ void Foam::edgeMesh::mergePoints(const scalar mergeDist)
|
||||
|
||||
edges_.setSize(newEdgeI);
|
||||
|
||||
for
|
||||
(
|
||||
HashTable<label, edge, Hash<edge> >::const_iterator iter =
|
||||
edgeToLabel.begin();
|
||||
iter != edgeToLabel.end();
|
||||
++iter
|
||||
)
|
||||
forAllConstIter(EdgeMap<label>, edgeToLabel, iter)
|
||||
{
|
||||
edges_[iter()] = iter.key();
|
||||
}
|
||||
@ -363,4 +355,35 @@ void Foam::edgeMesh::mergePoints(const scalar mergeDist)
|
||||
}
|
||||
|
||||
|
||||
void Foam::edgeMesh::mergeEdges()
|
||||
{
|
||||
EdgeMap<label> existingEdges(2*edges_.size());
|
||||
|
||||
label curEdgeI = 0;
|
||||
forAll(edges_, edgeI)
|
||||
{
|
||||
const edge& e = edges_[edgeI];
|
||||
|
||||
if (existingEdges.insert(e, curEdgeI))
|
||||
{
|
||||
curEdgeI++;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Merging duplicate edges: "
|
||||
<< edges_.size() - existingEdges.size()
|
||||
<< " edges will be deleted." << endl;
|
||||
}
|
||||
|
||||
edges_.setSize(existingEdges.size());
|
||||
|
||||
forAllConstIter(EdgeMap<label>, existingEdges, iter)
|
||||
{
|
||||
edges_[iter()] = iter.key();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -246,6 +246,9 @@ public:
|
||||
//- Merge common points (points within mergeDist)
|
||||
void mergePoints(const scalar mergeDist);
|
||||
|
||||
//- Merge similar edges
|
||||
void mergeEdges();
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
|
||||
@ -124,6 +124,7 @@ $(derivedFvPatchFields)/mappedFixedPushedInternalValue/mappedFixedPushedInternal
|
||||
$(derivedFvPatchFields)/mappedFixedValue/mappedFixedValueFvPatchFields.C
|
||||
$(derivedFvPatchFields)/mappedVelocityFluxFixedValue/mappedVelocityFluxFixedValueFvPatchField.C
|
||||
$(derivedFvPatchFields)/mappedFlowRate/mappedFlowRateFvPatchVectorField.C
|
||||
$(derivedFvPatchFields)/fixedMean/fixedMeanFvPatchFields.C
|
||||
$(derivedFvPatchFields)/fan/fanFvPatchFields.C
|
||||
$(derivedFvPatchFields)/fanPressure/fanPressureFvPatchScalarField.C
|
||||
$(derivedFvPatchFields)/buoyantPressure/buoyantPressureFvPatchScalarField.C
|
||||
|
||||
@ -0,0 +1,142 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fixedMeanFvPatchField.H"
|
||||
#include "volFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
fixedMeanFvPatchField<Type>::fixedMeanFvPatchField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
)
|
||||
:
|
||||
fixedValueFvPatchField<Type>(p, iF),
|
||||
meanValue_(pTraits<Type>::zero)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
fixedMeanFvPatchField<Type>::fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>& ptf,
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF,
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
|
||||
meanValue_(ptf.meanValue_)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
fixedMeanFvPatchField<Type>::fixedMeanFvPatchField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<Type, volMesh>& iF,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fixedValueFvPatchField<Type>(p, iF, dict),
|
||||
meanValue_(pTraits<Type>(dict.lookup("meanValue")))
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
fixedMeanFvPatchField<Type>::fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>& ptf
|
||||
)
|
||||
:
|
||||
fixedValueFvPatchField<Type>(ptf),
|
||||
meanValue_(ptf.meanValue_)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
fixedMeanFvPatchField<Type>::fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>& ptf,
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
)
|
||||
:
|
||||
fixedValueFvPatchField<Type>(ptf, iF),
|
||||
meanValue_(ptf.meanValue_)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void fixedMeanFvPatchField<Type>::updateCoeffs()
|
||||
{
|
||||
if (this->updated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Field<Type> newValues(this->patchInternalField());
|
||||
|
||||
Type meanValuePsi =
|
||||
gSum(this->patch().magSf()*newValues)
|
||||
/gSum(this->patch().magSf());
|
||||
|
||||
if (mag(meanValue_) > SMALL && mag(meanValuePsi)/mag(meanValue_) > 0.5)
|
||||
{
|
||||
newValues *= mag(meanValue_)/mag(meanValuePsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValues += (meanValue_ - meanValuePsi);
|
||||
}
|
||||
|
||||
this->operator==(newValues);
|
||||
|
||||
fixedValueFvPatchField<Type>::updateCoeffs();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void fixedMeanFvPatchField<Type>::write(Ostream& os) const
|
||||
{
|
||||
fvPatchField<Type>::write(os);
|
||||
os.writeKeyword("meanValue") << meanValue_ << token::END_STATEMENT << nl;
|
||||
this->writeEntry("value", os);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,158 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::fixedMeanFvPatchField
|
||||
|
||||
Description
|
||||
Extrapolates field to the patch using the near-cell values and adjusts
|
||||
the distribution to match the specified meanValue.
|
||||
|
||||
SourceFiles
|
||||
fixedMeanFvPatchField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fixedMeanFvPatchField_H
|
||||
#define fixedMeanFvPatchField_H
|
||||
|
||||
#include "fixedValueFvPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fixedMeanFvPatch Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class fixedMeanFvPatchField
|
||||
:
|
||||
public fixedValueFvPatchField<Type>
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- MeanValue value the field is adjusted to maintain
|
||||
Type meanValue_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("fixedMean");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from patch and internal field
|
||||
fixedMeanFvPatchField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct from patch, internal field and dictionary
|
||||
fixedMeanFvPatchField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&,
|
||||
const dictionary&
|
||||
);
|
||||
|
||||
//- Construct by mapping given fixedMeanFvPatchField
|
||||
// onto a new patch
|
||||
fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>&,
|
||||
const fvPatch&,
|
||||
const DimensionedField<Type, volMesh>&,
|
||||
const fvPatchFieldMapper&
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone
|
||||
virtual tmp<fvPatchField<Type> > clone() const
|
||||
{
|
||||
return tmp<fvPatchField<Type> >
|
||||
(
|
||||
new fixedMeanFvPatchField<Type>(*this)
|
||||
);
|
||||
}
|
||||
|
||||
//- Construct as copy setting internal field reference
|
||||
fixedMeanFvPatchField
|
||||
(
|
||||
const fixedMeanFvPatchField<Type>&,
|
||||
const DimensionedField<Type, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone setting internal field reference
|
||||
virtual tmp<fvPatchField<Type> > clone
|
||||
(
|
||||
const DimensionedField<Type, volMesh>& iF
|
||||
) const
|
||||
{
|
||||
return tmp<fvPatchField<Type> >
|
||||
(
|
||||
new fixedMeanFvPatchField<Type>(*this, iF)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
// Evaluation functions
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
virtual void updateCoeffs();
|
||||
|
||||
//- Write
|
||||
virtual void write(Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "fixedMeanFvPatchField.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fixedMeanFvPatchFields.H"
|
||||
#include "volMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
makePatchFields(fixedMean);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fixedMeanFvPatchFields_H
|
||||
#define fixedMeanFvPatchFields_H
|
||||
|
||||
#include "fixedMeanFvPatchField.H"
|
||||
#include "fieldTypes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makePatchTypeFieldTypedefs(fixedMean);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -23,67 +23,28 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "buildCGALPolyhedron.H"
|
||||
#ifndef fixedMeanFvPatchFieldsFwd_H
|
||||
#define fixedMeanFvPatchFieldsFwd_H
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
#include "fieldTypes.H"
|
||||
|
||||
Foam::buildCGALPolyhedron::buildCGALPolyhedron
|
||||
(
|
||||
const Foam::triSurface& surf
|
||||
)
|
||||
:
|
||||
CGAL::Modifier_base<HalfedgeDS>(),
|
||||
surf_(surf)
|
||||
{}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::buildCGALPolyhedron::~buildCGALPolyhedron()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::buildCGALPolyhedron::operator()
|
||||
(
|
||||
HalfedgeDS& hds
|
||||
)
|
||||
namespace Foam
|
||||
{
|
||||
typedef HalfedgeDS::Traits Traits;
|
||||
typedef Traits::Point_3 Point;
|
||||
|
||||
// Postcondition: `hds' is a valid polyhedral surface.
|
||||
CGAL::Polyhedron_incremental_builder_3<HalfedgeDS> B(hds, false);
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
B.begin_surface
|
||||
(
|
||||
surf_.points().size(), // n points
|
||||
surf_.size(), // n facets
|
||||
2*surf_.edges().size() // n halfedges
|
||||
);
|
||||
template<class Type> class fixedMeanFvPatchField;
|
||||
|
||||
forAll(surf_.points(), pI)
|
||||
{
|
||||
const Foam::point& p = surf_.points()[pI];
|
||||
makePatchTypeFieldTypedefs(fixedMean);
|
||||
|
||||
B.add_vertex(Point(p.x(), p.y(), p.z()));
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
forAll(surf_, fI)
|
||||
{
|
||||
B.begin_facet();
|
||||
} // End namespace Foam
|
||||
|
||||
B.add_vertex_to_facet(surf_[fI][0]);
|
||||
B.add_vertex_to_facet(surf_[fI][1]);
|
||||
B.add_vertex_to_facet(surf_[fI][2]);
|
||||
|
||||
B.end_facet();
|
||||
}
|
||||
|
||||
B.end_surface();
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -33,11 +33,15 @@ License
|
||||
#include "OFstream.H"
|
||||
#include "IFstream.H"
|
||||
#include "unitConversion.H"
|
||||
#include "EdgeMap.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(Foam::surfaceFeatures, 0);
|
||||
|
||||
const Foam::scalar Foam::surfaceFeatures::parallelTolerance =
|
||||
sin(degToRad(1.0));
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -170,7 +174,10 @@ void Foam::surfaceFeatures::setFromStatus(const List<edgeStatus>& edgeStat)
|
||||
|
||||
|
||||
//construct feature points where more than 2 feature edges meet
|
||||
void Foam::surfaceFeatures::calcFeatPoints(const List<edgeStatus>& edgeStat)
|
||||
void Foam::surfaceFeatures::calcFeatPoints
|
||||
(
|
||||
const List<edgeStatus>& edgeStat
|
||||
)
|
||||
{
|
||||
DynamicList<label> featurePoints(surf_.nPoints()/1000);
|
||||
|
||||
@ -200,6 +207,60 @@ void Foam::surfaceFeatures::calcFeatPoints(const List<edgeStatus>& edgeStat)
|
||||
}
|
||||
|
||||
|
||||
void Foam::surfaceFeatures::classifyFeatureAngles
|
||||
(
|
||||
const labelListList& edgeFaces,
|
||||
List<edgeStatus>& edgeStat,
|
||||
const scalar minCos
|
||||
) const
|
||||
{
|
||||
const vectorField& faceNormals = surf_.faceNormals();
|
||||
const pointField& points = surf_.points();
|
||||
|
||||
forAll(edgeFaces, edgeI)
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
if (eFaces.size() != 2)
|
||||
{
|
||||
// Non-manifold. What to do here? Is region edge? external edge?
|
||||
edgeStat[edgeI] = REGION;
|
||||
}
|
||||
else
|
||||
{
|
||||
label face0 = eFaces[0];
|
||||
label face1 = eFaces[1];
|
||||
|
||||
if (surf_[face0].region() != surf_[face1].region())
|
||||
{
|
||||
edgeStat[edgeI] = REGION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((faceNormals[face0] & faceNormals[face1]) < minCos)
|
||||
{
|
||||
|
||||
// Check if convex or concave by looking at angle
|
||||
// between face centres and normal
|
||||
vector f0Tof1 =
|
||||
surf_[face1].centre(points)
|
||||
- surf_[face0].centre(points);
|
||||
|
||||
if ((f0Tof1 & faceNormals[face0]) > 0.0)
|
||||
{
|
||||
edgeStat[edgeI] = INTERNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeStat[edgeI] = EXTERNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns next feature edge connected to pointI with correct value.
|
||||
Foam::label Foam::surfaceFeatures::nextFeatEdge
|
||||
(
|
||||
@ -436,6 +497,80 @@ Foam::surfaceFeatures::surfaceFeatures
|
||||
}
|
||||
|
||||
|
||||
Foam::surfaceFeatures::surfaceFeatures
|
||||
(
|
||||
const triSurface& surf,
|
||||
const pointField& points,
|
||||
const edgeList& edges,
|
||||
const scalar mergeTol
|
||||
)
|
||||
:
|
||||
surf_(surf),
|
||||
featurePoints_(0),
|
||||
featureEdges_(0),
|
||||
externalStart_(0),
|
||||
internalStart_(0)
|
||||
{
|
||||
// Match edge mesh edges with the triSurface edges
|
||||
|
||||
const labelListList& surfEdgeFaces = surf_.edgeFaces();
|
||||
const edgeList& surfEdges = surf_.edges();
|
||||
|
||||
scalar mergeTolSqr = sqr(mergeTol);
|
||||
|
||||
EdgeMap<label> dynFeatEdges(2*edges.size());
|
||||
DynamicList<labelList> dynFeatureEdgeFaces(edges.size());
|
||||
|
||||
labelList edgeLabel;
|
||||
|
||||
nearestFeatEdge
|
||||
(
|
||||
edges,
|
||||
points,
|
||||
mergeTolSqr,
|
||||
edgeLabel // label of surface edge or -1
|
||||
);
|
||||
|
||||
label count = 0;
|
||||
forAll(edgeLabel, sEdgeI)
|
||||
{
|
||||
const label sEdge = edgeLabel[sEdgeI];
|
||||
|
||||
if (sEdge == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dynFeatEdges.insert(surfEdges[sEdge], count++);
|
||||
dynFeatureEdgeFaces.append(surfEdgeFaces[sEdge]);
|
||||
}
|
||||
|
||||
// Find whether an edge is external or internal
|
||||
List<edgeStatus> edgeStat(dynFeatEdges.size(), NONE);
|
||||
|
||||
classifyFeatureAngles(dynFeatureEdgeFaces, edgeStat, GREAT);
|
||||
|
||||
// Transfer the edge status to a list encompassing all edges in the surface
|
||||
// so that calcFeatPoints can be used.
|
||||
List<edgeStatus> allEdgeStat(surf_.nEdges(), NONE);
|
||||
|
||||
forAll(allEdgeStat, eI)
|
||||
{
|
||||
EdgeMap<label>::const_iterator iter = dynFeatEdges.find(surfEdges[eI]);
|
||||
|
||||
if (iter != dynFeatEdges.end())
|
||||
{
|
||||
allEdgeStat[eI] = edgeStat[iter()];
|
||||
}
|
||||
}
|
||||
|
||||
edgeStat.clear();
|
||||
dynFeatEdges.clear();
|
||||
|
||||
setFromStatus(allEdgeStat);
|
||||
}
|
||||
|
||||
|
||||
//- Construct as copy
|
||||
Foam::surfaceFeatures::surfaceFeatures(const surfaceFeatures& sf)
|
||||
:
|
||||
@ -496,54 +631,10 @@ void Foam::surfaceFeatures::findFeatures(const scalar includedAngle)
|
||||
{
|
||||
scalar minCos = Foam::cos(degToRad(180.0 - includedAngle));
|
||||
|
||||
const labelListList& edgeFaces = surf_.edgeFaces();
|
||||
const vectorField& faceNormals = surf_.faceNormals();
|
||||
const pointField& points = surf_.points();
|
||||
|
||||
// Per edge whether is feature edge.
|
||||
List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
|
||||
|
||||
forAll(edgeFaces, edgeI)
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
if (eFaces.size() != 2)
|
||||
{
|
||||
// Non-manifold. What to do here? Is region edge? external edge?
|
||||
edgeStat[edgeI] = REGION;
|
||||
}
|
||||
else
|
||||
{
|
||||
label face0 = eFaces[0];
|
||||
label face1 = eFaces[1];
|
||||
|
||||
if (surf_[face0].region() != surf_[face1].region())
|
||||
{
|
||||
edgeStat[edgeI] = REGION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((faceNormals[face0] & faceNormals[face1]) < minCos)
|
||||
{
|
||||
|
||||
// Check if convex or concave by looking at angle
|
||||
// between face centres and normal
|
||||
vector f0Tof1 =
|
||||
surf_[face1].centre(points)
|
||||
- surf_[face0].centre(points);
|
||||
|
||||
if ((f0Tof1 & faceNormals[face0]) > 0.0)
|
||||
{
|
||||
edgeStat[edgeI] = INTERNAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
edgeStat[edgeI] = EXTERNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
classifyFeatureAngles(surf_.edgeFaces(), edgeStat, minCos);
|
||||
|
||||
setFromStatus(edgeStat);
|
||||
}
|
||||
@ -1147,6 +1238,9 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
||||
|
||||
const pointField& localPoints = surf_.localPoints();
|
||||
|
||||
treeBoundBox searchDomain(localPoints);
|
||||
searchDomain.inflate(0.1);
|
||||
|
||||
indexedOctree<treeDataEdge> ppTree
|
||||
(
|
||||
treeDataEdge
|
||||
@ -1156,7 +1250,7 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
||||
localPoints,
|
||||
selectedEdges
|
||||
), // all information needed to do geometric checks
|
||||
treeBoundBox(localPoints), // overall search domain
|
||||
searchDomain, // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
@ -1216,6 +1310,8 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
||||
pointOnEdge.setSize(selectedSampleEdges.size());
|
||||
pointOnFeature.setSize(selectedSampleEdges.size());
|
||||
|
||||
treeBoundBox searchDomain(surf_.localPoints());
|
||||
|
||||
indexedOctree<treeDataEdge> ppTree
|
||||
(
|
||||
treeDataEdge
|
||||
@ -1224,11 +1320,11 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
||||
surf_.edges(),
|
||||
surf_.localPoints(),
|
||||
selectedEdges
|
||||
), // all information needed to do geometric checks
|
||||
treeBoundBox(surf_.localPoints()), // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
), // all information needed to do geometric checks
|
||||
searchDomain, // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
);
|
||||
|
||||
forAll(selectedSampleEdges, i)
|
||||
@ -1262,6 +1358,67 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
||||
}
|
||||
|
||||
|
||||
void Foam::surfaceFeatures::nearestFeatEdge
|
||||
(
|
||||
const edgeList& edges,
|
||||
const pointField& points,
|
||||
scalar searchSpanSqr, // Search span
|
||||
labelList& edgeLabel
|
||||
) const
|
||||
{
|
||||
edgeLabel = labelList(surf_.nEdges(), -1);
|
||||
|
||||
treeBoundBox searchDomain(points);
|
||||
searchDomain.inflate(0.1);
|
||||
|
||||
indexedOctree<treeDataEdge> ppTree
|
||||
(
|
||||
treeDataEdge
|
||||
(
|
||||
false,
|
||||
edges,
|
||||
points,
|
||||
identity(edges.size())
|
||||
), // all information needed to do geometric checks
|
||||
searchDomain, // overall search domain
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
);
|
||||
|
||||
const edgeList& surfEdges = surf_.edges();
|
||||
const pointField& surfLocalPoints = surf_.localPoints();
|
||||
|
||||
forAll(surfEdges, edgeI)
|
||||
{
|
||||
const edge& sample = surfEdges[edgeI];
|
||||
|
||||
const point& startPoint = surfLocalPoints[sample.start()];
|
||||
const point& midPoint = sample.centre(surfLocalPoints);
|
||||
|
||||
pointIndexHit infoMid = ppTree.findNearest
|
||||
(
|
||||
midPoint,
|
||||
searchSpanSqr
|
||||
);
|
||||
|
||||
if (infoMid.hit())
|
||||
{
|
||||
const vector surfEdgeDir = midPoint - startPoint;
|
||||
|
||||
const edge& featEdge = edges[infoMid.index()];
|
||||
const vector featEdgeDir = featEdge.vec(points);
|
||||
|
||||
// Check that the edges are nearly parallel
|
||||
if (mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
|
||||
{
|
||||
edgeLabel[edgeI] = edgeI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::surfaceFeatures::operator=(const surfaceFeatures& rhs)
|
||||
|
||||
@ -95,6 +95,11 @@ private:
|
||||
{}
|
||||
};
|
||||
|
||||
// Static data
|
||||
|
||||
//- Tolerance for determining whether two vectors are parallel
|
||||
static const scalar parallelTolerance;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
@ -130,6 +135,14 @@ private:
|
||||
//- Construct feature points where more than 2 feature edges meet
|
||||
void calcFeatPoints(const List<edgeStatus>&);
|
||||
|
||||
//- Classify the angles of the feature edges
|
||||
void classifyFeatureAngles
|
||||
(
|
||||
const labelListList& edgeFaces,
|
||||
List<edgeStatus>& edgeStat,
|
||||
const scalar minCos
|
||||
) const;
|
||||
|
||||
//- Choose next unset feature edge.
|
||||
label nextFeatEdge
|
||||
(
|
||||
@ -186,6 +199,15 @@ public:
|
||||
//- Construct from file
|
||||
surfaceFeatures(const triSurface&, const fileName& fName);
|
||||
|
||||
//- Construct from pointField and edgeList (edgeMesh)
|
||||
surfaceFeatures
|
||||
(
|
||||
const triSurface&,
|
||||
const pointField& points,
|
||||
const edgeList& edges,
|
||||
const scalar mergeTol = 1e-6
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
surfaceFeatures(const surfaceFeatures&);
|
||||
|
||||
@ -327,9 +349,8 @@ public:
|
||||
pointField& edgePoint
|
||||
) const;
|
||||
|
||||
|
||||
//- Find nearest surface edge (out of selectedEdges) for each
|
||||
// sample edge.
|
||||
// sample edge.
|
||||
// Sets:
|
||||
// - edgeLabel : label of surface edge.
|
||||
// - pointOnEdge : exact position of nearest point on edge.
|
||||
@ -347,6 +368,16 @@ public:
|
||||
pointField& pointOnFeature // point on sample edge
|
||||
) const;
|
||||
|
||||
//- Find nearest feature edge to each surface edge. Uses the
|
||||
// mid-point of the surface edges.
|
||||
void nearestFeatEdge
|
||||
(
|
||||
const edgeList& edges,
|
||||
const pointField& points,
|
||||
scalar searchSpanSqr,
|
||||
labelList& edgeLabel
|
||||
) const;
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
|
||||
Reference in New Issue
Block a user