From 44fc18c4a657f16f1a3d603ff9db0efa7194a795 Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Thu, 10 Dec 2015 19:56:22 +0100
Subject: [PATCH] MultiTypeBlockVector: Fix NaN behaviour of infinity_norm()

---
 dune/istl/multitypeblockvector.hh | 37 ++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/dune/istl/multitypeblockvector.hh b/dune/istl/multitypeblockvector.hh
index dfc72d2fe..90fa3c874 100644
--- a/dune/istl/multitypeblockvector.hh
+++ b/dune/istl/multitypeblockvector.hh
@@ -233,12 +233,38 @@ namespace Dune {
      Each element of the vector has to provide the method "infinity_norm()"
      in order to calculate the whole vector's norm.
    */
-  template<int count, typename T>
+  template<int count, typename T,
+           bool hasNaN = has_nan<typename T::field_type>::value>
   class MultiTypeBlockVector_InfinityNorm {
   public:
     typedef typename T::field_type field_type;
     typedef typename FieldTraits<field_type>::real_type real_type;
 
+    /**
+     * Take the maximum over all elements' norms
+     */
+    static real_type result (const T& a)
+    {
+      std::pair<real_type, real_type> const ret = resultHelper(a);
+      return ret.first * (ret.second / ret.second);
+    }
+
+    // Computes the maximum while keeping track of NaN values
+    static std::pair<real_type, real_type> resultHelper(const T& a) {
+      using std::max;
+      auto const rest =
+          MultiTypeBlockVector_InfinityNorm<count - 1, T>::resultHelper(a);
+      real_type const norm = std::get<count - 1>(a).infinity_norm();
+      return {max(norm, rest.first), norm + rest.second};
+    }
+  };
+
+  template <int count, typename T>
+  class MultiTypeBlockVector_InfinityNorm<count, T, false> {
+  public:
+    typedef typename T::field_type field_type;
+    typedef typename FieldTraits<field_type>::real_type real_type;
+
     /**
      * Take the maximum over all elements' norms
      */
@@ -249,8 +275,8 @@ namespace Dune {
     }
   };
 
-  template<typename T>                                    //recursion end
-  class MultiTypeBlockVector_InfinityNorm<0,T> {
+  template<typename T, bool hasNaN>                       //recursion end
+  class MultiTypeBlockVector_InfinityNorm<0,T, hasNaN> {
   public:
     typedef typename T::field_type field_type;
     typedef typename FieldTraits<field_type>::real_type real_type;
@@ -258,6 +284,11 @@ namespace Dune {
     {
       return 0.0;
     }
+
+    static std::pair<real_type,real_type> resultHelper (const T&)
+    {
+      return {0.0, 1.0};
+    }
   };
 
   /**
-- 
GitLab