]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add ecl partitioners 9156/head
authorPeter Munch <peterrmuench@gmail.com>
Sun, 8 Dec 2019 23:18:19 +0000 (00:18 +0100)
committerPeter Munch <peterrmuench@gmail.com>
Wed, 29 Jan 2020 10:15:15 +0000 (11:15 +0100)
include/deal.II/matrix_free/dof_info.h
include/deal.II/matrix_free/matrix_free.h
include/deal.II/matrix_free/matrix_free.templates.h
tests/matrix_free/partitioner_01.cc [new file with mode: 0644]
tests/matrix_free/partitioner_01.with_mpi=true.with_p4est=true.mpirun=2.output [new file with mode: 0644]

index 9104a7d019972319955522cae0189c6d1899e5e2..8e1ffdd10639db5539a189baf4d2941bac4c60e5 100644 (file)
@@ -486,7 +486,7 @@ namespace internal
        * the indices for evaluation both the function values and the gradients
        * on the faces adjacent to the locally owned cells.
        */
-      std::array<std::shared_ptr<const Utilities::MPI::Partitioner>, 3>
+      std::array<std::shared_ptr<const Utilities::MPI::Partitioner>, 5>
         vector_partitioner_face_variants;
 
       /**
index df97932f76de8a72248d885f2e38eae271ea20b9..580e427789d11acd4a2abdb1f59655f3ca19c6a7 100644 (file)
@@ -725,6 +725,16 @@ public:
      */
     values,
 
+    /**
+     * Same as above. To be used if data has to be accessed from exterior faces
+     * if FEFaceEvaluation was reinitialized by providing the cell batch number
+     * and a face number. This configuration is useful in the context of
+     * cell-centric loops.
+     *
+     * @pre AdditionalData::hold_all_faces_to_owned_cells has to enabled.
+     */
+    values_all_faces,
+
     /**
      * The loop does involve FEFaceEvaluation access into neighbors by
      * function values and gradients, but no second derivatives, such as
@@ -737,6 +747,16 @@ public:
      */
     gradients,
 
+    /**
+     * Same as above. To be used if data has to be accessed from exterior faces
+     * if FEFaceEvaluation was reinitialized by providing the cell batch number
+     * and a face number. This configuration is useful in the context of
+     * cell-centric loops.
+     *
+     * @pre AdditionalData::hold_all_faces_to_owned_cells has to enabled.
+     */
+    gradients_all_faces,
+
     /**
      * General setup where the user does not want to make a restriction. This
      * is typically more expensive than the other options, but also the most
@@ -2946,7 +2966,7 @@ namespace internal
         for (unsigned int c = 0; c < matrix_free.n_components(); ++c)
           AssertDimension(
             matrix_free.get_dof_info(c).vector_partitioner_face_variants.size(),
-            3);
+            5);
     }
 
 
@@ -3003,7 +3023,7 @@ namespace internal
     {
       AssertDimension(matrix_free.get_dof_info(mf_component)
                         .vector_partitioner_face_variants.size(),
-                      3);
+                      5);
       if (vector_face_access ==
           dealii::MatrixFree<dim, Number, VectorizedArrayType>::
             DataAccessOnFaces::none)
@@ -3014,9 +3034,21 @@ namespace internal
                  DataAccessOnFaces::values)
         return *matrix_free.get_dof_info(mf_component)
                   .vector_partitioner_face_variants[1];
-      else
+      else if (vector_face_access ==
+               dealii::MatrixFree<dim, Number, VectorizedArrayType>::
+                 DataAccessOnFaces::gradients)
         return *matrix_free.get_dof_info(mf_component)
                   .vector_partitioner_face_variants[2];
+      else if (vector_face_access ==
+               dealii::MatrixFree<dim, Number, VectorizedArrayType>::
+                 DataAccessOnFaces::values_all_faces)
+        return *matrix_free.get_dof_info(mf_component)
+                  .vector_partitioner_face_variants[3];
+      else /*if (vector_face_access ==
+               dealii::MatrixFree<dim,
+              Number>::DataAccessOnFaces::gradients_all_faces)*/
+        return *matrix_free.get_dof_info(mf_component)
+                  .vector_partitioner_face_variants[4];
     }
 
 
