]> https://gitweb.dealii.org/ - dealii.git/commitdiff
AffineConstraints::merge(): allow mixed numbers 15753/head
authorPeter Munch <peterrmuench@gmail.com>
Sat, 15 Jul 2023 18:00:06 +0000 (20:00 +0200)
committerPeter Munch <peterrmuench@gmail.com>
Sat, 15 Jul 2023 18:01:33 +0000 (20:01 +0200)
include/deal.II/lac/affine_constraints.h
include/deal.II/lac/affine_constraints.templates.h

index 49c1b6425999f6113404333d44f3d38b8cb7f1e8..b786924f4ca5c882257c87968c8f4c948e1b8900 100644 (file)
@@ -821,9 +821,10 @@ public:
    * Merging a AffineConstraints that is initialized with an IndexSet
    * and one that is not initialized with an IndexSet is not yet implemented.
    */
+  template <typename other_number>
   void
   merge(
-    const AffineConstraints &   other_constraints,
+    const AffineConstraints<other_number> &other_constraints,
     const MergeConflictBehavior merge_conflict_behavior = no_conflicts_allowed,
     const bool                  allow_different_local_lines = false);
 
@@ -2468,6 +2469,160 @@ AffineConstraints<number>::copy_from(
 }
 
 
+template <typename number>
+template <typename other_number>
+void
+AffineConstraints<number>::merge(
+  const AffineConstraints<other_number> &other_constraints,
+  const MergeConflictBehavior            merge_conflict_behavior,
+  const bool                             allow_different_local_lines)
+{
+  (void)allow_different_local_lines;
+  Assert(allow_different_local_lines ||
+           local_lines == other_constraints.local_lines,
+         ExcMessage(
+           "local_lines for this and the other objects are not the same "
+           "although allow_different_local_lines is false."));
+
+  // store the previous state with respect to sorting
+  const bool object_was_sorted = sorted;
+  sorted                       = false;
+
+  // first action is to fold into the present object possible constraints
+  // in the second object. we don't strictly need to do this any more since
+  // the AffineConstraints container has learned to deal with chains of
+  // constraints in the close() function, but we have traditionally done
+  // this and it's not overly hard to do.
+  //
+  // for this, loop over all constraints and replace the constraint lines
+  // with a new one where constraints are replaced if necessary.
+  typename ConstraintLine::Entries tmp;
+  for (ConstraintLine &line : lines)
+    {
+      tmp.clear();
+      for (const std::pair<size_type, number> &entry : line.entries)
+        {
+          // if the present dof is not stored, or not constrained, or if we
+          // won't take the constraint from the other object, then simply copy
+          // it over
+          if ((other_constraints.local_lines.size() != 0. &&
+               other_constraints.local_lines.is_element(entry.first) ==
+                 false) ||
+              other_constraints.is_constrained(entry.first) == false ||
+              ((merge_conflict_behavior != right_object_wins) &&
+               other_constraints.is_constrained(entry.first) &&
+               this->is_constrained(entry.first)))
+            tmp.push_back(entry);
+          else
+            // otherwise resolve further constraints by replacing the old
+            // entry by a sequence of new entries taken from the other
+            // object, but with multiplied weights
+            {
+              const auto *other_entries =
+                other_constraints.get_constraint_entries(entry.first);
+              Assert(other_entries != nullptr, ExcInternalError());
+
+              const number weight = entry.second;
+
+              for (const std::pair<size_type, number> &other_entry :
+                   *other_entries)
+                tmp.emplace_back(other_entry.first,
+                                 other_entry.second * weight);
+
+              line.inhomogeneity +=
+                other_constraints.get_inhomogeneity(entry.first) * weight;
+            }
+        }
+      // finally exchange old and newly resolved line
+      line.entries.swap(tmp);
+    }
+
+  if (local_lines.size() != 0)
+    local_lines.add_indices(other_constraints.local_lines);
+
+  {
+    // do not bother to resize the lines cache exactly since it is pretty
+    // cheap to adjust it along the way.
+    std::fill(lines_cache.begin(),
+              lines_cache.end(),
+              numbers::invalid_size_type);
+
+    // reset lines_cache for our own constraints
+    size_type index = 0;
+    for (const ConstraintLine &line : lines)
+      {
+        const size_type local_line_no = calculate_line_index(line.index);
+        if (local_line_no >= lines_cache.size())
+          lines_cache.resize(local_line_no + 1, numbers::invalid_size_type);
+        lines_cache[local_line_no] = index++;
+      }
+
+    // Add other_constraints to lines cache and our list of constraints
+    for (const auto &line : other_constraints.lines)
+      {
+        const size_type local_line_no = calculate_line_index(line.index);
+        if (local_line_no >= lines_cache.size())
+          {
+            lines_cache.resize(local_line_no + 1, numbers::invalid_size_type);
+            lines.emplace_back(line.index,
+                               typename ConstraintLine::Entries(
+                                 line.entries.begin(), line.entries.end()),
+                               line.inhomogeneity);
+            lines_cache[local_line_no] = index++;
+          }
+        else if (lines_cache[local_line_no] == numbers::invalid_size_type)
+          {
+            // there are no constraints for that line yet
+            lines.emplace_back(line.index,
+                               typename ConstraintLine::Entries(
+                                 line.entries.begin(), line.entries.end()),
+                               line.inhomogeneity);
+            AssertIndexRange(local_line_no, lines_cache.size());
+            lines_cache[local_line_no] = index++;
+          }
+        else
+          {
+            // we already store that line
+            switch (merge_conflict_behavior)
+              {
+                case no_conflicts_allowed:
+                  AssertThrow(false,
+                              ExcDoFIsConstrainedFromBothObjects(line.index));
+                  break;
+
+                case left_object_wins:
+                  // ignore this constraint
+                  break;
+
+                case right_object_wins:
+                  AssertIndexRange(local_line_no, lines_cache.size());
+                  lines[lines_cache[local_line_no]] = {
+                    line.index,
+                    typename ConstraintLine::Entries(line.entries.begin(),
+                                                     line.entries.end()),
+                    line.inhomogeneity};
+                  break;
+
+                default:
+                  Assert(false, ExcNotImplemented());
+              }
+          }
+      }
+
+    // check that we set the pointers correctly
+    for (size_type i = 0; i < lines_cache.size(); ++i)
+      if (lines_cache[i] != numbers::invalid_size_type)
+        Assert(i == calculate_line_index(lines[lines_cache[i]].index),
+               ExcInternalError());
+  }
+
+  // if the object was sorted before, then make sure it is so afterward as
+  // well. otherwise leave everything in the unsorted state
+  if (object_was_sorted == true)
+    close();
+}
+
+
 
 template <typename number>
 template <typename MatrixType>
