]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Make DoFTools::count_dofs_per_{component,block} return its data.
authorWolfgang Bangerth <bangerth@colostate.edu>
Thu, 9 Jan 2020 17:15:58 +0000 (10:15 -0700)
committerWolfgang Bangerth <bangerth@colostate.edu>
Thu, 9 Jan 2020 17:15:58 +0000 (10:15 -0700)
Instead of doing so via an output argument. The existing functions are deprecated.

include/deal.II/dofs/dof_tools.h
source/dofs/dof_tools.cc

index cee3ae9e41afd823a13db2373c768a37ad95c6e6..b5a51ae3cf5edbbf7c24c0a8cacb55453ac9ed5c 100644 (file)
@@ -2257,7 +2257,18 @@ namespace DoFTools
    * The indices not targeted by target_components are left untouched.
    */
   template <typename DoFHandlerType>
-  void
+  std::vector<types::global_dof_index>
+  count_dofs_per_component(
+    const DoFHandlerType &           dof_handler,
+    const bool                       vector_valued_once = false,
+    const std::vector<unsigned int> &target_component   = {});
+
+  /**
+   * @deprecated A version of the previous function that returns its
+   * information through the non-`const` second argument.
+   */
+  template <typename DoFHandlerType>
+  DEAL_II_DEPRECATED void
   count_dofs_per_component(
     const DoFHandlerType &                dof_handler,
     std::vector<types::global_dof_index> &dofs_per_component,
@@ -2274,14 +2285,24 @@ namespace DoFTools
    * assertion is thrown.
    *
    * This function is used in the step-22, step-31, and step-32 tutorial
-   * programs.
+   * programs, among others.
    *
    * @pre The dofs_per_block variable has as many components as the finite
    * element used by the dof_handler argument has blocks, or alternatively as
    * many blocks as are enumerated in the target_blocks argument if given.
    */
   template <typename DoFHandlerType>
-  void
+  std::vector<types::global_dof_index>
+  count_dofs_per_block(const DoFHandlerType &           dof,
+                       const std::vector<unsigned int> &target_block =
+                         std::vector<unsigned int>());
+
+  /**
+   * @deprecated A version of the previous function that returns its
+   * information through the non-`const` second argument.
+   */
+  template <typename DoFHandlerType>
+  DEAL_II_DEPRECATED void
   count_dofs_per_block(const DoFHandlerType &                dof,
                        std::vector<types::global_dof_index> &dofs_per_block,
                        const std::vector<unsigned int> &     target_block =
index cc1d0ba1ebc1f1d21a1f009e3fdd8c7847af5065..07693402c311c09c17698ea4d33ff58b35b33d65 100644 (file)
@@ -1902,19 +1902,28 @@ namespace DoFTools
 
 
 
+  // deprecated function
   template <typename DoFHandlerType>
   void
   count_dofs_per_component(
     const DoFHandlerType &                dof_handler,
     std::vector<types::global_dof_index> &dofs_per_component,
     const bool                            only_once,
-    const std::vector<unsigned int> &     target_component_)
+    const std::vector<unsigned int> &     target_component)
   {
-    const unsigned int n_components = dof_handler.get_fe(0).n_components();
+    dofs_per_component =
+      count_dofs_per_component(dof_handler, only_once, target_component);
+  }
+
 
-    std::fill(dofs_per_component.begin(),
-              dofs_per_component.end(),
-              types::global_dof_index(0));
+
+  template <typename DoFHandlerType>
+  std::vector<types::global_dof_index>
+  count_dofs_per_component(const DoFHandlerType &           dof_handler,
+                           const bool                       only_once,
+                           const std::vector<unsigned int> &target_component_)
+  {
+    const unsigned int n_components = dof_handler.get_fe(0).n_components();
 
     // If the empty vector was given as default argument, set up this
     // vector as identity.
@@ -1933,16 +1942,16 @@ namespace DoFTools
     const unsigned int max_component =
       *std::max_element(target_component.begin(), target_component.end());
     const unsigned int n_target_components = max_component + 1;
-    (void)n_target_components; // silence possible warning about unused variable
 
-    AssertDimension(dofs_per_component.size(), n_target_components);
+    std::vector<types::global_dof_index> dofs_per_component(
+      n_target_components, types::global_dof_index(0));
 
     // special case for only one component. treat this first since it does
     // not require any computations
     if (n_components == 1)
       {
         dofs_per_component[0] = dof_handler.n_locally_owned_dofs();
-        return;
+        return dofs_per_component;
       }
 
 
@@ -1995,63 +2004,82 @@ namespace DoFTools
         AssertThrowMPI(ierr);
       }
 #endif
+
+    return dofs_per_component;
   }
 
 
 