index 8db758b14e9a8f2b8bf4bd1da4dddacb9f24323d..7661b7278eefb2c325208175ad7bb8e73b52acea 100644 (file)
@@ -1484,7 +1484,7 @@ MatrixFree<dim, Number, VectorizedArrayType>::initialize_indices(
         true);
       face_info.cell_and_face_boundary_id.fill(numbers::invalid_boundary_id);
 
-      for (unsigned int f = 0; f < task_info.boundary_partition_data.back();
+      for (unsigned int f = 0; f < task_info.ghost_face_partition_data.back();
            ++f)
         for (unsigned int v = 0; v < VectorizedArrayType::n_array_elements &&
                                  face_info.faces[f].cells_interior[v] !=
@@ -1589,205 +1589,304 @@ MatrixFree<dim, Number, VectorizedArrayType>::initialize_indices(
               }
           }
 
-          // partitioner 1: values on faces
-          {
-            bool all_nodal = true;
-            for (unsigned int c = 0; c < di.n_base_elements; ++c)
-              if (!shape_info(di.global_base_element_offset + c, 0, 0, 0)
-                     .nodal_at_cell_boundaries)
-                all_nodal = false;
-            if (all_nodal == false)
-              di.vector_partitioner_face_variants[1] = di.vector_partitioner;
-            else
-              {
-                bool has_noncontiguous_cell = false;
-                for (unsigned int f = 0; f < n_inner_face_batches(); ++f)
-                  for (unsigned int v = 0;
-                       v < VectorizedArrayType::n_array_elements &&
-                       face_info.faces[f].cells_interior[v] !=
-                         numbers::invalid_unsigned_int;
-                       ++v)
-                    {
-                      AssertIndexRange(face_info.faces[f].cells_interior[v],
-                                       n_macro_cells_before *
-                                         VectorizedArrayType::n_array_elements);
-                      if (di.index_storage_variants
-                              [internal::MatrixFreeFunctions::DoFInfo::
-                                 dof_access_face_exterior][f] >=
-                            internal::MatrixFreeFunctions::DoFInfo::
-                              IndexStorageVariants::contiguous &&
-                          di.dof_indices_contiguous
-                              [internal::MatrixFreeFunctions::DoFInfo::
-                                 dof_access_cell]
-                              [face_info.faces[f].cells_exterior[v]] >=
-                            part.local_size())
-                        {
-                          const unsigned int p =
-                            face_info.faces[f].cells_exterior[v];
-                          const unsigned int stride =
-                            di.dof_indices_interleave_strides[2][p];
-                          unsigned int i = 0;
-                          for (unsigned int e = 0; e < di.n_base_elements; ++e)
-                            for (unsigned int c = 0; c < di.n_components[e];
-                                 ++c)
-                              {
-                                const internal::MatrixFreeFunctions::ShapeInfo<
-                                  VectorizedArrayType> &shape =
-                                  shape_info(di.global_base_element_offset + e,
-                                             0,
-                                             0,
-                                             0);
-                                for (unsigned int j = 0;
-                                     j < shape.dofs_per_component_on_face;
-                                     ++j)
-                                  ghost_indices.push_back(part.local_to_global(
-                                    di.dof_indices_contiguous
-                                      [internal::MatrixFreeFunctions::DoFInfo::
-                                         dof_access_cell][p] +
-                                    i +
-                                    shape.face_to_cell_index_nodal(
-                                      face_info.faces[f].exterior_face_no, j) *
-                                      stride));
-                                i += shape.dofs_per_component_on_cell * stride;
-                              }
-                          AssertDimension(i, di.dofs_per_cell[0] * stride);
-                        }
-                      else if (di.index_storage_variants
-                                 [internal::MatrixFreeFunctions::DoFInfo::
-                                    dof_access_face_exterior][f] <
-                               internal::MatrixFreeFunctions::DoFInfo::
-                                 IndexStorageVariants::contiguous)
-                        has_noncontiguous_cell = true;
-                    }
-                has_noncontiguous_cell =
-                  Utilities::MPI::min<int>(has_noncontiguous_cell,
-                                           task_info.communicator) != 0;
-
-                std::sort(ghost_indices.begin(), ghost_indices.end());
-                ghost_indices.erase(std::unique(ghost_indices.begin(),
-                                                ghost_indices.end()),
-                                    ghost_indices.end());
-                IndexSet compressed_set(part.size());
-                compressed_set.add_indices(ghost_indices.begin(),
-                                           ghost_indices.end());
-                compressed_set.subtract_set(
-                  di.vector_partitioner->locally_owned_range());
-                const bool all_ghosts_equal =
-                  Utilities::MPI::min<int>(
-                    compressed_set.n_elements() ==
-                      di.vector_partitioner->ghost_indices().n_elements(),
-                    di.vector_partitioner->get_mpi_communicator()) != 0;
-                if (all_ghosts_equal || has_noncontiguous_cell)
-                  di.vector_partitioner_face_variants[1] =
-                    di.vector_partitioner;
-                else
+          const auto loop_over_faces =
+            [&](const std::function<void(const unsigned int,
+                                         const unsigned int,
+                                         const unsigned int,
+                                         const unsigned int,
+                                         const bool,
+                                         const bool)> &fu) {
+              for (unsigned int f = 0; f < n_inner_face_batches(); ++f)
+                for (unsigned int v = 0;
+                     v < VectorizedArrayType::n_array_elements &&
+                     face_info.faces[f].cells_interior[v] !=
+                       numbers::invalid_unsigned_int;
+                     ++v)
                   {
-                    di.vector_partitioner_face_variants[1].reset(
-                      new Utilities::MPI::Partitioner(
-                        part.locally_owned_range(),
-                        part.get_mpi_communicator()));
-                    const_cast<Utilities::MPI::Partitioner *>(
-                      di.vector_partitioner_face_variants[1].get())
-                      ->set_ghost_indices(compressed_set, part.ghost_indices());
+                    AssertIndexRange(face_info.faces[f].cells_interior[v],
+                                     n_macro_cells_before *
+                                       VectorizedArrayType::n_array_elements);
+                    const unsigned int p = face_info.faces[f].cells_exterior[v];
+                    const unsigned int face_no =
+                      face_info.faces[f].exterior_face_no;
+
+                    fu(p, face_no, f, v, true /*exterior*/, false /*flag*/);
                   }
-              }
-          }
-
-          // partitioner 2: values and gradients on faces
-          {
-            bool all_hermite = true;
-            for (unsigned int c = 0; c < di.n_base_elements; ++c)
-              if (shape_info(di.global_base_element_offset + c, 0, 0, 0)
-                    .element_type !=
-                  internal::MatrixFreeFunctions::tensor_symmetric_hermite)
-                all_hermite = false;
-            if (all_hermite == false ||
-                di.vector_partitioner_face_variants[1].get() ==
-                  di.vector_partitioner.get())
-              di.vector_partitioner_face_variants[2] = di.vector_partitioner;
-            else
-              {
-                for (unsigned int f = 0; f < n_inner_face_batches(); ++f)
+            };
+
+          const auto loop_over_all_faces =
+            [&](const std::function<void(const unsigned int,
+                                         const unsigned int,
+                                         const unsigned int,
+                                         const unsigned int,
+                                         const bool,
+                                         const bool)> &fu) {
+              for (unsigned int c = 0; c < n_cell_batches(); ++c)
+                for (unsigned int d = 0; d < GeometryInfo<dim>::faces_per_cell;
+                     ++d)
                   for (unsigned int v = 0;
-                       v < VectorizedArrayType::n_array_elements &&
-                       face_info.faces[f].cells_interior[v] !=
-                         numbers::invalid_unsigned_int;
+                       v < VectorizedArrayType::n_array_elements;
                        ++v)
                     {
-                      AssertIndexRange(face_info.faces[f].cells_interior[v],
-                                       n_macro_cells_before *
-                                         VectorizedArrayType::n_array_elements);
-                      if (di.index_storage_variants
-                              [internal::MatrixFreeFunctions::DoFInfo::
-                                 dof_access_face_exterior][f] >=
-                            internal::MatrixFreeFunctions::DoFInfo::
-                              IndexStorageVariants::contiguous &&
-                          di.dof_indices_contiguous
-                              [internal::MatrixFreeFunctions::DoFInfo::
-                                 dof_access_cell]
-                              [face_info.faces[f].cells_exterior[v]] >=
-                            part.local_size())
-                        {
-                          const unsigned int p =
-                            face_info.faces[f].cells_exterior[v];
-                          const unsigned int stride =
-                            di.dof_indices_interleave_strides[2][p];
-                          unsigned int i = 0;
-                          for (unsigned int e = 0; e < di.n_base_elements; ++e)
-                            for (unsigned int c = 0; c < di.n_components[e];
-                                 ++c)
-                              {
-                                const internal::MatrixFreeFunctions::ShapeInfo<
-                                  VectorizedArrayType> &shape =
-                                  shape_info(di.global_base_element_offset + e,
-                                             0,
-                                             0,
-                                             0);
-                                for (unsigned int j = 0;
-                                     j < 2 * shape.dofs_per_component_on_face;
-                                     ++j)
-                                  ghost_indices.push_back(part.local_to_global(
-                                    di.dof_indices_contiguous
-                                      [internal::MatrixFreeFunctions::DoFInfo::
-                                         dof_access_cell][p] +
-                                    i +
-                                    shape.face_to_cell_index_hermite(
-                                      face_info.faces[f].exterior_face_no, j) *
-                                      stride));
-                                i += shape.dofs_per_component_on_cell * stride;
-                              }
-                          AssertDimension(i, di.dofs_per_cell[0] * stride);
-                        }
+                      unsigned int f =
+                        this->face_info.cell_and_face_to_plain_faces(c, d, v);
+                      if (f == numbers::invalid_unsigned_int)
+                        continue;
+
+                      const unsigned int v_len =
+                        VectorizedArrayType::n_array_elements;
+                      const unsigned int cell_this = c * v_len + v;
+
+                      const unsigned int cell_m = this->get_face_info(f / v_len)
+                                                    .cells_interior[f % v_len];
+                      const unsigned int cell_p = this->get_face_info(f / v_len)
+                                                    .cells_exterior[f % v_len];
+
+                      const bool ext = cell_this == cell_m;
+
+                      if (ext && cell_p == numbers::invalid_unsigned_int)
+                        continue;
+
+                      const unsigned int p = ext ? cell_p : cell_m;
+                      const unsigned int face_no =
+                        ext ? face_info.faces[f / v_len].exterior_face_no :
+                              face_info.faces[f / v_len].interior_face_no;
+
+                      fu(p, face_no, f / v_len, v, ext, true);
                     }
-                std::sort(ghost_indices.begin(), ghost_indices.end());
-                ghost_indices.erase(std::unique(ghost_indices.begin(),
-                                                ghost_indices.end()),
-                                    ghost_indices.end());
-                IndexSet compressed_set(part.size());
-                compressed_set.add_indices(ghost_indices.begin(),
-                                           ghost_indices.end());
-                compressed_set.subtract_set(
-                  di.vector_partitioner->locally_owned_range());
-                const bool all_ghosts_equal =
-                  Utilities::MPI::min<int>(
-                    compressed_set.n_elements() ==
-                      di.vector_partitioner->ghost_indices().n_elements(),
-                    di.vector_partitioner->get_mpi_communicator()) != 0;
-                if (all_ghosts_equal)
-                  di.vector_partitioner_face_variants[2] =
-                    di.vector_partitioner;
-                else
-                  {
-                    di.vector_partitioner_face_variants[2].reset(
-                      new Utilities::MPI::Partitioner(
-                        part.locally_owned_range(),
-                        part.get_mpi_communicator()));
-                    const_cast<Utilities::MPI::Partitioner *>(
-                      di.vector_partitioner_face_variants[2].get())
-                      ->set_ghost_indices(compressed_set, part.ghost_indices());
-                  }
-              }
-          }
+            };
+
+          const auto process_values =
+            [&](std::shared_ptr<const Utilities::MPI::Partitioner>
+                  &vector_partitioner_values,
+                const std::function<void(
+                  const std::function<void(const unsigned int,
+                                           const unsigned int,
+                                           const unsigned int,
+                                           const unsigned int,
+                                           const bool,
+                                           const bool)> &)> &loop) {
+              bool all_nodal = true;
+              for (unsigned int c = 0; c < di.n_base_elements; ++c)
+                if (!shape_info(di.global_base_element_offset + c, 0, 0, 0)
+                       .nodal_at_cell_boundaries)
+                  all_nodal = false;
+              if (all_nodal == false)
+                vector_partitioner_values = di.vector_partitioner;
+              else
+                {
+                  bool has_noncontiguous_cell = false;
+
+                  loop([&](const unsigned int p,
+                           const unsigned int face_no,
+                           const unsigned int f,
+                           const unsigned int /*v*/,
+                           const bool ext,
+                           const bool flag) {
+                    if (flag ||
+                        (di.index_storage_variants
+                             [ext ? internal::MatrixFreeFunctions::DoFInfo::
+                                      dof_access_face_exterior :
+                                    internal::MatrixFreeFunctions::DoFInfo::
+                                      dof_access_face_interior][f] >=
+                           internal::MatrixFreeFunctions::DoFInfo::
+                             IndexStorageVariants::contiguous &&
+                         di.dof_indices_contiguous
+                             [internal::MatrixFreeFunctions::DoFInfo::
+                                dof_access_cell][p] >= part.local_size()))
+                      {
+                        const unsigned int stride =
+                          di.dof_indices_interleave_strides[2][p];
+                        unsigned int i = 0;
+                        for (unsigned int e = 0; e < di.n_base_elements; ++e)
+                          for (unsigned int c = 0; c < di.n_components[e]; ++c)
+                            {
+                              const internal::MatrixFreeFunctions::ShapeInfo<
+                                VectorizedArrayType> &shape =
+                                shape_info(di.global_base_element_offset + e,
+                                           0,
+                                           0,
+                                           0);
+                              for (unsigned int j = 0;
+                                   j < shape.dofs_per_component_on_face;
+                                   ++j)
+                                ghost_indices.push_back(part.local_to_global(
+                                  di.dof_indices_contiguous
+                                    [internal::MatrixFreeFunctions::DoFInfo::
+                                       dof_access_cell][p] +
+                                  i +
+                                  shape.face_to_cell_index_nodal(face_no, j) *
+                                    stride));
+                              i += shape.dofs_per_component_on_cell * stride;
+                            }
+                        AssertDimension(i, di.dofs_per_cell[0] * stride);
+                      }
+                    else if (di.index_storage_variants
+                               [ext ? internal::MatrixFreeFunctions::DoFInfo::
+                                        dof_access_face_exterior :
+                                      internal::MatrixFreeFunctions::DoFInfo::
+                                        dof_access_face_interior][f] <
+                             internal::MatrixFreeFunctions::DoFInfo::
+                               IndexStorageVariants::contiguous)
+                      has_noncontiguous_cell = true;
+                  });
+                  has_noncontiguous_cell =
+                    Utilities::MPI::min<int>(has_noncontiguous_cell,
+                                             task_info.communicator) != 0;
+
+                  std::sort(ghost_indices.begin(), ghost_indices.end());
+                  ghost_indices.erase(std::unique(ghost_indices.begin(),
+                                                  ghost_indices.end()),
+                                      ghost_indices.end());
+                  IndexSet compressed_set(part.size());
+                  compressed_set.add_indices(ghost_indices.begin(),
+                                             ghost_indices.end());
+                  compressed_set.subtract_set(
+                    di.vector_partitioner->locally_owned_range());
+                  const bool all_ghosts_equal =
+                    Utilities::MPI::min<int>(
+                      compressed_set.n_elements() ==
+                        di.vector_partitioner->ghost_indices().n_elements(),
+                      di.vector_partitioner->get_mpi_communicator()) != 0;
+                  if (all_ghosts_equal || has_noncontiguous_cell)
+                    vector_partitioner_values = di.vector_partitioner;
+                  else
+                    {
+                      vector_partitioner_values.reset(
+                        new Utilities::MPI::Partitioner(
+                          part.locally_owned_range(),
+                          part.get_mpi_communicator()));
+                      const_cast<Utilities::MPI::Partitioner *>(
+                        vector_partitioner_values.get())
+                        ->set_ghost_indices(compressed_set,
+                                            part.ghost_indices());
+                    }
+                }
+            };
+
+
+          const auto process_gradients =
+            [&](const std::shared_ptr<const Utilities::MPI::Partitioner>
+                  &vector_partitoner_values,
+                std::shared_ptr<const Utilities::MPI::Partitioner>
+                  &vector_partitioner_gradients,
+                const std::function<void(
+                  const std::function<void(const unsigned int,
+                                           const unsigned int,
+                                           const unsigned int,
+                                           const unsigned int,
+                                           const bool,
+                                           const bool)> &)> &loop) {
+              bool all_hermite = true;
+              for (unsigned int c = 0; c < di.n_base_elements; ++c)
+                if (shape_info(di.global_base_element_offset + c, 0, 0, 0)
+                      .element_type !=
+                    internal::MatrixFreeFunctions::tensor_symmetric_hermite)
+                  all_hermite = false;
+              if (all_hermite == false ||
+                  vector_partitoner_values.get() == di.vector_partitioner.get())
+                vector_partitioner_gradients = di.vector_partitioner;
+              else
+                {
+                  loop([&](const unsigned int p,
+                           const unsigned int face_no,
+                           const unsigned int f,
+                           const unsigned int v,
+                           const bool         ext,
+                           const bool         flag) {
+                    AssertIndexRange(face_info.faces[f].cells_interior[v],
+                                     n_macro_cells_before *
+                                       VectorizedArrayType::n_array_elements);
+                    if (flag ||
+                        (di.index_storage_variants
+                             [ext ? internal::MatrixFreeFunctions::DoFInfo::
+                                      dof_access_face_exterior :
+                                    internal::MatrixFreeFunctions::DoFInfo::
+                                      dof_access_face_interior][f] >=
+                           internal::MatrixFreeFunctions::DoFInfo::
+                             IndexStorageVariants::contiguous &&
+                         di.dof_indices_contiguous
+                             [internal::MatrixFreeFunctions::DoFInfo::
+                                dof_access_cell][p] >= part.local_size()))
+                      {
+                        const unsigned int stride =
+                          di.dof_indices_interleave_strides[2][p];
+                        unsigned int i = 0;
+                        for (unsigned int e = 0; e < di.n_base_elements; ++e)
+                          for (unsigned int c = 0; c < di.n_components[e]; ++c)
+                            {
+                              const internal::MatrixFreeFunctions::ShapeInfo<
+                                VectorizedArrayType> &shape =
+                                shape_info(di.global_base_element_offset + e,
+                                           0,
+                                           0,
+                                           0);
+                              for (unsigned int j = 0;
+                                   j < 2 * shape.dofs_per_component_on_face;
+                                   ++j)
+                                ghost_indices.push_back(part.local_to_global(
+                                  di.dof_indices_contiguous
+                                    [internal::MatrixFreeFunctions::DoFInfo::
+                                       dof_access_cell][p] +
+                                  i +
+                                  shape.face_to_cell_index_hermite(face_no, j) *
+                                    stride));
+                              i += shape.dofs_per_component_on_cell * stride;
+                            }
+                        AssertDimension(i, di.dofs_per_cell[0] * stride);
+                      }
+                  });
+                  std::sort(ghost_indices.begin(), ghost_indices.end());
+                  ghost_indices.erase(std::unique(ghost_indices.begin(),
+                                                  ghost_indices.end()),
+                                      ghost_indices.end());
+                  IndexSet compressed_set(part.size());
+                  compressed_set.add_indices(ghost_indices.begin(),
+                                             ghost_indices.end());
+                  compressed_set.subtract_set(
+                    di.vector_partitioner->locally_owned_range());
+                  const bool all_ghosts_equal =
+                    Utilities::MPI::min<int>(
+                      compressed_set.n_elements() ==
+                        di.vector_partitioner->ghost_indices().n_elements(),
+                      di.vector_partitioner->get_mpi_communicator()) != 0;
+                  if (all_ghosts_equal)
+                    vector_partitioner_gradients = di.vector_partitioner;
+                  else
+                    {
+                      vector_partitioner_gradients.reset(
+                        new Utilities::MPI::Partitioner(
+                          part.locally_owned_range(),
+                          part.get_mpi_communicator()));
+                      const_cast<Utilities::MPI::Partitioner *>(
+                        vector_partitioner_gradients.get())
+                        ->set_ghost_indices(compressed_set,
+                                            part.ghost_indices());
+                    }
+                }
+            };
+
+          // partitioner 1: values on faces
+          process_values(di.vector_partitioner_face_variants[1],
+                         loop_over_faces);
+
+          // partitioner 2: values and gradients on faces
+          process_gradients(di.vector_partitioner_face_variants[1],
+                            di.vector_partitioner_face_variants[2],
+                            loop_over_faces);
+
+
+          if (additional_data.hold_all_faces_to_owned_cells)
+            {
+              ghost_indices.clear();
+              // partitioner 3: values on all faces
+              process_values(di.vector_partitioner_face_variants[3],
+                             loop_over_all_faces);
+              // partitioner 4: values and gradients on faces
+              process_gradients(di.vector_partitioner_face_variants[3],
+                                di.vector_partitioner_face_variants[4],
+                                loop_over_all_faces);
+            }
         }
     }
 
