From 2e5259107f39641af210e6c6dddbd4edd07c263f Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Tue, 22 Jan 2019 22:36:46 +0100
Subject: [PATCH] Implement AMG for scalar-valued matrices

---
 dune/istl/paamg/aggregates.hh   | 28 ++++++++++++++++++++++++++--
 dune/istl/paamg/amg.hh          | 10 +++++++++-
 dune/istl/paamg/test/amgtest.cc |  7 +++++++
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/dune/istl/paamg/aggregates.hh b/dune/istl/paamg/aggregates.hh
index cf0bdd9cd..a2a17659b 100644
--- a/dune/istl/paamg/aggregates.hh
+++ b/dune/istl/paamg/aggregates.hh
@@ -9,6 +9,7 @@
 #include "properties.hh"
 #include "combinedfunctor.hh"
 
+#include <dune/common/hybridutilities.hh>
 #include <dune/common/timer.hh>
 #include <dune/common/stdstreams.hh>
 #include <dune/common/poolallocator.hh>
@@ -382,7 +383,8 @@ namespace Dune
        * @param m The matrix to compute the norm of
        */
       template<class M>
-      typename FieldTraits<typename M::field_type>::real_type operator()(const M& m) const
+      typename FieldTraits<typename M::field_type>::real_type operator()(const M& m,
+                                                                         typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr) const
       {
         typedef typename M::field_type field_type;
         typedef typename FieldTraits<field_type>::real_type real_type;
@@ -392,6 +394,21 @@ namespace Dune
         // possible implementation for complex types: return signed_abs(m[N][N]);
       }
 
+      /**
+       * @brief Compute the norm of a scalar
+       * @param m The scalar to compute the norm of
+       */
+      template<class M>
+      auto operator()(const M& m,
+                      typename std::enable_if_t<Dune::IsNumber<M>::value>* sfinae = nullptr) const
+      {
+        typedef typename FieldTraits<M>::real_type real_type;
+        static_assert( std::is_convertible<M, real_type >::value,
+                  "use of diagonal norm in AMG not implemented for complex field_type");
+        return m;
+        // possible implementation for complex types: return signed_abs(m[N][N]);
+      }
+
     private:
 
       //! return sign * abs_value; for real numbers this is just v
@@ -1813,7 +1830,14 @@ namespace Dune
           for(ColIterator col = row.begin(); col != end; ++col)
             if(col.index()!=*vertex) {
               criterion.examine(col);
-              absoffdiag = max(absoffdiag, col->frobenius_norm());
+              Hybrid::ifElse(IsNumber<typename Matrix::block_type>(),
+                [&](auto id) {
+                  using std::abs;
+                  absoffdiag = max(absoffdiag, abs(*id(col)));
+                },
+                [&](auto id) {
+                  absoffdiag = max(absoffdiag, id(col)->frobenius_norm());
+                });
             }
 
           if(absoffdiag==0)
diff --git a/dune/istl/paamg/amg.hh b/dune/istl/paamg/amg.hh
index 44ce9c3e5..7551b8dda 100644
--- a/dune/istl/paamg/amg.hh
+++ b/dune/istl/paamg/amg.hh
@@ -584,7 +584,15 @@ namespace Dune
           }
         }
         if(isDirichlet && hasDiagonal)
-          diagonal.solve(x[row.index()], b[row.index()]);
+        {
+          Hybrid::ifElse(IsNumber<Block>(),
+            [&](auto id) {
+              x[row.index()] = id(diagonal) / b[row.index()];
+            },
+            [&](auto id) {
+              id(diagonal).solve(x[row.index()], b[row.index()]);
+            });
+        }
       }
 
       if(smoothers_->levels()>0)
diff --git a/dune/istl/paamg/test/amgtest.cc b/dune/istl/paamg/test/amgtest.cc
index 826496d29..d3be925cc 100644
--- a/dune/istl/paamg/test/amgtest.cc
+++ b/dune/istl/paamg/test/amgtest.cc
@@ -179,6 +179,13 @@ try
   if(argc>3)
     ml = atoi(argv[3]);
 
+  {
+    using Matrix = Dune::BCRSMatrix<XREAL>;
+    using Vector = Dune::BlockVector<XREAL>;
+
+    testAMG<Matrix,Vector>(N, coarsenTarget, ml);
+  }
+
   {
     using Matrix = Dune::BCRSMatrix<Dune::FieldMatrix<XREAL,1,1> >;
     using Vector = Dune::BlockVector<Dune::FieldVector<XREAL,1> >;
-- 
GitLab