From 01b785f23a6dceb90eff6f981a26e4cca1c6b8f9 Mon Sep 17 00:00:00 2001
From: mattijs <mattijs>
Date: Thu, 21 Dec 2017 13:12:22 +0000
Subject: [PATCH] ENH: 2:1 constraint

---
 .../polyTopoChange/hexRef8/hexRef8.C          |  44 ++--
 .../polyTopoChange/hexRef8/hexRef8.H          |  22 +-
 .../meshRefinement/meshRefinement.H           |  10 +
 .../meshRefinement/meshRefinementRefine.C     | 102 +++++++-
 .../snappyHexMeshDriver/snappyRefineDriver.C  | 240 ++----------------
 5 files changed, 175 insertions(+), 243 deletions(-)

diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
index 74dcafca1d1..79c7e7446ae 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C
@@ -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
diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
index a2388f3b60f..3f4292d527e 100644
--- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
+++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.H
@@ -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
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
index 1d9e7248255..2ae2f5634ca 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.H
@@ -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
             (
diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
index 53728b952a6..9954987315a 100644
--- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
+++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementRefine.C
@@ -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,
diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
index 68df871bd5d..15fe6edf80e 100644
--- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
+++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C
@@ -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];
-                }
+                currentLevel[celli] = dirCellLevel[celli][dir];
+            }
 
-                // Find cells inside the shells
-                labelList insideShell;
-                shells.findDirectionalLevel
+            labelList candidateCells
+            (
+                meshRefiner_.directionalRefineCandidates
                 (
-                    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;
-                    }
-                }
-            }
+                    refineParams.maxGlobalCells(),
+                    refineParams.maxLocalCells(),
+                    currentLevel,
+                    dir
+                )
+            );
 
             // Extend to keep 2:1 ratio
             labelList cellsToRefine
             (
-                consistentDirectionalRefinement
+                meshRefiner_.meshCutter().consistentRefinement
                 (
-                    dir,
-                    dirCellLevel,
+                    currentLevel,
                     candidateCells,
                     true
                 )
-- 
GitLab