diff --git a/tests/matrix_free/partitioner_01.cc b/tests/matrix_free/partitioner_01.cc
new file mode 100644 (file)
index 0000000..9298e1d
--- /dev/null
@@ -0,0 +1,205 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 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.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// tests matrix-free partitioners for update_ghost_values and compress(add)
+
+
+#include <deal.II/base/mpi.h>
+#include <deal.II/base/quadrature_lib.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/mapping_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+#include <deal.II/matrix_free/matrix_free.h>
+
+#include <deal.II/multigrid/mg_constrained_dofs.h>
+
+#include "../tests.h"
+
+using namespace dealii;
+
+template <int dim,
+          typename Number              = double,
+          typename VectorizedArrayType = VectorizedArray<Number>>
+class Test
+{
+public:
+  using VectorType = LinearAlgebra::distributed::Vector<Number>;
+
+  void
+  run(unsigned int fe_degree)
+  {
+    // test FE_DGQ
+    run(fe_degree, FE_DGQ<dim>(fe_degree));
+    // test FE_Q
+    run(fe_degree, FE_DGQHermite<dim>(fe_degree));
+  }
+
+  void
+  run(unsigned int fe_degree, const FiniteElement<dim> &fe)
+  {
+    // test different update flags
+    run(
+      fe_degree,
+      fe,
+      MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces::values);
+    run(fe_degree,
+        fe,
+        MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces::
+          values_all_faces);
+    run(fe_degree,
+        fe,
+        MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces::
+          gradients);
+    run(fe_degree,
+        fe,
+        MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces::
+          gradients_all_faces);
+    run(fe_degree,
+        fe,
+        MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces::
+          unspecified);
+  }
+
+
+private:
+  void
+  run(unsigned int              fe_degree,
+      const FiniteElement<dim> &fe,
+      typename MatrixFree<dim, Number, VectorizedArrayType>::DataAccessOnFaces
+        update_flag)
+  {
+    this->fe_degree = fe_degree;
+
+    parallel::distributed::Triangulation<dim> tria(MPI_COMM_WORLD);
+
+    {
+      std::vector<unsigned int> repetitions(dim, 1);
+      repetitions[0] = 2;
+
+      Point<dim> p1, p2;
+
+      for (unsigned int d = 0; d < dim; d++)
+        p2[d] = 1.0;
+
+      GridGenerator::subdivided_hyper_rectangle(tria, repetitions, p1, p2);
+    }
+
+    DoFHandler<dim> dof_handler(tria);
+    dof_handler.distribute_dofs(fe);
+
+    MappingQ<dim> mapping(1);
+
+    QGauss<1> quad(fe_degree + 1);
+
+    AffineConstraints<Number> constraint;
+    constraint.close();
+
+    typename MatrixFree<dim, Number, VectorizedArrayType>::AdditionalData
+      additional_data;
+    additional_data.tasks_parallel_scheme =
+      MatrixFree<dim, Number, VectorizedArrayType>::AdditionalData::none;
+    additional_data.mapping_update_flags =
+      update_gradients | update_JxW_values | update_quadrature_points;
+    additional_data.mapping_update_flags_inner_faces =
+      update_gradients | update_JxW_values | update_quadrature_points;
+    additional_data.mapping_update_flags_boundary_faces =
+      update_gradients | update_JxW_values | update_quadrature_points;
+    additional_data.mapping_update_flags_faces_by_cells =
+      update_gradients | update_JxW_values | update_quadrature_points;
+    additional_data.hold_all_faces_to_owned_cells = true;
+
+    MatrixFree<dim, Number, VectorizedArrayType> matrix_free;
+
+    matrix_free.reinit(mapping, dof_handler, constraint, quad, additional_data);
+
+    VectorType src, dst;
+    matrix_free.initialize_dof_vector(src);
+    matrix_free.initialize_dof_vector(dst);
+
+    for (unsigned int i = 0; i < Utilities::pow(fe_degree + 1, dim); i++)
+      src.begin()[i] = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) + 1;
+
+    matrix_free.loop(&Test::dummy_operation_1,
+                     &Test::dummy_operation_2,
+                     &Test::dummy_operation_2,
+                     this,
+                     dst,
+                     src,
+                     false,
+                     update_flag,
+                     update_flag);
+
+    deallog << "dst:" << std::endl;
+    for (unsigned int i = Utilities::pow(fe_degree + 1, dim);
+         i < 2 * Utilities::pow(fe_degree + 1, dim);
+         i++)
+      dst.begin()[i] = 0;
+    for (unsigned int i = 0; i < 2 * Utilities::pow(fe_degree + 1, dim); i++)
+      deallog << static_cast<int>(dst[i]) << " ";
+    deallog << std::endl << std::endl;
+  }
+
+  void
+  dummy_operation_1(const MatrixFree<dim, Number, VectorizedArrayType> &,
+                    VectorType &      dst,
+                    const VectorType &src,
+                    const std::pair<unsigned int, unsigned int> &) const
+  {
+    deallog << "src:" << std::endl;
+    for (unsigned int i = 0; i < 2 * Utilities::pow(fe_degree + 1, dim); i++)
+      deallog << static_cast<int>(src[i]) << " ";
+    deallog << std::endl;
+
+    for (unsigned int i = Utilities::pow(fe_degree + 1, dim);
+         i < 2 * Utilities::pow(fe_degree + 1, dim);
+         i++)
+      dst.begin()[i] = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) + 1;
+  }
+
+  void
+  dummy_operation_2(const MatrixFree<dim, Number, VectorizedArrayType> &,
+                    VectorType &,
+                    const VectorType &,
+                    const std::pair<unsigned int, unsigned int> &) const
+  {}
+
+  unsigned int fe_degree;
+};
+
+
+int
+main(int argc, char **argv)
+{
+  Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv, 1);
+
+  MPILogInitAll all;
+
+  {
+    deallog.push("2d");
+    Test<2> runner;
+    runner.run(3);
+    deallog.pop();
+  }
+}
diff --git a/tests/matrix_free/partitioner_01.with_mpi=true.with_p4est=true.mpirun=2.output b/tests/matrix_free/partitioner_01.with_mpi=true.with_p4est=true.mpirun=2.output
new file mode 100644 (file)
index 0000000..32bc167
--- /dev/null
@@ -0,0 +1,103 @@
+
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:0:2d::dst:
+DEAL:0:2d::2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:0:2d::dst:
+DEAL:0:2d::2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:0:2d::dst:
+DEAL:0:2d::2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 2 2 0 0 2 2 0 0 2 2 0 0 
+DEAL:0:2d::dst:
+DEAL:0:2d::0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+DEAL:0:2d::src:
+DEAL:0:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:0:2d::dst:
+DEAL:0:2d::2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:0:2d::
+
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 
+DEAL:1:2d::
+DEAL:1:2d::src:
+DEAL:1:2d::1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 
+DEAL:1:2d::dst:
+DEAL:1:2d::0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+DEAL:1:2d::
+

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.