]> https://gitweb.dealii.org/ - dealii.git/commitdiff
MGLevelGlobalTransfer/MGTransferMatrixFree: allow user to init vectors 11871/head
authorPeter Munch <peterrmuench@gmail.com>
Mon, 8 Mar 2021 21:13:23 +0000 (22:13 +0100)
committerPeter Munch <peterrmuench@gmail.com>
Wed, 9 Mar 2022 16:48:21 +0000 (17:48 +0100)
doc/news/changes/minor/20210309Munch [new file with mode: 0644]
include/deal.II/multigrid/mg_transfer.h
include/deal.II/multigrid/mg_transfer.templates.h
include/deal.II/multigrid/mg_transfer_matrix_free.h
source/multigrid/mg_transfer_matrix_free.cc
tests/matrix_free/multigrid_dg_sip_01.cc

diff --git a/doc/news/changes/minor/20210309Munch b/doc/news/changes/minor/20210309Munch
new file mode 100644 (file)
index 0000000..e6b3b60
--- /dev/null
@@ -0,0 +1,7 @@
+New: The class MGTransferMatrixFree::build() now also
+accepts an optional function for initializing the internal level vectors. 
+This is useful if one uses the the transfer operators in the context of 
+smoothers that are built around MatrixFree objects.
+<br>
+(Peter Munch, 2021/03/09)
+
index b20acc46aaec85e2956467b556d3a0098ffbcff3..021f53e2625715f716aaa1b7117e4a54bec2ff30 100644 (file)
@@ -611,6 +611,13 @@ protected:
   mutable MGLevelObject<LinearAlgebra::distributed::Vector<Number>>
     solution_ghosted_level_vector;
 
