From 2fc52c6525a78dfd9060d94b70d52621bf27ba70 Mon Sep 17 00:00:00 2001
From: Daniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Date: Wed, 25 Jan 2017 11:40:37 +0100
Subject: [PATCH] Fix ConstraintMatrix::merge for empty objects

---
 source/lac/constraint_matrix.cc       | 28 ++++++++---
 tests/lac/constraints_merge_11.cc     | 67 +++++++++++++++++++++++++++
 tests/lac/constraints_merge_11.output |  5 ++
 3 files changed, 94 insertions(+), 6 deletions(-)
 create mode 100644 tests/lac/constraints_merge_11.cc
 create mode 100644 tests/lac/constraints_merge_11.output

diff --git a/source/lac/constraint_matrix.cc b/source/lac/constraint_matrix.cc
index f0b0c1cbdf..920c7d8abb 100644
--- a/source/lac/constraint_matrix.cc
+++ b/source/lac/constraint_matrix.cc
@@ -546,12 +546,28 @@ ConstraintMatrix::merge (const ConstraintMatrix &other_constraints,
       {
         Assert (other_constraints.local_lines.size() !=0, ExcNotImplemented());
         // The last stored index determines the new size of lines_cache
-        const size_type last_stored_index
-          = std::max(local_lines.nth_index_in_set(lines_cache.size()-1),
-                     other_constraints.local_lines.nth_index_in_set(other_constraints.lines_cache.size()-1));
-        // we don't need the old local_lines anymore, so update it
-        local_lines.add_indices(other_constraints.local_lines);
-        new_size = local_lines.index_within_set (last_stored_index)+1;
+        if (lines_cache.size()>0 || other_constraints.lines_cache.size()>0)
+          {
+            // there exist constraints
+            const size_type last_stored_index_own
+              = (lines_cache.size()>0)?
+                local_lines.nth_index_in_set(lines_cache.size()-1):
+                0;
+            const size_type last_stored_index_other
+              = (other_constraints.lines_cache.size()>0)?
+                other_constraints.local_lines.nth_index_in_set(other_constraints.lines_cache.size()-1):
+                0;
+            const size_type last_stored_index = std::max(last_stored_index_own,
+                                                         last_stored_index_other);
+            // we don't need the old local_lines anymore, so update it
+            local_lines.add_indices(other_constraints.local_lines);
+            new_size = local_lines.index_within_set (last_stored_index)+1;
+          }
+        else
+          {
+            // there don't exist constraints
+            new_size = 0;
+          }
       }
     else
       {
diff --git a/tests/lac/constraints_merge_11.cc b/tests/lac/constraints_merge_11.cc
new file mode 100644
index 0000000000..ed3e50e334
--- /dev/null
+++ b/tests/lac/constraints_merge_11.cc
@@ -0,0 +1,67 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Try to merge two empty ConstraintMatrix objects initialized with IndexSets
+// that don't match.
+
+#include "../tests.h"
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/base/logstream.h>
+
+#include <fstream>
+#include <iomanip>
+
+
+void merge_check ()
+{
+  deallog << "Checking ConstraintMatrix::merge with localized lines" << std::endl;
+
+  // set local lines to a very large range that
+  // surely triggers an error if the
+  // implementation is wrong
+  IndexSet local_lines1 (100000000);
+  local_lines1.add_range (99999890, 99999900);
+  local_lines1.add_range (99999990, 99999992);
+  local_lines1.compress();
+  local_lines1.print(deallog.get_file_stream());
+
+  IndexSet local_lines2 (100000000);
+  local_lines2.add_range (99999893, 99999900);
+  local_lines2.add_range (99999990, 100000000);
+  local_lines2.compress();
+  local_lines2.print(deallog.get_file_stream());
+
+  // works correctly
+  ConstraintMatrix c1 (local_lines1), c2 (local_lines2);
+
+  // now merge the two and print the
+  // results
+  c1.merge (c2, ConstraintMatrix::no_conflicts_allowed, true);
+  c1.print(deallog.get_file_stream());
+
+  deallog << "OK" << std::endl;
+}
+
+
+
+int main ()
+{
+  initlog();
+
+  merge_check ();
+}
+
diff --git a/tests/lac/constraints_merge_11.output b/tests/lac/constraints_merge_11.output
new file mode 100644
index 0000000000..1813c34e9f
--- /dev/null
+++ b/tests/lac/constraints_merge_11.output
@@ -0,0 +1,5 @@
+
+DEAL::Checking ConstraintMatrix::merge with localized lines
+{[99999890,99999899], [99999990,99999991]}
+{[99999893,99999899], [99999990,99999999]}
+DEAL::OK
-- 
2.39.5