index d465c9f710d95f68bb024f2b498fddb50330f4d5..7f37bbdac14160aed992253eb28d6aadcf854d32 100644 (file)
@@ -1014,149 +1014,6 @@ AffineConstraints<number>::is_closed(const MPI_Comm comm) const
 }
 
 
-template <typename number>
-void
-AffineConstraints<number>::merge(
-  const AffineConstraints<number> &other_constraints,
-  const MergeConflictBehavior      merge_conflict_behavior,
-  const bool                       allow_different_local_lines)
-{
-  (void)allow_different_local_lines;
-  Assert(allow_different_local_lines ||
-           local_lines == other_constraints.local_lines,
-         ExcMessage(
-           "local_lines for this and the other objects are not the same "
-           "although allow_different_local_lines is false."));
-
-  // store the previous state with respect to sorting
-  const bool object_was_sorted = sorted;
-  sorted                       = false;
-
-  // first action is to fold into the present object possible constraints
-  // in the second object. we don't strictly need to do this any more since
-  // the AffineConstraints container has learned to deal with chains of
-  // constraints in the close() function, but we have traditionally done
-  // this and it's not overly hard to do.
-  //
-  // for this, loop over all constraints and replace the constraint lines
-  // with a new one where constraints are replaced if necessary.
-  typename ConstraintLine::Entries tmp;
-  for (ConstraintLine &line : lines)
-    {
-      tmp.clear();
-      for (const std::pair<size_type, number> &entry : line.entries)
-        {
-          // if the present dof is not stored, or not constrained, or if we
-          // won't take the constraint from the other object, then simply copy
-          // it over
-          if ((other_constraints.local_lines.size() != 0. &&
-               other_constraints.local_lines.is_element(entry.first) ==
-                 false) ||
-              other_constraints.is_constrained(entry.first) == false ||
-              ((merge_conflict_behavior != right_object_wins) &&
-               other_constraints.is_constrained(entry.first) &&
-               this->is_constrained(entry.first)))
-            tmp.push_back(entry);
-          else
-            // otherwise resolve further constraints by replacing the old
-            // entry by a sequence of new entries taken from the other
-            // object, but with multiplied weights
-            {
-              const typename ConstraintLine::Entries *other_entries =
-                other_constraints.get_constraint_entries(entry.first);
-              Assert(other_entries != nullptr, ExcInternalError());
-
-              const number weight = entry.second;
-
-              for (const std::pair<size_type, number> &other_entry :
-                   *other_entries)
-                tmp.emplace_back(other_entry.first,
-                                 other_entry.second * weight);
-
-              line.inhomogeneity +=
-                other_constraints.get_inhomogeneity(entry.first) * weight;
-            }
-        }
-      // finally exchange old and newly resolved line
-      line.entries.swap(tmp);
-    }
-
-  if (local_lines.size() != 0)
-    local_lines.add_indices(other_constraints.local_lines);
-
-  {
-    // do not bother to resize the lines cache exactly since it is pretty
-    // cheap to adjust it along the way.
-    std::fill(lines_cache.begin(),
-              lines_cache.end(),
-              numbers::invalid_size_type);
-
-    // reset lines_cache for our own constraints
-    size_type index = 0;
-    for (const ConstraintLine &line : lines)
-      {
-        const size_type local_line_no = calculate_line_index(line.index);
-        if (local_line_no >= lines_cache.size())
-          lines_cache.resize(local_line_no + 1, numbers::invalid_size_type);
-        lines_cache[local_line_no] = index++;
-      }
-
-    // Add other_constraints to lines cache and our list of constraints
-    for (const ConstraintLine &line : other_constraints.lines)
-      {
-        const size_type local_line_no = calculate_line_index(line.index);
-        if (local_line_no >= lines_cache.size())
-          {
-            lines_cache.resize(local_line_no + 1, numbers::invalid_size_type);
-            lines.push_back(line);
-            lines_cache[local_line_no] = index++;
-          }
-        else if (lines_cache[local_line_no] == numbers::invalid_size_type)
-          {
-            // there are no constraints for that line yet
-            lines.push_back(line);
-            AssertIndexRange(local_line_no, lines_cache.size());
-            lines_cache[local_line_no] = index++;
-          }
-        else
-          {
-            // we already store that line
-            switch (merge_conflict_behavior)
-              {
-                case no_conflicts_allowed:
-                  AssertThrow(false,
-                              ExcDoFIsConstrainedFromBothObjects(line.index));
-                  break;
-
-                case left_object_wins:
-                  // ignore this constraint
-                  break;
-
-                case right_object_wins:
-                  AssertIndexRange(local_line_no, lines_cache.size());
-                  lines[lines_cache[local_line_no]] = line;
-                  break;
-
-                default:
-                  Assert(false, ExcNotImplemented());
-              }
-          }
-      }
-
-    // check that we set the pointers correctly
-    for (size_type i = 0; i < lines_cache.size(); ++i)
-      if (lines_cache[i] != numbers::invalid_size_type)
-        Assert(i == calculate_line_index(lines[lines_cache[i]].index),
-               ExcInternalError());
-  }
-
-  // if the object was sorted before, then make sure it is so afterward as
-  // well. otherwise leave everything in the unsorted state
-  if (object_was_sorted == true)
-    close();
-}
-
-
 
 template <typename number>
 void

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.