+  /**
+   * Function to initialize internal level vectors.
+   */
+  std::function<void(const unsigned int,
+                     LinearAlgebra::distributed::Vector<Number> &)>
+    initialize_dof_vector;
+
 private:
   /**
    * This function is called to make sure that build() has been invoked.
index 2b8c186bf406ee6c43d315d67d90b26fcf924d76..4941974466795bd36249c082deb22db13b22db37 100644 (file)
@@ -438,14 +438,15 @@ MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number>>::copy_to_mg(
         // In case a ghosted level vector has been initialized, we can simply
         // use that as a template for the vector partitioning. If not, we
         // resort to the locally owned range of the dof handler.
-        if (level <= ghosted_level_vector.max_level() &&
-            ghosted_level_vector[level].size() == dof_handler.n_dofs(level))
+        if (initialize_dof_vector)
+          initialize_dof_vector(level, dst[level]);
+        else if (level <= ghosted_level_vector.max_level() &&
+                 ghosted_level_vector[level].size() ==
+                   dof_handler.n_dofs(level))
           dst[level].reinit(ghosted_level_vector[level], false);
         else
-          {
-            dst[level].reinit(dof_handler.locally_owned_mg_dofs(level),
-                              dof_handler.get_communicator());
-          }
+          dst[level].reinit(dof_handler.locally_owned_mg_dofs(level),
+                            dof_handler.get_communicator());
       }
     else if ((perform_plain_copy == false &&
               perform_renumbered_plain_copy == false) ||
@@ -561,20 +562,29 @@ MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number>>::copy_from_mg(
     {
       // the ghosted vector should already have the correct local size (but
       // different parallel layout)
-      AssertDimension(ghosted_level_vector[level].locally_owned_size(),
-                      src[level].locally_owned_size());
+      if (ghosted_level_vector[level].size() > 0)
+        AssertDimension(ghosted_level_vector[level].locally_owned_size(),
+                        src[level].locally_owned_size());
 
       // the first time around, we copy the source vector to the temporary
       // vector that we hold for the purpose of data exchange
       LinearAlgebra::distributed::Vector<Number> &ghosted_vector =
         ghosted_level_vector[level];
-      ghosted_vector = src[level];
-      ghosted_vector.update_ghost_values();
+
+      if (ghosted_level_vector[level].size() > 0)
+        ghosted_vector = src[level];
+
+      const auto ghosted_vector_ptr = (ghosted_level_vector[level].size() > 0) ?
+                                        &ghosted_vector :
+                                        &src[level];
+
+      ghosted_vector_ptr->update_ghost_values();
+
 
       auto copy_unknowns = [&](const Table<2, unsigned int> &indices) {
         for (unsigned int i = 0; i < indices.n_cols(); ++i)
           dst.local_element(indices(0, i)) =
-            ghosted_vector.local_element(indices(1, i));
+            ghosted_vector_ptr->local_element(indices(1, i));
       };
 
       // first copy local unknowns
index f87fff7d480c13f710208a05ef23fe5480255133..3e558e0954bd9d1eaa7f26b7e3c7226b2b79ef65 100644 (file)
@@ -105,6 +105,16 @@ public:
           &external_partitioners =
             std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>());
 
+  /**
+   * Same as above but taking a lambda for initializing vector instead of
+   * partitioners.
+   */
+  void
+  build(const DoFHandler<dim, dim> &dof_handler,
+        const std::function<void(const unsigned int,
+                                 LinearAlgebra::distributed::Vector<Number> &)>
+          &initialize_dof_vector);
+
   /**
    * Prolongate a vector from level <tt>to_level-1</tt> to level
    * <tt>to_level</tt> using the embedding matrices of the underlying finite
index 8010b0fa6f028ccf4dd4bc7ff079b80aa2f92c81..6cb316961776f00e2a76ebc1abf1bd1c770e6966 100644 (file)
@@ -93,6 +93,7 @@ MGTransferMatrixFree<dim, Number>::clear()
 }
 
 
+
 template <int dim, typename Number>
 void
 MGTransferMatrixFree<dim, Number>::build(
@@ -106,6 +107,20 @@ MGTransferMatrixFree<dim, Number>::build(
            "distribute_mg_dofs() function called, but this is a prerequisite "
            "for multigrid transfers. You will need to call this function, "
            "probably close to where you already call distribute_dofs()."));
+  if (external_partitioners.size() > 0)
+    {
+      Assert(
+        this->initialize_dof_vector == nullptr,
+        ExcMessage(
+          "A initialize_dof_vector function has already been registered in the constructor!"));
+
+      this->initialize_dof_vector =
+        [external_partitioners](
+          const unsigned int                          level,
+          LinearAlgebra::distributed::Vector<Number> &vec) {
+          vec.reinit(external_partitioners[level]);
+        };
+    }
 
   this->fill_and_communicate_copy_indices(dof_handler);
 
@@ -186,6 +201,39 @@ MGTransferMatrixFree<dim, Number>::build(
 
 
 
+template <int dim, typename Number>
+void
+MGTransferMatrixFree<dim, Number>::build(
+  const DoFHandler<dim, dim> &dof_handler,
+  const std::function<void(const unsigned int,
+                           LinearAlgebra::distributed::Vector<Number> &)>
+    &initialize_dof_vector)
+{
+  if (initialize_dof_vector)
+    {
+      const unsigned int n_levels =
+        dof_handler.get_triangulation().n_global_levels();
+
+      std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
+        external_partitioners(n_levels);
+
+      for (unsigned int level = 0; level < n_levels; ++level)
+        {
+          LinearAlgebra::distributed::Vector<Number> vector;
+          initialize_dof_vector(level, vector);
+          external_partitioners[level] = vector.get_partitioner();
+        }
+
+      build(dof_handler, external_partitioners);
+    }
+  else
+    {
+      build(dof_handler);
+    }
+}
+
+
+
 template <int dim, typename Number>
 void
 MGTransferMatrixFree<dim, Number>::prolongate(
index 381b6155145fcb853554bbab7d951623eba4b3bf..63a436459ae25e8ee094ba55083ce41f4a67117d 100644 (file)
@@ -596,9 +596,11 @@ do_test(const DoFHandler<dim> &dof, const unsigned n_q_points_1d)
   mg_constrained_dofs.initialize(dof);
   mg_constrained_dofs.make_zero_boundary_constraints(dof, {0});
 
-  MGTransferMF<dim, LevelMatrixType> mg_transfer(mg_matrices,
-                                                 mg_constrained_dofs);
-  mg_transfer.build(dof);
+  MGTransferMatrixFree<dim, number> mg_transfer(mg_constrained_dofs);
+
+  mg_transfer.build(dof, [&](const unsigned int level, auto &vec) {
+    mg_matrices[level].initialize_dof_vector(vec);
+  });
 
   mg::Matrix<LinearAlgebra::distributed::Vector<double>> mg_matrix(mg_matrices);
 
@@ -606,7 +608,7 @@ do_test(const DoFHandler<dim> &dof, const unsigned n_q_points_1d)
     mg_matrix, mg_coarse, mg_transfer, mg_smoother, mg_smoother);
   PreconditionMG<dim,
                  LinearAlgebra::distributed::Vector<double>,
-                 MGTransferMF<dim, LevelMatrixType>>
+                 MGTransferMatrixFree<dim, number>>
     preconditioner(dof, mg, mg_transfer);
 
   {

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.