From a3228f861a3eaf779ed3ecec35036d9f92bbb740 Mon Sep 17 00:00:00 2001
From: Andrew Heather <a.heather@opencfd.co.uk>
Date: Tue, 5 Jun 2018 15:13:13 +0100
Subject: [PATCH] ENH: GAMG agglom - more robust treatment for small meshes

---
 .../GAMGAgglomeration/GAMGAgglomeration.C      |  8 ++++++++
 .../GAMGAgglomeration/GAMGAgglomeration.H      | 18 +++++++++---------
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
index d3b63e7b9d7..b507253a199 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.C
@@ -265,6 +265,14 @@ Foam::GAMGAgglomeration::GAMGAgglomeration
 
     meshLevels_(maxLevels_)
 {
+    // Limit the cells in the coarsest level based on the local number of
+    // cells.  Note: 2 for pair-wise
+    nCellsInCoarsestLevel_ =
+        max(1, min(mesh.lduAddr().size()/2, nCellsInCoarsestLevel_));
+
+    // Ensure all procs see the same nCellsInCoarsestLevel_
+    reduce(nCellsInCoarsestLevel_, minOp<label>());
+
     procCommunicator_.setSize(maxLevels_ + 1, -1);
     if (processorAgglomerate())
     {
diff --git a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
index 9a8bb8c05c7..d258e7f8c58 100644
--- a/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
+++ b/src/OpenFOAM/matrices/lduMatrix/solvers/GAMG/GAMGAgglomerations/GAMGAgglomeration/GAMGAgglomeration.H
@@ -71,7 +71,7 @@ protected:
         const label maxLevels_;
 
         //- Number of cells in coarsest level
-        const label nCellsInCoarsestLevel_;
+        label nCellsInCoarsestLevel_;
 
         //- Cached mesh interfaces
         const lduInterfacePtrsList meshInterfaces_;
@@ -242,7 +242,7 @@ public:
         );
 
         //- Runtime selection table for matrix or mixed geometric/matrix
-        //  agglomerators
+        //- agglomerators
         declareRunTimeSelectionTable
         (
             autoPtr,
@@ -259,7 +259,7 @@ public:
         );
 
         //- Runtime selection table for matrix or mixed geometric/matrix
-        //  agglomerators
+        //- agglomerators
         declareRunTimeSelectionTable
         (
             autoPtr,
@@ -378,7 +378,7 @@ public:
             }
 
             //- Return number of coarse patch faces (before processor
-            //  agglomeration)
+            //- agglomeration)
             const labelList& nPatchFaces(const label leveli) const
             {
                 return nPatchFaces_[leveli];
@@ -452,14 +452,14 @@ public:
             }
 
             //- Mapping from processor to agglomerated processor (global, all
-            //  processors have the same information). Note that level is
-            //  the fine, not the coarse, level index. This is to be
-            //  consistent with the way the restriction is stored
+            //- processors have the same information). Note that level is
+            //- the fine, not the coarse, level index. This is to be
+            //- consistent with the way the restriction is stored
             const labelList& procAgglomMap(const label fineLeveli) const;
 
             //- Set of processors to agglomerate. Element 0 is the
-            //  master processor. (local, same only on those processors that
-            //  agglomerate)
+            //- master processor. (local, same only on those processors that
+            //- agglomerate)
             const labelList& agglomProcIDs(const label fineLeveli) const;
 
             //- Check that level has combined mesh
-- 
GitLab