From: Wolfgang Bangerth Date: Thu, 9 Jan 2020 17:15:58 +0000 (-0700) Subject: Make DoFTools::count_dofs_per_{component,block} return its data. X-Git-Tag: v9.2.0-rc1~670^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=070e9ac52f04cbc2b62ade126509652df3cd6e65;p=dealii.git Make DoFTools::count_dofs_per_{component,block} return its data. Instead of doing so via an output argument. The existing functions are deprecated. --- diff --git a/include/deal.II/dofs/dof_tools.h b/include/deal.II/dofs/dof_tools.h index cee3ae9e41..b5a51ae3cf 100644 --- a/include/deal.II/dofs/dof_tools.h +++ b/include/deal.II/dofs/dof_tools.h @@ -2257,7 +2257,18 @@ namespace DoFTools * The indices not targeted by target_components are left untouched. */ template - void + std::vector + count_dofs_per_component( + const DoFHandlerType & dof_handler, + const bool vector_valued_once = false, + const std::vector &target_component = {}); + + /** + * @deprecated A version of the previous function that returns its + * information through the non-`const` second argument. + */ + template + DEAL_II_DEPRECATED void count_dofs_per_component( const DoFHandlerType & dof_handler, std::vector &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 - void + std::vector + count_dofs_per_block(const DoFHandlerType & dof, + const std::vector &target_block = + std::vector()); + + /** + * @deprecated A version of the previous function that returns its + * information through the non-`const` second argument. + */ + template + DEAL_II_DEPRECATED void count_dofs_per_block(const DoFHandlerType & dof, std::vector &dofs_per_block, const std::vector & target_block = diff --git a/source/dofs/dof_tools.cc b/source/dofs/dof_tools.cc index cc1d0ba1eb..07693402c3 100644 --- a/source/dofs/dof_tools.cc +++ b/source/dofs/dof_tools.cc @@ -1902,19 +1902,28 @@ namespace DoFTools + // deprecated function template void count_dofs_per_component( const DoFHandlerType & dof_handler, std::vector &dofs_per_component, const bool only_once, - const std::vector & target_component_) + const std::vector & 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 + std::vector + count_dofs_per_component(const DoFHandlerType & dof_handler, + const bool only_once, + const std::vector &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 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 void count_dofs_per_block(const DoFHandlerType & dof_handler, std::vector &dofs_per_block, - const std::vector & target_block_) + const std::vector & target_block) { - std::vector target_block = target_block_; + dofs_per_block = count_dofs_per_block(dof_handler, target_block); + } + + + template + std::vector + count_dofs_per_block(const DoFHandlerType & dof_handler, + const std::vector &target_block_) + { const dealii::hp::FECollection &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 &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 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 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 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 &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 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; }