mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: autoHexMesh: parallel consistency, fix curvature refinement
This commit is contained in:
@ -910,6 +910,7 @@ void Foam::autoSnapDriver::detectNearSurfaces
|
|||||||
Info<< "Detecting near surfaces ..." << endl;
|
Info<< "Detecting near surfaces ..." << endl;
|
||||||
|
|
||||||
const pointField& localPoints = pp.localPoints();
|
const pointField& localPoints = pp.localPoints();
|
||||||
|
const labelList& meshPoints = pp.meshPoints();
|
||||||
const refinementSurfaces& surfaces = meshRefiner_.surfaces();
|
const refinementSurfaces& surfaces = meshRefiner_.surfaces();
|
||||||
const fvMesh& mesh = meshRefiner_.mesh();
|
const fvMesh& mesh = meshRefiner_.mesh();
|
||||||
|
|
||||||
@ -1220,6 +1221,7 @@ void Foam::autoSnapDriver::detectNearSurfaces
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackedBoolList isMasterPoint(syncTools::getMasterPoints(mesh));
|
||||||
label nOverride = 0;
|
label nOverride = 0;
|
||||||
|
|
||||||
// 1. All points to non-interface surfaces
|
// 1. All points to non-interface surfaces
|
||||||
@ -1332,7 +1334,7 @@ void Foam::autoSnapDriver::detectNearSurfaces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override)
|
if (override && isMasterPoint[meshPoints[pointI]])
|
||||||
{
|
{
|
||||||
nOverride++;
|
nOverride++;
|
||||||
}
|
}
|
||||||
@ -1399,8 +1401,6 @@ void Foam::autoSnapDriver::detectNearSurfaces
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
label nOverride = 0;
|
|
||||||
|
|
||||||
forAll(hit1, i)
|
forAll(hit1, i)
|
||||||
{
|
{
|
||||||
label pointI = zonePointIndices[i];
|
label pointI = zonePointIndices[i];
|
||||||
@ -1472,7 +1472,7 @@ void Foam::autoSnapDriver::detectNearSurfaces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override)
|
if (override && isMasterPoint[meshPoints[pointI]])
|
||||||
{
|
{
|
||||||
nOverride++;
|
nOverride++;
|
||||||
}
|
}
|
||||||
@ -1690,7 +1690,13 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurface
|
|||||||
scalarField magDisp(mag(patchDisp));
|
scalarField magDisp(mag(patchDisp));
|
||||||
|
|
||||||
Info<< "Wanted displacement : average:"
|
Info<< "Wanted displacement : average:"
|
||||||
<< gSum(magDisp)/returnReduce(patchDisp.size(), sumOp<label>())
|
<< meshRefinement::gAverage
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
syncTools::getMasterPoints(mesh),
|
||||||
|
pp.meshPoints(),
|
||||||
|
magDisp
|
||||||
|
)
|
||||||
<< " min:" << gMin(magDisp)
|
<< " min:" << gMin(magDisp)
|
||||||
<< " max:" << gMax(magDisp) << endl;
|
<< " max:" << gMax(magDisp) << endl;
|
||||||
}
|
}
|
||||||
@ -2548,25 +2554,30 @@ void Foam::autoSnapDriver::doSnap
|
|||||||
adaptPatchIDs
|
adaptPatchIDs
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
indirectPrimitivePatch& pp = ppPtr();
|
|
||||||
|
|
||||||
// Distance to attract to nearest feature on surface
|
// Distance to attract to nearest feature on surface
|
||||||
const scalarField snapDist(calcSnapDistance(mesh, snapParams, pp));
|
const scalarField snapDist(calcSnapDistance(mesh, snapParams, ppPtr()));
|
||||||
|
|
||||||
|
|
||||||
// Construct iterative mesh mover.
|
// Construct iterative mesh mover.
|
||||||
Info<< "Constructing mesh displacer ..." << endl;
|
Info<< "Constructing mesh displacer ..." << endl;
|
||||||
Info<< "Using mesh parameters " << motionDict << nl << endl;
|
Info<< "Using mesh parameters " << motionDict << nl << endl;
|
||||||
|
|
||||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
autoPtr<motionSmoother> meshMoverPtr
|
||||||
|
|
||||||
motionSmoother meshMover
|
|
||||||
(
|
(
|
||||||
mesh,
|
new motionSmoother
|
||||||
pp,
|
(
|
||||||
adaptPatchIDs,
|
mesh,
|
||||||
meshRefinement::makeDisplacementField(pMesh, adaptPatchIDs),
|
ppPtr(),
|
||||||
motionDict
|
adaptPatchIDs,
|
||||||
|
meshRefinement::makeDisplacementField
|
||||||
|
(
|
||||||
|
pointMesh::New(mesh),
|
||||||
|
adaptPatchIDs
|
||||||
|
),
|
||||||
|
motionDict
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -2595,16 +2606,95 @@ void Foam::autoSnapDriver::doSnap
|
|||||||
snapParams,
|
snapParams,
|
||||||
nInitErrors,
|
nInitErrors,
|
||||||
baffles,
|
baffles,
|
||||||
meshMover
|
meshMoverPtr()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//- Only if in feature attraction mode:
|
||||||
|
// Nearest feature
|
||||||
|
vectorField patchAttraction;
|
||||||
|
// Constraints at feature
|
||||||
|
List<pointConstraint> patchConstraints;
|
||||||
|
|
||||||
|
|
||||||
for (label iter = 0; iter < nFeatIter; iter++)
|
for (label iter = 0; iter < nFeatIter; iter++)
|
||||||
{
|
{
|
||||||
Info<< nl
|
Info<< nl
|
||||||
<< "Morph iteration " << iter << nl
|
<< "Morph iteration " << iter << nl
|
||||||
<< "-----------------" << endl;
|
<< "-----------------" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
//if (iter > 0 && iter == nFeatIter/2)
|
||||||
|
//{
|
||||||
|
// Info<< "Splitting diagonal attractions" << endl;
|
||||||
|
// const labelList& bFaces = ppPtr().addressing();
|
||||||
|
//
|
||||||
|
// DynamicList<label> splitFaces(bFaces.size());
|
||||||
|
// DynamicList<labelPair> splits(bFaces.size());
|
||||||
|
//
|
||||||
|
// forAll(bFaces, faceI)
|
||||||
|
// {
|
||||||
|
// const labelPair split
|
||||||
|
// (
|
||||||
|
// findDiagonalAttraction
|
||||||
|
// (
|
||||||
|
// ppPtr(),
|
||||||
|
// patchAttraction,
|
||||||
|
// patchConstraints,
|
||||||
|
// faceI
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// if (split != labelPair(-1, -1))
|
||||||
|
// {
|
||||||
|
// splitFaces.append(bFaces[faceI]);
|
||||||
|
// splits.append(split);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// autoPtr<mapPolyMesh> mapPtr = meshRefiner_.splitFaces
|
||||||
|
// (
|
||||||
|
// splitFaces,
|
||||||
|
// splits
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// const labelList& faceMap = mapPtr().faceMap();
|
||||||
|
// meshRefinement::updateList(faceMap, -1, duplicateFace);
|
||||||
|
// const labelList& reverseFaceMap = mapPtr().reverseFaceMap();
|
||||||
|
// forAll(baffles, i)
|
||||||
|
// {
|
||||||
|
// labelPair& baffle = baffles[i];
|
||||||
|
// baffle.first() = reverseFaceMap[baffle.first()];
|
||||||
|
// baffle.second() = reverseFaceMap[baffle.second()];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// meshMoverPtr.clear();
|
||||||
|
// ppPtr.clear();
|
||||||
|
//
|
||||||
|
// ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
|
||||||
|
// meshMoverPtr.reset
|
||||||
|
// (
|
||||||
|
// new motionSmoother
|
||||||
|
// (
|
||||||
|
// mesh,
|
||||||
|
// ppPtr(),
|
||||||
|
// adaptPatchIDs,
|
||||||
|
// meshRefinement::makeDisplacementField
|
||||||
|
// (
|
||||||
|
// pointMesh::New(mesh),
|
||||||
|
// adaptPatchIDs
|
||||||
|
// ),
|
||||||
|
// motionDict
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
indirectPrimitivePatch& pp = ppPtr();
|
||||||
|
motionSmoother& meshMover = meshMoverPtr();
|
||||||
|
|
||||||
|
|
||||||
// Calculate displacement at every patch point. Insert into
|
// Calculate displacement at every patch point. Insert into
|
||||||
// meshMover.
|
// meshMover.
|
||||||
// Calculate displacement at every patch point
|
// Calculate displacement at every patch point
|
||||||
@ -2652,7 +2742,9 @@ void Foam::autoSnapDriver::doSnap
|
|||||||
scalar(iter+1)/nFeatIter,
|
scalar(iter+1)/nFeatIter,
|
||||||
snapDist,
|
snapDist,
|
||||||
disp,
|
disp,
|
||||||
meshMover
|
meshMover,
|
||||||
|
patchAttraction,
|
||||||
|
patchConstraints
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -125,7 +125,9 @@ class autoSnapDriver
|
|||||||
|
|
||||||
void smoothAndConstrain
|
void smoothAndConstrain
|
||||||
(
|
(
|
||||||
|
const PackedBoolList& isMasterEdge,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
|
const labelList& meshEdges,
|
||||||
const List<pointConstraint>& constraints,
|
const List<pointConstraint>& constraints,
|
||||||
vectorField& disp
|
vectorField& disp
|
||||||
) const;
|
) const;
|
||||||
@ -196,6 +198,16 @@ class autoSnapDriver
|
|||||||
List<pointConstraint>& patchConstraints
|
List<pointConstraint>& patchConstraints
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Detect any diagonal attraction. Returns indices in face
|
||||||
|
// or (-1, -1) if none
|
||||||
|
labelPair findDiagonalAttraction
|
||||||
|
(
|
||||||
|
const indirectPrimitivePatch& pp,
|
||||||
|
const vectorField& patchAttraction,
|
||||||
|
const List<pointConstraint>& patchConstraints,
|
||||||
|
const label faceI
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Return hit if on multiple points
|
//- Return hit if on multiple points
|
||||||
pointIndexHit findMultiPatchPoint
|
pointIndexHit findMultiPatchPoint
|
||||||
(
|
(
|
||||||
@ -371,7 +383,9 @@ class autoSnapDriver
|
|||||||
const scalar featureAttract,
|
const scalar featureAttract,
|
||||||
const scalarField& snapDist,
|
const scalarField& snapDist,
|
||||||
const vectorField& nearestDisp,
|
const vectorField& nearestDisp,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover,
|
||||||
|
vectorField& patchAttraction,
|
||||||
|
List<pointConstraint>& patchConstraints
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -38,50 +38,18 @@ License
|
|||||||
#include "treeDataPoint.H"
|
#include "treeDataPoint.H"
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
#include "snapParameters.H"
|
#include "snapParameters.H"
|
||||||
|
#include "PatchTools.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
class listTransform
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
void operator()
|
|
||||||
(
|
|
||||||
const vectorTensorTransform& vt,
|
|
||||||
const bool forward,
|
|
||||||
List<List<point> >& fld
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const tensor T
|
|
||||||
(
|
|
||||||
forward
|
|
||||||
? vt.R()
|
|
||||||
: vt.R().T()
|
|
||||||
);
|
|
||||||
|
|
||||||
forAll(fld, i)
|
|
||||||
{
|
|
||||||
List<point>& elems = fld[i];
|
|
||||||
forAll(elems, elemI)
|
|
||||||
{
|
|
||||||
elems[elemI] = transform(T, elems[elemI]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class listPlusEqOp
|
class listPlusEqOp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void operator()
|
void operator()(List<T>& x, const List<T>& y) const
|
||||||
(
|
|
||||||
List<T>& x,
|
|
||||||
const List<T>& y
|
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
label sz = x.size();
|
label sz = x.size();
|
||||||
x.setSize(sz+y.size());
|
x.setSize(sz+y.size());
|
||||||
@ -159,7 +127,9 @@ bool Foam::autoSnapDriver::isFeaturePoint
|
|||||||
|
|
||||||
void Foam::autoSnapDriver::smoothAndConstrain
|
void Foam::autoSnapDriver::smoothAndConstrain
|
||||||
(
|
(
|
||||||
|
const PackedBoolList& isMasterEdge,
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
|
const labelList& meshEdges,
|
||||||
const List<pointConstraint>& constraints,
|
const List<pointConstraint>& constraints,
|
||||||
vectorField& disp
|
vectorField& disp
|
||||||
) const
|
) const
|
||||||
@ -197,11 +167,16 @@ void Foam::autoSnapDriver::smoothAndConstrain
|
|||||||
{
|
{
|
||||||
forAll(pEdges, i)
|
forAll(pEdges, i)
|
||||||
{
|
{
|
||||||
label nbrPointI = edges[pEdges[i]].otherVertex(pointI);
|
label edgeI = pEdges[i];
|
||||||
if (constraints[nbrPointI].first() >= nConstraints)
|
|
||||||
|
if (isMasterEdge[meshEdges[edgeI]])
|
||||||
{
|
{
|
||||||
dispSum[pointI] += disp[nbrPointI];
|
label nbrPointI = edges[pEdges[i]].otherVertex(pointI);
|
||||||
dispCount[pointI]++;
|
if (constraints[nbrPointI].first() >= nConstraints)
|
||||||
|
{
|
||||||
|
dispSum[pointI] += disp[nbrPointI];
|
||||||
|
dispCount[pointI]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,6 +539,9 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
{
|
{
|
||||||
const fvMesh& mesh = meshRefiner_.mesh();
|
const fvMesh& mesh = meshRefiner_.mesh();
|
||||||
|
|
||||||
|
const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
|
||||||
|
|
||||||
|
|
||||||
// For now just get all surrounding face data. Expensive - should just
|
// For now just get all surrounding face data. Expensive - should just
|
||||||
// store and sync data on coupled points only
|
// store and sync data on coupled points only
|
||||||
// (see e.g PatchToolsNormals.C)
|
// (see e.g PatchToolsNormals.C)
|
||||||
@ -583,7 +561,7 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
forAll(pFaces, i)
|
forAll(pFaces, i)
|
||||||
{
|
{
|
||||||
label faceI = pFaces[i];
|
label faceI = pFaces[i];
|
||||||
if (faceSurfaceGlobalRegion[faceI] != -1)
|
if (isMasterFace[faceI] && faceSurfaceGlobalRegion[faceI] != -1)
|
||||||
{
|
{
|
||||||
nFaces++;
|
nFaces++;
|
||||||
}
|
}
|
||||||
@ -605,7 +583,7 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
label faceI = pFaces[i];
|
label faceI = pFaces[i];
|
||||||
label globalRegionI = faceSurfaceGlobalRegion[faceI];
|
label globalRegionI = faceSurfaceGlobalRegion[faceI];
|
||||||
|
|
||||||
if (globalRegionI != -1)
|
if (isMasterFace[faceI] && globalRegionI != -1)
|
||||||
{
|
{
|
||||||
pNormals[nFaces] = faceSurfaceNormal[faceI];
|
pNormals[nFaces] = faceSurfaceNormal[faceI];
|
||||||
pDisp[nFaces] = faceDisp[faceI];
|
pDisp[nFaces] = faceDisp[faceI];
|
||||||
@ -694,7 +672,7 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
pointFaceSurfNormals,
|
pointFaceSurfNormals,
|
||||||
listPlusEqOp<point>(),
|
listPlusEqOp<point>(),
|
||||||
List<point>(),
|
List<point>(),
|
||||||
listTransform()
|
mapDistribute::transform()
|
||||||
);
|
);
|
||||||
syncTools::syncPointList
|
syncTools::syncPointList
|
||||||
(
|
(
|
||||||
@ -703,7 +681,7 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
pointFaceDisp,
|
pointFaceDisp,
|
||||||
listPlusEqOp<point>(),
|
listPlusEqOp<point>(),
|
||||||
List<point>(),
|
List<point>(),
|
||||||
listTransform()
|
mapDistribute::transform()
|
||||||
);
|
);
|
||||||
syncTools::syncPointList
|
syncTools::syncPointList
|
||||||
(
|
(
|
||||||
@ -712,7 +690,7 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
pointFaceCentres,
|
pointFaceCentres,
|
||||||
listPlusEqOp<point>(),
|
listPlusEqOp<point>(),
|
||||||
List<point>(),
|
List<point>(),
|
||||||
listTransform()
|
mapDistribute::transformPosition()
|
||||||
);
|
);
|
||||||
syncTools::syncPointList
|
syncTools::syncPointList
|
||||||
(
|
(
|
||||||
@ -722,6 +700,25 @@ void Foam::autoSnapDriver::calcNearestFacePointProperties
|
|||||||
listPlusEqOp<label>(),
|
listPlusEqOp<label>(),
|
||||||
List<label>()
|
List<label>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Sort the data according to the face centres. This is only so we get
|
||||||
|
// consistent behaviour serial and parallel.
|
||||||
|
labelList visitOrder;
|
||||||
|
forAll(pointFaceDisp, pointI)
|
||||||
|
{
|
||||||
|
List<point>& pNormals = pointFaceSurfNormals[pointI];
|
||||||
|
List<point>& pDisp = pointFaceDisp[pointI];
|
||||||
|
List<point>& pFc = pointFaceCentres[pointI];
|
||||||
|
labelList& pFid = pointFacePatchID[pointI];
|
||||||
|
|
||||||
|
sortedOrder(mag(pFc)(), visitOrder);
|
||||||
|
|
||||||
|
pNormals = List<point>(pNormals, visitOrder);
|
||||||
|
pDisp = List<point>(pDisp, visitOrder);
|
||||||
|
pFc = List<point>(pFc, visitOrder);
|
||||||
|
pFid = UIndirectList<label>(pFid, visitOrder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1360,6 +1357,70 @@ void Foam::autoSnapDriver::stringFeatureEdges
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If only two attractions and across face return the face indices
|
||||||
|
Foam::labelPair Foam::autoSnapDriver::findDiagonalAttraction
|
||||||
|
(
|
||||||
|
const indirectPrimitivePatch& pp,
|
||||||
|
const vectorField& patchAttraction,
|
||||||
|
const List<pointConstraint>& patchConstraints,
|
||||||
|
const label faceI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const face& f = pp.localFaces()[faceI];
|
||||||
|
// For now just detect any attraction. Improve this to look at
|
||||||
|
// actual attraction position and orientation
|
||||||
|
|
||||||
|
labelPair attractIndices(-1, -1);
|
||||||
|
|
||||||
|
if (f.size() >= 4)
|
||||||
|
{
|
||||||
|
forAll(f, fp)
|
||||||
|
{
|
||||||
|
label pointI = f[fp];
|
||||||
|
if (patchConstraints[pointI].first() >= 2)
|
||||||
|
{
|
||||||
|
// Attract to feature edge or point
|
||||||
|
if (attractIndices[0] == -1)
|
||||||
|
{
|
||||||
|
// First attraction. Store
|
||||||
|
attractIndices[0] = fp;
|
||||||
|
}
|
||||||
|
else if (attractIndices[1] == -1)
|
||||||
|
{
|
||||||
|
// Second attraction. Check if not consecutive to first
|
||||||
|
// attraction
|
||||||
|
label fp0 = attractIndices[0];
|
||||||
|
if (f.fcIndex(fp0) == fp || f.fcIndex(fp) == fp0)
|
||||||
|
{
|
||||||
|
// Consecutive. Skip.
|
||||||
|
attractIndices = labelPair(-1, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attractIndices[1] = fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// More than two attractions. Skip.
|
||||||
|
attractIndices = labelPair(-1, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (attractIndices[1] == -1)
|
||||||
|
{
|
||||||
|
// Found only one attraction. Skip.
|
||||||
|
attractIndices = labelPair(-1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attractIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::pointIndexHit Foam::autoSnapDriver::findNearFeatureEdge
|
Foam::pointIndexHit Foam::autoSnapDriver::findNearFeatureEdge
|
||||||
(
|
(
|
||||||
const indirectPrimitivePatch& pp,
|
const indirectPrimitivePatch& pp,
|
||||||
@ -1929,7 +1990,7 @@ void Foam::autoSnapDriver::featureAttractionUsingFeatureEdges
|
|||||||
edgeFaceNormals,
|
edgeFaceNormals,
|
||||||
listPlusEqOp<point>(),
|
listPlusEqOp<point>(),
|
||||||
List<point>(),
|
List<point>(),
|
||||||
listTransform()
|
mapDistribute::transform()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2778,7 +2839,9 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
const scalar featureAttract,
|
const scalar featureAttract,
|
||||||
const scalarField& snapDist,
|
const scalarField& snapDist,
|
||||||
const vectorField& nearestDisp,
|
const vectorField& nearestDisp,
|
||||||
motionSmoother& meshMover
|
motionSmoother& meshMover,
|
||||||
|
vectorField& patchAttraction,
|
||||||
|
List<pointConstraint>& patchConstraints
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const Switch implicitFeatureAttraction = snapParams.implicitFeatureSnap();
|
const Switch implicitFeatureAttraction = snapParams.implicitFeatureSnap();
|
||||||
@ -2851,7 +2914,7 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// - faceSurfaceNormal
|
// - faceSurfaceNormal
|
||||||
// - faceDisp
|
// - faceDisp
|
||||||
// - faceCentres&faceNormal
|
// - faceCentres
|
||||||
List<List<point> > pointFaceSurfNormals(pp.nPoints());
|
List<List<point> > pointFaceSurfNormals(pp.nPoints());
|
||||||
List<List<point> > pointFaceDisp(pp.nPoints());
|
List<List<point> > pointFaceDisp(pp.nPoints());
|
||||||
List<List<point> > pointFaceCentres(pp.nPoints());
|
List<List<point> > pointFaceCentres(pp.nPoints());
|
||||||
@ -2884,10 +2947,11 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
// here.
|
// here.
|
||||||
|
|
||||||
// Nearest feature
|
// Nearest feature
|
||||||
vectorField patchAttraction(localPoints.size(), vector::zero);
|
patchAttraction.setSize(localPoints.size());
|
||||||
|
patchAttraction = vector::zero;
|
||||||
// Constraints at feature
|
// Constraints at feature
|
||||||
List<pointConstraint> patchConstraints(localPoints.size());
|
patchConstraints.setSize(localPoints.size());
|
||||||
|
patchConstraints = pointConstraint();
|
||||||
|
|
||||||
if (implicitFeatureAttraction)
|
if (implicitFeatureAttraction)
|
||||||
{
|
{
|
||||||
@ -2951,15 +3015,29 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
patchConstraints
|
patchConstraints
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const PackedBoolList isMasterPoint(syncTools::getMasterPoints(mesh));
|
||||||
|
{
|
||||||
|
vector avgPatchDisp = meshRefinement::gAverage
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
isMasterPoint,
|
||||||
|
pp.meshPoints(),
|
||||||
|
patchDisp
|
||||||
|
);
|
||||||
|
vector avgPatchAttr = meshRefinement::gAverage
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
isMasterPoint,
|
||||||
|
pp.meshPoints(),
|
||||||
|
patchAttraction
|
||||||
|
);
|
||||||
|
|
||||||
Info<< "Attraction:" << endl
|
Info<< "Attraction:" << endl
|
||||||
<< " linear : max:" << gMax(patchDisp)
|
<< " linear : max:" << gMaxMagSqr(patchDisp)
|
||||||
<< " avg:" << gAverage(patchDisp)
|
<< " avg:" << avgPatchDisp << endl
|
||||||
<< endl
|
<< " feature : max:" << gMaxMagSqr(patchAttraction)
|
||||||
<< " feature : max:" << gMax(patchAttraction)
|
<< " avg:" << avgPatchAttr << endl;
|
||||||
<< " avg:" << gAverage(patchAttraction)
|
}
|
||||||
<< endl;
|
|
||||||
|
|
||||||
|
|
||||||
// So now we have:
|
// So now we have:
|
||||||
// - patchDisp : point movement to go to nearest point on surface
|
// - patchDisp : point movement to go to nearest point on surface
|
||||||
@ -2986,37 +3064,45 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
|
|
||||||
// Count
|
// Count
|
||||||
{
|
{
|
||||||
|
const labelList& meshPoints = pp.meshPoints();
|
||||||
|
|
||||||
|
label nMasterPoints = 0;
|
||||||
label nPlanar = 0;
|
label nPlanar = 0;
|
||||||
label nEdge = 0;
|
label nEdge = 0;
|
||||||
label nPoint = 0;
|
label nPoint = 0;
|
||||||
|
|
||||||
forAll(patchConstraints, pointI)
|
forAll(patchConstraints, pointI)
|
||||||
{
|
{
|
||||||
if (patchConstraints[pointI].first() == 1)
|
if (isMasterPoint[meshPoints[pointI]])
|
||||||
{
|
{
|
||||||
nPlanar++;
|
nMasterPoints++;
|
||||||
}
|
|
||||||
else if (patchConstraints[pointI].first() == 2)
|
if (patchConstraints[pointI].first() == 1)
|
||||||
{
|
{
|
||||||
nEdge++;
|
nPlanar++;
|
||||||
}
|
}
|
||||||
else if (patchConstraints[pointI].first() == 3)
|
else if (patchConstraints[pointI].first() == 2)
|
||||||
{
|
{
|
||||||
nPoint++;
|
nEdge++;
|
||||||
|
}
|
||||||
|
else if (patchConstraints[pointI].first() == 3)
|
||||||
|
{
|
||||||
|
nPoint++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label nTotPoints = returnReduce(pp.nPoints(), sumOp<label>());
|
reduce(nMasterPoints, sumOp<label>());
|
||||||
reduce(nPlanar, sumOp<label>());
|
reduce(nPlanar, sumOp<label>());
|
||||||
reduce(nEdge, sumOp<label>());
|
reduce(nEdge, sumOp<label>());
|
||||||
reduce(nPoint, sumOp<label>());
|
reduce(nPoint, sumOp<label>());
|
||||||
Info<< "Feature analysis : total points:"
|
Info<< "Feature analysis : total master points:"
|
||||||
<< nTotPoints
|
<< nMasterPoints
|
||||||
<< " attraction to :" << nl
|
<< " attraction to :" << nl
|
||||||
<< " feature point : " << nPoint << nl
|
<< " feature point : " << nPoint << nl
|
||||||
<< " feature edge : " << nEdge << nl
|
<< " feature edge : " << nEdge << nl
|
||||||
<< " nearest surface : " << nPlanar << nl
|
<< " nearest surface : " << nPlanar << nl
|
||||||
<< " rest : " << nTotPoints-nPoint-nEdge-nPlanar
|
<< " rest : " << nMasterPoints-nPoint-nEdge-nPlanar
|
||||||
<< nl
|
<< nl
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
@ -3035,11 +3121,29 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
|
|
||||||
if (featureAttract < 1-0.001)
|
if (featureAttract < 1-0.001)
|
||||||
{
|
{
|
||||||
|
const PackedBoolList isMasterEdge(syncTools::getMasterEdges(mesh));
|
||||||
|
|
||||||
|
const vectorField pointNormals
|
||||||
|
(
|
||||||
|
PatchTools::pointNormals
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
pp
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const labelList meshEdges
|
||||||
|
(
|
||||||
|
pp.meshEdges(mesh.edges(), mesh.pointEdges())
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// 1. Smoothed all displacement
|
// 1. Smoothed all displacement
|
||||||
vectorField smoothedPatchDisp = patchDisp;
|
vectorField smoothedPatchDisp = patchDisp;
|
||||||
smoothAndConstrain
|
smoothAndConstrain
|
||||||
(
|
(
|
||||||
|
isMasterEdge,
|
||||||
pp,
|
pp,
|
||||||
|
meshEdges,
|
||||||
patchConstraints,
|
patchConstraints,
|
||||||
smoothedPatchDisp
|
smoothedPatchDisp
|
||||||
);
|
);
|
||||||
@ -3047,16 +3151,18 @@ Foam::vectorField Foam::autoSnapDriver::calcNearestSurfaceFeature
|
|||||||
|
|
||||||
// 2. Smoothed tangential component
|
// 2. Smoothed tangential component
|
||||||
vectorField tangPatchDisp = patchDisp;
|
vectorField tangPatchDisp = patchDisp;
|
||||||
tangPatchDisp -= (pp.pointNormals() & patchDisp) * pp.pointNormals();
|
tangPatchDisp -= (pointNormals & patchDisp) * pointNormals;
|
||||||
smoothAndConstrain
|
smoothAndConstrain
|
||||||
(
|
(
|
||||||
|
isMasterEdge,
|
||||||
pp,
|
pp,
|
||||||
|
meshEdges,
|
||||||
patchConstraints,
|
patchConstraints,
|
||||||
tangPatchDisp
|
tangPatchDisp
|
||||||
);
|
);
|
||||||
|
|
||||||
// Re-add normal component
|
// Re-add normal component
|
||||||
tangPatchDisp += (pp.pointNormals() & patchDisp) * pp.pointNormals();
|
tangPatchDisp += (pointNormals & patchDisp) * pointNormals;
|
||||||
|
|
||||||
if (debug&meshRefinement::OBJINTERSECTIONS)
|
if (debug&meshRefinement::OBJINTERSECTIONS)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -259,23 +259,14 @@ private:
|
|||||||
label& nRefine
|
label& nRefine
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Mark cell if local curvature > curvature or
|
//- Helper: count number of normals1 that are in normals2
|
||||||
// markDifferingRegions = true and intersections with different
|
label countMatches
|
||||||
// regions.
|
|
||||||
bool checkCurvature
|
|
||||||
(
|
(
|
||||||
const scalar curvature,
|
const List<point>& normals1,
|
||||||
const label nAllowRefine,
|
const List<point>& normals2,
|
||||||
const label surfaceLevel,
|
const scalar tol = 1e-6
|
||||||
const vector& surfaceNormal,
|
|
||||||
const label cellI,
|
|
||||||
label& cellMaxLevel,
|
|
||||||
vector& cellMaxNormal,
|
|
||||||
labelList& refineCell,
|
|
||||||
label& nRefine
|
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
||||||
//- Mark cells for surface curvature based refinement. Marks if
|
//- Mark cells for surface curvature based refinement. Marks if
|
||||||
// local curvature > curvature or if on different regions
|
// local curvature > curvature or if on different regions
|
||||||
// (markDifferingRegions)
|
// (markDifferingRegions)
|
||||||
|
|||||||
@ -38,7 +38,74 @@ License
|
|||||||
#include "featureEdgeMesh.H"
|
#include "featureEdgeMesh.H"
|
||||||
#include "Cloud.H"
|
#include "Cloud.H"
|
||||||
//#include "globalIndex.H"
|
//#include "globalIndex.H"
|
||||||
//#include "OBJstream.H"
|
#include "OBJstream.H"
|
||||||
|
#include "cellSet.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
//- To compare normals
|
||||||
|
static bool less(const vector& x, const vector& y)
|
||||||
|
{
|
||||||
|
for (direction i = 0; i < vector::nComponents; i++)
|
||||||
|
{
|
||||||
|
if (x[i] < y[i])
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (x[i] > y[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All components the same
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- To compare normals
|
||||||
|
class normalLess
|
||||||
|
{
|
||||||
|
const vectorList& values_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
normalLess(const vectorList& values)
|
||||||
|
:
|
||||||
|
values_(values)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()(const label a, const label b) const
|
||||||
|
{
|
||||||
|
return less(values_[a], values_[b]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- template specialization for pTraits<labelList> so we can have fields
|
||||||
|
template<>
|
||||||
|
class pTraits<labelList>
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Component type
|
||||||
|
typedef labelList cmptType;
|
||||||
|
};
|
||||||
|
|
||||||
|
//- template specialization for pTraits<labelList> so we can have fields
|
||||||
|
template<>
|
||||||
|
class pTraits<vectorList>
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Component type
|
||||||
|
typedef vectorList cmptType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -954,64 +1021,33 @@ Foam::label Foam::meshRefinement::markSurfaceRefinement
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Checks if multiple intersections of a cell (by a surface with a higher
|
// Count number of matches of first argument in second argument
|
||||||
// max than the cell level) and if so if the normals at these intersections
|
Foam::label Foam::meshRefinement::countMatches
|
||||||
// make a large angle.
|
|
||||||
// Returns false if the nRefine limit has been reached, true otherwise.
|
|
||||||
bool Foam::meshRefinement::checkCurvature
|
|
||||||
(
|
(
|
||||||
const scalar curvature,
|
const List<point>& normals1,
|
||||||
const label nAllowRefine,
|
const List<point>& normals2,
|
||||||
|
const scalar tol
|
||||||
const label surfaceLevel, // current intersection max level
|
|
||||||
const vector& surfaceNormal,// current intersection normal
|
|
||||||
|
|
||||||
const label cellI,
|
|
||||||
|
|
||||||
label& cellMaxLevel, // cached max surface level for this cell
|
|
||||||
vector& cellMaxNormal, // cached surface normal for this cell
|
|
||||||
|
|
||||||
labelList& refineCell,
|
|
||||||
label& nRefine
|
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const labelList& cellLevel = meshCutter_.cellLevel();
|
label nMatches = 0;
|
||||||
|
|
||||||
// Test if surface applicable
|
forAll(normals1, i)
|
||||||
if (surfaceLevel > cellLevel[cellI])
|
|
||||||
{
|
{
|
||||||
if (cellMaxLevel == -1)
|
const vector& n1 = normals1[i];
|
||||||
{
|
|
||||||
// First visit of cell. Store
|
|
||||||
cellMaxLevel = surfaceLevel;
|
|
||||||
cellMaxNormal = surfaceNormal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Second or more visit. Check curvature.
|
|
||||||
if ((cellMaxNormal & surfaceNormal) < curvature)
|
|
||||||
{
|
|
||||||
return markForRefine
|
|
||||||
(
|
|
||||||
surfaceLevel, // mark with any non-neg number.
|
|
||||||
nAllowRefine,
|
|
||||||
refineCell[cellI],
|
|
||||||
nRefine
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set normal to that of highest surface. Not really necessary
|
forAll(normals2, j)
|
||||||
// over here but we reuse cellMax info when doing coupled faces.
|
{
|
||||||
if (surfaceLevel > cellMaxLevel)
|
const vector& n2 = normals2[j];
|
||||||
|
|
||||||
|
if (magSqr(n1-n2) < tol)
|
||||||
{
|
{
|
||||||
cellMaxLevel = surfaceLevel;
|
nMatches++;
|
||||||
cellMaxNormal = surfaceNormal;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did not reach refinement limit.
|
return nMatches;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1039,6 +1075,9 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
|
|||||||
// on a different surface gets refined (if its current level etc.)
|
// on a different surface gets refined (if its current level etc.)
|
||||||
|
|
||||||
|
|
||||||
|
const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
|
||||||
|
|
||||||
|
|
||||||
// Collect candidate faces (i.e. intersecting any surface and
|
// Collect candidate faces (i.e. intersecting any surface and
|
||||||
// owner/neighbour not yet refined.
|
// owner/neighbour not yet refined.
|
||||||
labelList testFaces(getRefineCandidateFaces(refineCell));
|
labelList testFaces(getRefineCandidateFaces(refineCell));
|
||||||
@ -1068,6 +1107,12 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
|
|||||||
|
|
||||||
start[i] = cellCentres[own];
|
start[i] = cellCentres[own];
|
||||||
end[i] = neiCc[bFaceI];
|
end[i] = neiCc[bFaceI];
|
||||||
|
|
||||||
|
if (!isMasterFace[faceI])
|
||||||
|
{
|
||||||
|
Swap(start[i], end[i]);
|
||||||
|
}
|
||||||
|
|
||||||
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
|
minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1081,10 +1126,9 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
|
|||||||
|
|
||||||
|
|
||||||
// Test for all intersections (with surfaces of higher max level than
|
// Test for all intersections (with surfaces of higher max level than
|
||||||
// minLevel) and cache per cell the max surface level and the local normal
|
// minLevel) and cache per cell the interesting inter
|
||||||
// on that surface.
|
labelListList cellSurfLevels(mesh_.nCells());
|
||||||
labelList cellMaxLevel(mesh_.nCells(), -1);
|
List<vectorList> cellSurfNormals(mesh_.nCells());
|
||||||
vectorField cellMaxNormal(mesh_.nCells(), vector::zero);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Per segment the normals of the surfaces
|
// Per segment the normals of the surfaces
|
||||||
@ -1104,12 +1148,29 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
|
|||||||
surfaceNormal,
|
surfaceNormal,
|
||||||
surfaceLevel
|
surfaceLevel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Sort the data according to surface location. This will guarantee
|
||||||
|
// that on coupled faces both sides visit the intersections in
|
||||||
|
// the same order so will decide the same
|
||||||
|
labelList visitOrder;
|
||||||
|
forAll(surfaceNormal, pointI)
|
||||||
|
{
|
||||||
|
vectorList& pNormals = surfaceNormal[pointI];
|
||||||
|
labelList& pLevel = surfaceLevel[pointI];
|
||||||
|
|
||||||
|
sortedOrder(pNormals, visitOrder, normalLess(pNormals));
|
||||||
|
|
||||||
|
pNormals = List<point>(pNormals, visitOrder);
|
||||||
|
pLevel = UIndirectList<label>(pLevel, visitOrder);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear out unnecessary data
|
// Clear out unnecessary data
|
||||||
start.clear();
|
start.clear();
|
||||||
end.clear();
|
end.clear();
|
||||||
minLevel.clear();
|
minLevel.clear();
|
||||||
|
|
||||||
// Extract per cell information on the surface with the highest max
|
// Convert face-wise data to cell.
|
||||||
forAll(testFaces, i)
|
forAll(testFaces, i)
|
||||||
{
|
{
|
||||||
label faceI = testFaces[i];
|
label faceI = testFaces[i];
|
||||||
@ -1118,164 +1179,280 @@ Foam::label Foam::meshRefinement::markSurfaceCurvatureRefinement
|
|||||||
const vectorList& fNormals = surfaceNormal[i];
|
const vectorList& fNormals = surfaceNormal[i];
|
||||||
const labelList& fLevels = surfaceLevel[i];
|
const labelList& fLevels = surfaceLevel[i];
|
||||||
|
|
||||||
forAll(fLevels, hitI)
|
forAll(fNormals, hitI)
|
||||||
{
|
{
|
||||||
checkCurvature
|
if (fLevels[hitI] > cellLevel[own])
|
||||||
(
|
|
||||||
curvature,
|
|
||||||
nAllowRefine,
|
|
||||||
|
|
||||||
fLevels[hitI],
|
|
||||||
fNormals[hitI],
|
|
||||||
|
|
||||||
own,
|
|
||||||
cellMaxLevel[own],
|
|
||||||
cellMaxNormal[own],
|
|
||||||
|
|
||||||
refineCell,
|
|
||||||
nRefine
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mesh_.isInternalFace(faceI))
|
|
||||||
{
|
|
||||||
label nei = mesh_.faceNeighbour()[faceI];
|
|
||||||
|
|
||||||
forAll(fLevels, hitI)
|
|
||||||
{
|
{
|
||||||
checkCurvature
|
cellSurfLevels[own].append(fLevels[hitI]);
|
||||||
(
|
cellSurfNormals[own].append(fNormals[hitI]);
|
||||||
curvature,
|
}
|
||||||
nAllowRefine,
|
|
||||||
|
|
||||||
fLevels[hitI],
|
if (mesh_.isInternalFace(faceI))
|
||||||
fNormals[hitI],
|
{
|
||||||
|
label nei = mesh_.faceNeighbour()[faceI];
|
||||||
nei,
|
if (fLevels[hitI] > cellLevel[nei])
|
||||||
cellMaxLevel[nei],
|
{
|
||||||
cellMaxNormal[nei],
|
cellSurfLevels[nei].append(fLevels[hitI]);
|
||||||
|
cellSurfNormals[nei].append(fNormals[hitI]);
|
||||||
refineCell,
|
}
|
||||||
nRefine
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Find out a measure of surface curvature and region edges.
|
|
||||||
// Send over surface region and surface normal to neighbour cell.
|
|
||||||
|
|
||||||
labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces());
|
|
||||||
vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces());
|
|
||||||
|
|
||||||
for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
|
// Bit of statistics
|
||||||
{
|
{
|
||||||
label bFaceI = faceI-mesh_.nInternalFaces();
|
label nSet = 0;
|
||||||
label own = mesh_.faceOwner()[faceI];
|
label nNormals = 9;
|
||||||
|
forAll(cellSurfNormals, cellI)
|
||||||
neiBndMaxLevel[bFaceI] = cellMaxLevel[own];
|
{
|
||||||
neiBndMaxNormal[bFaceI] = cellMaxNormal[own];
|
const vectorList& normals = cellSurfNormals[cellI];
|
||||||
|
if (normals.size())
|
||||||
|
{
|
||||||
|
nSet++;
|
||||||
|
nNormals += normals.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reduce(nSet, sumOp<label>());
|
||||||
|
reduce(nNormals, sumOp<label>());
|
||||||
|
Info<< "markSurfaceCurvatureRefinement :"
|
||||||
|
<< " cells:" << mesh_.globalData().nTotalCells()
|
||||||
|
<< " of which with normals:" << nSet
|
||||||
|
<< " ; total normals stored:" << nNormals
|
||||||
|
<< endl;
|
||||||
}
|
}
|
||||||
syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel);
|
|
||||||
syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal);
|
|
||||||
|
|
||||||
// Loop over all faces. Could only be checkFaces.. except if they're coupled
|
|
||||||
|
|
||||||
|
bool reachedLimit = false;
|
||||||
|
|
||||||
|
|
||||||
|
// 1. Check normals per cell
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label cellI = 0;
|
||||||
|
!reachedLimit && cellI < cellSurfNormals.size();
|
||||||
|
cellI++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const vectorList& normals = cellSurfNormals[cellI];
|
||||||
|
const labelList& levels = cellSurfLevels[cellI];
|
||||||
|
|
||||||
|
// n^2 comparison of all normals in a cell
|
||||||
|
for (label i = 0; !reachedLimit && i < normals.size(); i++)
|
||||||
|
{
|
||||||
|
for (label j = i+1; !reachedLimit && j < normals.size(); j++)
|
||||||
|
{
|
||||||
|
if ((normals[i] & normals[j]) < curvature)
|
||||||
|
{
|
||||||
|
label maxLevel = max(levels[i], levels[j]);
|
||||||
|
|
||||||
|
if (cellLevel[cellI] < maxLevel)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!markForRefine
|
||||||
|
(
|
||||||
|
maxLevel,
|
||||||
|
nAllowRefine,
|
||||||
|
refineCell[cellI],
|
||||||
|
nRefine
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Stopped refining since reaching my cell"
|
||||||
|
<< " limit of " << mesh_.nCells()+7*nRefine
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
reachedLimit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 2. Find out a measure of surface curvature
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Look at normals between neighbouring surfaces
|
||||||
|
// Loop over all faces. Could only be checkFaces, except if they're coupled
|
||||||
|
|
||||||
// Internal faces
|
// Internal faces
|
||||||
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
|
for
|
||||||
|
(
|
||||||
|
label faceI = 0;
|
||||||
|
!reachedLimit && faceI < mesh_.nInternalFaces();
|
||||||
|
faceI++
|
||||||
|
)
|
||||||
{
|
{
|
||||||
label own = mesh_.faceOwner()[faceI];
|
label own = mesh_.faceOwner()[faceI];
|
||||||
label nei = mesh_.faceNeighbour()[faceI];
|
label nei = mesh_.faceNeighbour()[faceI];
|
||||||
|
|
||||||
if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1)
|
const vectorList& ownNormals = cellSurfNormals[own];
|
||||||
{
|
const labelList& ownLevels = cellSurfLevels[own];
|
||||||
// Have valid data on both sides. Check curvature.
|
const vectorList& neiNormals = cellSurfNormals[nei];
|
||||||
if ((cellMaxNormal[own] & cellMaxNormal[nei]) < curvature)
|
const labelList& neiLevels = cellSurfLevels[nei];
|
||||||
{
|
|
||||||
// See which side to refine
|
|
||||||
if (cellLevel[own] < cellMaxLevel[own])
|
|
||||||
{
|
|
||||||
if
|
|
||||||
(
|
|
||||||
!markForRefine
|
|
||||||
(
|
|
||||||
cellMaxLevel[own],
|
|
||||||
nAllowRefine,
|
|
||||||
refineCell[own],
|
|
||||||
nRefine
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "Stopped refining since reaching my cell"
|
|
||||||
<< " limit of " << mesh_.nCells()+7*nRefine
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellLevel[nei] < cellMaxLevel[nei])
|
|
||||||
|
// Special case: owner normals set is a subset of the neighbour
|
||||||
|
// normals. Do not do curvature refinement since other cell's normals
|
||||||
|
// do not add any information. Avoids weird corner extensions of
|
||||||
|
// refinement regions.
|
||||||
|
bool ownIsSubset =
|
||||||
|
countMatches(ownNormals, neiNormals)
|
||||||
|
== ownNormals.size();
|
||||||
|
|
||||||
|
bool neiIsSubset =
|
||||||
|
countMatches(neiNormals, ownNormals)
|
||||||
|
== neiNormals.size();
|
||||||
|
|
||||||
|
|
||||||
|
if (!ownIsSubset && !neiIsSubset)
|
||||||
|
{
|
||||||
|
// n^2 comparison of between ownNormals and neiNormals
|
||||||
|
for (label i = 0; !reachedLimit && i < ownNormals.size(); i++)
|
||||||
|
{
|
||||||
|
for (label j = 0; !reachedLimit && j < neiNormals.size(); j++)
|
||||||
{
|
{
|
||||||
if
|
// Have valid data on both sides. Check curvature.
|
||||||
(
|
if ((ownNormals[i] & neiNormals[j]) < curvature)
|
||||||
!markForRefine
|
|
||||||
(
|
|
||||||
cellMaxLevel[nei],
|
|
||||||
nAllowRefine,
|
|
||||||
refineCell[nei],
|
|
||||||
nRefine
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (debug)
|
// See which side to refine.
|
||||||
|
if (cellLevel[own] < ownLevels[i])
|
||||||
{
|
{
|
||||||
Pout<< "Stopped refining since reaching my cell"
|
if
|
||||||
<< " limit of " << mesh_.nCells()+7*nRefine
|
(
|
||||||
<< endl;
|
!markForRefine
|
||||||
|
(
|
||||||
|
ownLevels[i],
|
||||||
|
nAllowRefine,
|
||||||
|
refineCell[own],
|
||||||
|
nRefine
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Stopped refining since reaching"
|
||||||
|
<< " my cell limit of "
|
||||||
|
<< mesh_.nCells()+7*nRefine << endl;
|
||||||
|
}
|
||||||
|
reachedLimit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cellLevel[nei] < neiLevels[j])
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!markForRefine
|
||||||
|
(
|
||||||
|
neiLevels[j],
|
||||||
|
nAllowRefine,
|
||||||
|
refineCell[nei],
|
||||||
|
nRefine
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Stopped refining since reaching"
|
||||||
|
<< " my cell limit of "
|
||||||
|
<< mesh_.nCells()+7*nRefine << endl;
|
||||||
|
}
|
||||||
|
reachedLimit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Send over surface normal to neighbour cell.
|
||||||
|
List<vectorList> neiSurfaceNormals;
|
||||||
|
syncTools::swapBoundaryCellList(mesh_, cellSurfNormals, neiSurfaceNormals);
|
||||||
|
|
||||||
// Boundary faces
|
// Boundary faces
|
||||||
for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
|
for
|
||||||
|
(
|
||||||
|
label faceI = mesh_.nInternalFaces();
|
||||||
|
!reachedLimit && faceI < mesh_.nFaces();
|
||||||
|
faceI++
|
||||||
|
)
|
||||||
{
|
{
|
||||||
label own = mesh_.faceOwner()[faceI];
|
label own = mesh_.faceOwner()[faceI];
|
||||||
label bFaceI = faceI - mesh_.nInternalFaces();
|
label bFaceI = faceI - mesh_.nInternalFaces();
|
||||||
|
|
||||||
if (cellLevel[own] < cellMaxLevel[own] && neiBndMaxLevel[bFaceI] != -1)
|
const vectorList& ownNormals = cellSurfNormals[own];
|
||||||
|
const labelList& ownLevels = cellSurfLevels[own];
|
||||||
|
const vectorList& neiNormals = neiSurfaceNormals[bFaceI];
|
||||||
|
|
||||||
|
// Special case: owner normals set is a subset of the neighbour
|
||||||
|
// normals. Do not do curvature refinement since other cell's normals
|
||||||
|
// do not add any information. Avoids weird corner extensions of
|
||||||
|
// refinement regions.
|
||||||
|
bool ownIsSubset =
|
||||||
|
countMatches(ownNormals, neiNormals)
|
||||||
|
== ownNormals.size();
|
||||||
|
|
||||||
|
bool neiIsSubset =
|
||||||
|
countMatches(neiNormals, ownNormals)
|
||||||
|
== neiNormals.size();
|
||||||
|
|
||||||
|
|
||||||
|
if (!ownIsSubset && !neiIsSubset)
|
||||||
{
|
{
|
||||||
// Have valid data on both sides. Check curvature.
|
// n^2 comparison of between ownNormals and neiNormals
|
||||||
if ((cellMaxNormal[own] & neiBndMaxNormal[bFaceI]) < curvature)
|
for (label i = 0; !reachedLimit && i < ownNormals.size(); i++)
|
||||||
{
|
{
|
||||||
if
|
for (label j = 0; !reachedLimit && j < neiNormals.size(); j++)
|
||||||
(
|
|
||||||
!markForRefine
|
|
||||||
(
|
|
||||||
cellMaxLevel[own],
|
|
||||||
nAllowRefine,
|
|
||||||
refineCell[own],
|
|
||||||
nRefine
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (debug)
|
// Have valid data on both sides. Check curvature.
|
||||||
|
if ((ownNormals[i] & neiNormals[j]) < curvature)
|
||||||
{
|
{
|
||||||
Pout<< "Stopped refining since reaching my cell"
|
if (cellLevel[own] < ownLevels[i])
|
||||||
<< " limit of " << mesh_.nCells()+7*nRefine
|
{
|
||||||
<< endl;
|
if
|
||||||
|
(
|
||||||
|
!markForRefine
|
||||||
|
(
|
||||||
|
ownLevels[i],
|
||||||
|
nAllowRefine,
|
||||||
|
refineCell[own],
|
||||||
|
nRefine
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Stopped refining since reaching"
|
||||||
|
<< " my cell limit of "
|
||||||
|
<< mesh_.nCells()+7*nRefine
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
reachedLimit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
returnReduce(nRefine, sumOp<label>())
|
returnReduce(nRefine, sumOp<label>())
|
||||||
|
|||||||
Reference in New Issue
Block a user