+  // deprecated function
   template <typename DoFHandlerType>
   void
   count_dofs_per_block(const DoFHandlerType &                dof_handler,
                        std::vector<types::global_dof_index> &dofs_per_block,
-                       const std::vector<unsigned int> &     target_block_)
+                       const std::vector<unsigned int> &     target_block)
   {
-    std::vector<unsigned int> target_block = target_block_;
+    dofs_per_block = count_dofs_per_block(dof_handler, target_block);
+  }
+
 
+
+  template <typename DoFHandlerType>
+  std::vector<types::global_dof_index>
+  count_dofs_per_block(const DoFHandlerType &           dof_handler,
+                       const std::vector<unsigned int> &target_block_)
+  {
     const dealii::hp::FECollection<DoFHandlerType::dimension,
                                    DoFHandlerType::space_dimension>
       &fe_collection = dof_handler.get_fe_collection();
     Assert(fe_collection.size() < 256, ExcNotImplemented());
 
-    for (unsigned int this_fe = 0; this_fe < fe_collection.size(); ++this_fe)
-      {
-        const FiniteElement<DoFHandlerType::dimension,
-                            DoFHandlerType::space_dimension> &fe =
-          fe_collection[this_fe];
-        std::fill(dofs_per_block.begin(),
-                  dofs_per_block.end(),
-                  types::global_dof_index(0));
-
-        // If the empty vector was given as default argument, set up this
-        // vector as identity.
-        if (target_block.size() == 0)
-          {
-            target_block.resize(fe.n_blocks());
-            for (unsigned int i = 0; i < fe.n_blocks(); ++i)
-              target_block[i] = i;
-          }
-        else
-          Assert(target_block.size() == fe.n_blocks(),
-                 ExcDimensionMismatch(target_block.size(), fe.n_blocks()));
-
+    // If the empty vector for target_block(e.g., as default argument), then
+    // set up this vector as identity. We do this set up with the first
+    // element of the collection, but the whole thing can only work if
+    // all elements have the same number of blocks anyway -- so check
+    // that right after
+    const unsigned int n_blocks = fe_collection[0].n_blocks();
 
+    std::vector<unsigned int> target_block = target_block_;
+    if (target_block.size() == 0)
+      {
+        target_block.resize(fe_collection[0].n_blocks());
+        for (unsigned int i = 0; i < n_blocks; ++i)
+          target_block[i] = i;
+      }
+    else
+      Assert(target_block.size() == n_blocks,
+             ExcDimensionMismatch(target_block.size(), n_blocks));
+    for (unsigned int f = 1; f < fe_collection.size(); ++f)
+      Assert(fe_collection[0].n_blocks() == fe_collection[f].n_blocks(),
+             ExcMessage("This function can only work if all elements in a "
+                        "collection have the same number of blocks."));
+
+    // special case for only one block. treat this first since it does
+    // not require any computations
+    if (n_blocks == 1)
+      {
+        std::vector<types::global_dof_index> dofs_per_block(1);
+        dofs_per_block[0] = dof_handler.n_dofs();
+        return dofs_per_block;
+      }
 
-        const unsigned int max_block =
-          *std::max_element(target_block.begin(), target_block.end());
-        const unsigned int n_target_blocks = max_block + 1;
-        (void)n_target_blocks; // silence possible warning about unused variable
+    // Otherwise set up the right-sized object and start working
+    const unsigned int max_block =
+      *std::max_element(target_block.begin(), target_block.end());
+    const unsigned int n_target_blocks = max_block + 1;
 
-        const unsigned int n_blocks = fe.n_blocks();
+    std::vector<types::global_dof_index> dofs_per_block(n_target_blocks);
 
-        AssertDimension(dofs_per_block.size(), n_target_blocks);
+    // Loop over the elements of the collection, but really only consider
+    // the last element (see #9271)
+    for (unsigned int this_fe = fe_collection.size() - 1;
+         this_fe < fe_collection.size();
+         ++this_fe)
+      {
+        const FiniteElement<DoFHandlerType::dimension,
+                            DoFHandlerType::space_dimension> &fe =
+          fe_collection[this_fe];
 
-        // special case for only one block. treat this first since it does
-        // not require any computations
-        if (n_blocks == 1)
-          {
-            dofs_per_block[0] = dof_handler.n_dofs();
-            return;
-          }
-        // otherwise determine the number of dofs in each block separately.
         std::vector<unsigned char> dofs_by_block(
           dof_handler.n_locally_owned_dofs());
         internal::get_block_association(dof_handler, dofs_by_block);
@@ -2083,6 +2111,8 @@ namespace DoFTools
           }
 #endif
       }
+
+    return dofs_per_block;
   }
 
 

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.