ENH: 2:1 constraint

This commit is contained in:
mattijs 2017-12-21 13:12:22 +00:00
parent 47bd51348b
commit 01b785f23a
5 changed files with 176 additions and 244 deletions

View File

@ -1564,6 +1564,7 @@ void Foam::hexRef8::walkFaceFromMid
Foam::label Foam::hexRef8::faceConsistentRefinement
(
const bool maxSet,
const labelUList& cellLevel,
bitSet& refineCell
) const
{
@ -1573,10 +1574,10 @@ Foam::label Foam::hexRef8::faceConsistentRefinement
for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
{
label own = mesh_.faceOwner()[facei];
label nei = mesh_.faceNeighbour()[facei];
label ownLevel = cellLevel[own] + refineCell.get(own);
label ownLevel = cellLevel_[own] + refineCell.get(own);
label neiLevel = cellLevel_[nei] + refineCell.get(nei);
label nei = mesh_.faceNeighbour()[facei];
label neiLevel = cellLevel[nei] + refineCell.get(nei);
if (ownLevel > (neiLevel+1))
{
@ -1613,7 +1614,7 @@ Foam::label Foam::hexRef8::faceConsistentRefinement
{
label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
neiLevel[i] = cellLevel_[own] + refineCell.get(own);
neiLevel[i] = cellLevel[own] + refineCell.get(own);
}
// Swap to neighbour
@ -1623,7 +1624,7 @@ Foam::label Foam::hexRef8::faceConsistentRefinement
forAll(neiLevel, i)
{
label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
label ownLevel = cellLevel_[own] + refineCell.get(own);
label ownLevel = cellLevel[own] + refineCell.get(own);
if (ownLevel > (neiLevel[i]+1))
{
@ -1650,6 +1651,7 @@ Foam::label Foam::hexRef8::faceConsistentRefinement
// Debug: check if wanted refinement is compatible with 2:1
void Foam::hexRef8::checkWantedRefinementLevels
(
const labelUList& cellLevel,
const labelList& cellsToRefine
) const
{
@ -1658,10 +1660,10 @@ void Foam::hexRef8::checkWantedRefinementLevels
for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
{
label own = mesh_.faceOwner()[facei];
label nei = mesh_.faceNeighbour()[facei];
label ownLevel = cellLevel[own] + refineCell.get(own);
label ownLevel = cellLevel_[own] + refineCell.get(own);
label neiLevel = cellLevel_[nei] + refineCell.get(nei);
label nei = mesh_.faceNeighbour()[facei];
label neiLevel = cellLevel[nei] + refineCell.get(nei);
if (mag(ownLevel-neiLevel) > 1)
{
@ -1669,11 +1671,11 @@ void Foam::hexRef8::checkWantedRefinementLevels
dumpCell(nei);
FatalErrorInFunction
<< "cell:" << own
<< " current level:" << cellLevel_[own]
<< " current level:" << cellLevel[own]
<< " level after refinement:" << ownLevel
<< nl
<< "neighbour cell:" << nei
<< " current level:" << cellLevel_[nei]
<< " current level:" << cellLevel[nei]
<< " level after refinement:" << neiLevel
<< nl
<< "which does not satisfy 2:1 constraints anymore."
@ -1689,7 +1691,7 @@ void Foam::hexRef8::checkWantedRefinementLevels
{
label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
neiLevel[i] = cellLevel_[own] + refineCell.get(own);
neiLevel[i] = cellLevel[own] + refineCell.get(own);
}
// Swap to neighbour
@ -1701,7 +1703,7 @@ void Foam::hexRef8::checkWantedRefinementLevels
label facei = i + mesh_.nInternalFaces();
label own = mesh_.faceOwner()[facei];
label ownLevel = cellLevel_[own] + refineCell.get(own);
label ownLevel = cellLevel[own] + refineCell.get(own);
if (mag(ownLevel - neiLevel[i]) > 1)
{
@ -1715,7 +1717,7 @@ void Foam::hexRef8::checkWantedRefinementLevels
<< " on patch " << patchi << " "
<< mesh_.boundaryMesh()[patchi].name()
<< " owner cell " << own
<< " current level:" << cellLevel_[own]
<< " current level:" << cellLevel[own]
<< " level after refinement:" << ownLevel
<< nl
<< " (coupled) neighbour cell will get refinement "
@ -2251,6 +2253,7 @@ Foam::hexRef8::hexRef8
Foam::labelList Foam::hexRef8::consistentRefinement
(
const labelUList& cellLevel,
const labelList& cellsToRefine,
const bool maxSet
) const
@ -2264,7 +2267,12 @@ Foam::labelList Foam::hexRef8::consistentRefinement
while (true)
{
label nChanged = faceConsistentRefinement(maxSet, refineCell);
label nChanged = faceConsistentRefinement
(
maxSet,
cellLevel,
refineCell
);
reduce(nChanged, sumOp<label>());
@ -2286,7 +2294,7 @@ Foam::labelList Foam::hexRef8::consistentRefinement
if (debug)
{
checkWantedRefinementLevels(newCellsToRefine);
checkWantedRefinementLevels(cellLevel, newCellsToRefine);
}
return newCellsToRefine;
@ -3089,11 +3097,11 @@ Foam::labelList Foam::hexRef8::consistentSlowRefinement2
refineCell.set(celli);
}
}
faceConsistentRefinement(true, refineCell);
faceConsistentRefinement(true, cellLevel_, refineCell);
while (true)
{
label nChanged = faceConsistentRefinement(true, refineCell);
label nChanged = faceConsistentRefinement(true, cellLevel_, refineCell);
reduce(nChanged, sumOp<label>());
@ -3141,7 +3149,7 @@ Foam::labelList Foam::hexRef8::consistentSlowRefinement2
const bitSet savedRefineCell(refineCell);
label nChanged = faceConsistentRefinement(true, refineCell);
label nChanged = faceConsistentRefinement(true, cellLevel_, refineCell);
{
cellSet cellsOut2

View File

@ -300,11 +300,16 @@ class hexRef8
label faceConsistentRefinement
(
const bool maxSet,
const labelUList& cellLevel,
bitSet& refineCell
) const;
//- Check wanted refinement for 2:1 consistency
void checkWantedRefinementLevels(const labelList&) const;
void checkWantedRefinementLevels
(
const labelUList& cellLevel,
const labelList&
) const;
// Cellshape recognition
@ -420,10 +425,25 @@ public:
// removes cells to refine (maxSet = false)
labelList consistentRefinement
(
const labelUList& cellLevel,
const labelList& cellsToRefine,
const bool maxSet
) const;
//- Given valid mesh and current cell level and proposed
// cells to refine calculate any clashes (due to 2:1) and return
// ok list of cells to refine.
// Either adds cells to refine to set (maxSet = true) or
// removes cells to refine (maxSet = false)
labelList consistentRefinement
(
const labelList& cellsToRefine,
const bool maxSet
) const
{
return consistentRefinement(cellLevel_, cellsToRefine, maxSet);
}
//- Like consistentRefinement but slower:
//
// - specify number of cells between consecutive refinement levels

View File

@ -1037,6 +1037,16 @@ public:
const scalar maxLoadUnbalance
);
//- Calculate list of cells to directionally refine
labelList directionalRefineCandidates
(
const label maxGlobalCells,
const label maxLocalCells,
const labelList& currentLevel,
const direction dir
) const;
//- Directionally refine in direction cmpt
autoPtr<mapPolyMesh> directionalRefine
(

View File

@ -2078,7 +2078,7 @@ Foam::labelList Foam::meshRefinement::refineCandidates
label nAllowRefine = labelMax / Pstream::nProcs();
// Marked for refinement (>= 0) or not (-1). Actual value is the
// index of the surface it intersects.
// index of the surface it intersects / shell it is inside.
labelList refineCell(mesh_.nCells(), -1);
label nRefine = 0;
@ -2629,6 +2629,106 @@ Foam::meshRefinement::balanceAndRefine
}
Foam::labelList Foam::meshRefinement::directionalRefineCandidates
(
const label maxGlobalCells,
const label maxLocalCells,
const labelList& currentLevel,
const direction dir
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
label totNCells = mesh_.globalData().nTotalCells();
labelList cellsToRefine;
if (totNCells >= maxGlobalCells)
{
Info<< "No cells marked for refinement since reached limit "
<< maxGlobalCells << '.' << endl;
}
else
{
// Disable refinement shortcut. nAllowRefine is per processor limit.
label nAllowRefine = labelMax / Pstream::nProcs();
// Marked for refinement (>= 0) or not (-1). Actual value is the
// index of the surface it intersects / shell it is inside
labelList refineCell(mesh_.nCells(), -1);
label nRefine = 0;
// Find cells inside the shells with directional levels
labelList insideShell;
shells_.findDirectionalLevel
(
cellCentres,
cellLevel,
currentLevel, // current directional level
dir,
insideShell
);
// Mark for refinement
forAll(insideShell, celli)
{
if (insideShell[celli] >= 0)
{
bool reachedLimit = !markForRefine
(
insideShell[celli], // mark with any positive value
nAllowRefine,
refineCell[celli],
nRefine
);
if (reachedLimit)
{
if (debug)
{
Pout<< "Stopped refining cells"
<< " since reaching my cell limit of "
<< mesh_.nCells()+nAllowRefine << endl;
}
break;
}
}
}
// Limit refinement
// ~~~~~~~~~~~~~~~~
{
label nUnmarked = unmarkInternalRefinement(refineCell, nRefine);
if (nUnmarked > 0)
{
Info<< "Unmarked for refinement due to limit shells"
<< " : " << nUnmarked << " cells." << endl;
}
}
// Pack cells-to-refine
// ~~~~~~~~~~~~~~~~~~~~
cellsToRefine.setSize(nRefine);
nRefine = 0;
forAll(refineCell, cellI)
{
if (refineCell[cellI] != -1)
{
cellsToRefine[nRefine++] = cellI;
}
}
}
return cellsToRefine;
}
Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::directionalRefine
(
const string& msg,

View File

@ -1572,190 +1572,6 @@ Foam::label Foam::snappyRefineDriver::shellRefine
return iter;
}
//XXXXXXXXXX
Foam::List<Foam::direction> Foam::snappyRefineDriver::faceDirection() const
{
const fvMesh& mesh = meshRefiner_.mesh();
List<direction> faceDir(mesh.nFaces());
vectorField nf(mesh.faceAreas());
nf /= mag(nf);
forAll(nf, facei)
{
const vector& n = nf[facei];
if (mag(n[0]) > 0.5)
{
faceDir[facei] = 0;
}
else if (mag(n[1]) > 0.5)
{
faceDir[facei] = 1;
}
else if (mag(n[2]) > 0.5)
{
faceDir[facei] = 2;
}
}
return faceDir;
}
Foam::label Foam::snappyRefineDriver::faceConsistentRefinement
(
const PackedBoolList& isDirFace,
const List<labelVector>& dirCellLevel,
const direction dir,
const bool maxSet,
PackedBoolList& refineCell
) const
{
const fvMesh& mesh = meshRefiner_.mesh();
label nChanged = 0;
// Internal faces.
for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
{
if (isDirFace[facei])
{
label own = mesh.faceOwner()[facei];
label ownLevel = dirCellLevel[own][dir] + refineCell.get(own);
label nei = mesh.faceNeighbour()[facei];
label neiLevel = dirCellLevel[nei][dir] + refineCell.get(nei);
if (ownLevel > (neiLevel+1))
{
if (maxSet)
{
refineCell.set(nei);
}
else
{
refineCell.unset(own);
}
nChanged++;
}
else if (neiLevel > (ownLevel+1))
{
if (maxSet)
{
refineCell.set(own);
}
else
{
refineCell.unset(nei);
}
nChanged++;
}
}
}
// Coupled faces. Swap owner level to get neighbouring cell level.
// (only boundary faces of neiLevel used)
labelList neiLevel(mesh.nFaces()-mesh.nInternalFaces());
forAll(neiLevel, i)
{
label own = mesh.faceOwner()[i+mesh.nInternalFaces()];
neiLevel[i] = dirCellLevel[own][dir] + refineCell.get(own);
}
// Swap to neighbour
syncTools::swapBoundaryFaceList(mesh, neiLevel);
// Now we have neighbour value see which cells need refinement
forAll(neiLevel, i)
{
label facei = i+mesh.nInternalFaces();
if (isDirFace[facei])
{
label own = mesh.faceOwner()[facei];
label ownLevel = dirCellLevel[own][dir] + refineCell.get(own);
if (ownLevel > (neiLevel[i]+1))
{
if (!maxSet)
{
refineCell.unset(own);
nChanged++;
}
}
else if (neiLevel[i] > (ownLevel+1))
{
if (maxSet)
{
refineCell.set(own);
nChanged++;
}
}
}
}
return nChanged;
}
Foam::labelList Foam::snappyRefineDriver::consistentDirectionalRefinement
(
const direction dir,
const List<labelVector>& dirCellLevel,
const labelUList& candidateCells,
const bool maxSet
) const
{
const fvMesh& mesh = meshRefiner_.mesh();
const List<direction> faceDir(faceDirection());
PackedBoolList isDirFace(mesh.nFaces());
forAll(faceDir, facei)
{
if (faceDir[facei] == dir)
{
isDirFace[facei] = true;
}
}
// Loop, modifying cellsToRefine, until no more changes to due to 2:1
// conflicts.
// maxSet = false : unselect cells to refine
// maxSet = true : select cells to refine
// Go to straight boolList.
PackedBoolList isRefineCell(mesh.nCells());
isRefineCell.set(candidateCells);
while (true)
{
label nChanged = faceConsistentRefinement
(
isDirFace,
dirCellLevel,
dir,
maxSet,
isRefineCell
);
reduce(nChanged, sumOp<label>());
if (debug)
{
Pout<< "snappyRefineDriver::consistentDirectionalRefinement"
<< " : Changed " << nChanged
<< " refinement levels due to 2:1 conflicts."
<< endl;
}
if (nChanged == 0)
{
break;
}
}
return isRefineCell.used();
}
Foam::label Foam::snappyRefineDriver::directionalShellRefine
@ -1814,53 +1630,31 @@ Foam::label Foam::snappyRefineDriver::directionalShellRefine
// - original cellLevel (using mapping) mentioned in levelIncrement
// - dirCellLevel not yet up to cellLevel+levelIncrement
labelList candidateCells;
// Extract component of directional level
labelList currentLevel(dirCellLevel.size());
forAll(dirCellLevel, celli)
{
// Extract component of directional level
labelList currentLevel(dirCellLevel.size());
forAll(dirCellLevel, celli)
{
currentLevel[celli] = dirCellLevel[celli][dir];
}
// Find cells inside the shells
labelList insideShell;
shells.findDirectionalLevel
(
mesh.cellCentres(),
cellLevel,
currentLevel, // directional level
dir,
insideShell
);
// Extract
label n = 0;
forAll(insideShell, celli)
{
if (insideShell[celli] >= 0)
{
n++;
}
}
candidateCells.setSize(n);
n = 0;
forAll(insideShell, celli)
{
if (insideShell[celli] >= 0)
{
candidateCells[n++] = celli;
}
}
currentLevel[celli] = dirCellLevel[celli][dir];
}
labelList candidateCells
(
meshRefiner_.directionalRefineCandidates
(
refineParams.maxGlobalCells(),
refineParams.maxLocalCells(),
currentLevel,
dir
)
);
// Extend to keep 2:1 ratio
labelList cellsToRefine
(
consistentDirectionalRefinement
meshRefiner_.meshCutter().consistentRefinement
(
dir,
dirCellLevel,
currentLevel,
candidateCells,
true
)