From: Sebastian Proell Date: Mon, 31 Jan 2022 17:13:58 +0000 (+0100) Subject: Enable FE_Nothing in DoFTools::extract_constant_modes X-Git-Tag: v9.4.0-rc1~487^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F13313%2Fhead;p=dealii.git Enable FE_Nothing in DoFTools::extract_constant_modes --- diff --git a/doc/news/changes/minor/20220207Proell b/doc/news/changes/minor/20220207Proell new file mode 100644 index 0000000000..0b3a1de861 --- /dev/null +++ b/doc/news/changes/minor/20220207Proell @@ -0,0 +1,5 @@ +New: The FE_Nothing class can now return its (empty) constant modes. +DoFTools::extract_constant_modes can now work with DoFHandlers that +contain FE_Nothing. +
+(Sebastian Proell, 2022/02/07) diff --git a/include/deal.II/fe/fe_nothing.h b/include/deal.II/fe/fe_nothing.h index 2df7f0b5a5..ec229d6dc1 100644 --- a/include/deal.II/fe/fe_nothing.h +++ b/include/deal.II/fe/fe_nothing.h @@ -326,6 +326,15 @@ public: FullMatrix & interpolation_matrix, const unsigned int face_no = 0) const override; + /** + * Return a list of constant modes of the element. + * + * Since the current finite element has no degrees of freedom, the returned + * list is necessarily empty. + */ + virtual std::pair, std::vector> + get_constant_modes() const override; + /** * @return true if the FE dominates any other. */ diff --git a/source/dofs/dof_tools.cc b/source/dofs/dof_tools.cc index 1acf4d5602..ba7379924e 100644 --- a/source/dofs/dof_tools.cc +++ b/source/dofs/dof_tools.cc @@ -1249,26 +1249,47 @@ namespace DoFTools dof_handler.get_fe_collection(); std::vector> element_constant_modes; std::vector>> - constant_mode_to_component_translation(n_components); - unsigned int n_constant_modes = 0; - for (unsigned int f = 0; f < fe_collection.size(); ++f) - { - std::pair, std::vector> data = - fe_collection[f].get_constant_modes(); - element_constant_modes.push_back(data.first); - if (f == 0) - for (unsigned int i = 0; i < data.second.size(); ++i) - if (component_mask[data.second[i]]) - constant_mode_to_component_translation[data.second[i]] - .emplace_back(n_constant_modes++, i); - AssertDimension(element_constant_modes.back().n_rows(), - element_constant_modes[0].n_rows()); - } + constant_mode_to_component_translation(n_components); + { + unsigned int n_constant_modes = 0; + int first_non_empty_constant_mode = -1; + for (unsigned int f = 0; f < fe_collection.size(); ++f) + { + std::pair, std::vector> data = + fe_collection[f].get_constant_modes(); - // First count the number of dofs in the current component. - constant_modes.clear(); - constant_modes.resize(n_constant_modes, - std::vector(n_selected_dofs, false)); + // Store the index of the current element if it is the first that has + // non-empty constant modes. + if (first_non_empty_constant_mode < 0 && data.first.n_rows() > 0) + { + first_non_empty_constant_mode = f; + // This is the first non-empty constant mode, so we figure out the + // translation between index in the constant modes and the + // components + for (unsigned int i = 0; i < data.second.size(); ++i) + if (component_mask[data.second[i]]) + constant_mode_to_component_translation[data.second[i]] + .emplace_back(n_constant_modes++, i); + } + + // Add the constant modes of this element to the list and assert that + // there are as many constant modes as for the other elements (or zero + // constant modes). + element_constant_modes.push_back(data.first); + Assert( + element_constant_modes.back().n_rows() == 0 || + element_constant_modes.back().n_rows() == + element_constant_modes[first_non_empty_constant_mode].n_rows(), + ExcInternalError()); + } + AssertIndexRange(first_non_empty_constant_mode, fe_collection.size()); + + // Now we know the number of constant modes and resize the return vector + // accordingly + constant_modes.clear(); + constant_modes.resize(n_constant_modes, + std::vector(n_selected_dofs, false)); + } // Loop over all owned cells and ask the element for the constant modes std::vector dof_indices; diff --git a/source/fe/fe_nothing.cc b/source/fe/fe_nothing.cc index 40db67be56..a1742e80b4 100644 --- a/source/fe/fe_nothing.cc +++ b/source/fe/fe_nothing.cc @@ -314,6 +314,7 @@ FE_Nothing::get_face_interpolation_matrix( } + template void FE_Nothing::get_subface_interpolation_matrix( @@ -334,6 +335,16 @@ FE_Nothing::get_subface_interpolation_matrix( +template +std::pair, std::vector> +FE_Nothing::get_constant_modes() const +{ + // since this element has no dofs, there are no constant modes + return {Table<2, bool>{}, std::vector{}}; +} + + + // explicit instantiations #include "fe_nothing.inst" diff --git a/tests/mpi/extract_constant_modes_03.cc b/tests/mpi/extract_constant_modes_03.cc new file mode 100644 index 0000000000..144eab2639 --- /dev/null +++ b/tests/mpi/extract_constant_modes_03.cc @@ -0,0 +1,129 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2009 - 2018 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. +// +// --------------------------------------------------------------------- + + + +// test DoFTools::extract_constant_modes with FE_Nothing + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "../tests.h" + + + +template +void +test(unsigned int fe_nothing_index) +{ + unsigned int myid = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + parallel::distributed::Triangulation tr(MPI_COMM_WORLD); + + std::vector sub(2); + sub[0] = 2 * Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + sub[1] = 1; + GridGenerator::subdivided_hyper_rectangle( + static_cast &>(tr), sub, Point<2>(0, 0), Point<2>(1, 1)); + + DoFHandler dofh(tr); + + { + // set cells to use FE_Q and FE_Nothing alternately + unsigned int last_index = 1; + for (const auto &cell : + dofh.active_cell_iterators() | IteratorFilters::LocallyOwnedCell()) + cell->set_active_fe_index(last_index = 1 - last_index); + } + + if (fe_nothing_index == 1) + dofh.distribute_dofs( + hp::FECollection(FE_Q(1), FE_Nothing(1))); + else + dofh.distribute_dofs( + hp::FECollection(FE_Nothing(1), FE_Q(1))); + + if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0) + deallog << "Total dofs=" << dofh.n_dofs() << std::endl; + + // extract constant modes and print + + if (myid == 0) + { + std::vector mask(1, true); + + std::vector> constant_modes; + DoFTools::extract_constant_modes(dofh, mask, constant_modes); + + for (unsigned int i = 0; i < constant_modes.size(); ++i) + { + for (unsigned int j = 0; j < constant_modes[i].size(); ++j) + deallog << (constant_modes[i][j] ? '1' : '0') << ' '; + deallog << std::endl; + } + } +} + + +int +main(int argc, char *argv[]) +{ + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1); + + unsigned int myid = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + + deallog.push(Utilities::int_to_string(myid)); + + + if (myid == 0) + { + initlog(); + + deallog.push("FE_Nothing second"); + test<2>(1); + deallog.pop(); + + deallog.push("FE_Nothing first"); + test<2>(0); + deallog.pop(); + } + else + { + deallog.push("FE_Nothing second"); + test<2>(1); + deallog.pop(); + + deallog.push("FE_Nothing first"); + test<2>(0); + deallog.pop(); + } +} diff --git a/tests/mpi/extract_constant_modes_03.mpirun=2.with_p4est=true.output b/tests/mpi/extract_constant_modes_03.mpirun=2.with_p4est=true.output new file mode 100644 index 0000000000..6b819141ea --- /dev/null +++ b/tests/mpi/extract_constant_modes_03.mpirun=2.with_p4est=true.output @@ -0,0 +1,5 @@ + +DEAL:0:FE_Nothing second::Total dofs=8 +DEAL:0:FE_Nothing second::1 1 1 1 +DEAL:0:FE_Nothing first::Total dofs=8 +DEAL:0:FE_Nothing first::1 1 1 1