From: Marc Fehling Date: Sun, 3 Feb 2019 00:24:43 +0000 (+0100) Subject: Added 'set_fe' functionality to DoFHandlers. X-Git-Tag: v9.1.0-rc1~310^2~2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=052b9b1b3cbd27520a63daf7b085b2bd84fecc2a;p=dealii.git Added 'set_fe' functionality to DoFHandlers. --- diff --git a/doc/news/changes/minor/20190210MarcFehling b/doc/news/changes/minor/20190210MarcFehling new file mode 100644 index 0000000000..9a3e1e9f47 --- /dev/null +++ b/doc/news/changes/minor/20190210MarcFehling @@ -0,0 +1,6 @@ +New: Member functions DoFHandler::set_fe() and hp::DoFHandler::set_fe() +that will register a finite element object without enumerating all +degrees of freedom. In the hp case, the active_fe_indices will be +initialized and communicated amongst all processors, additionally. +
+(2019/02/10, Marc Fehling) diff --git a/include/deal.II/distributed/solution_transfer.h b/include/deal.II/distributed/solution_transfer.h index 558ebeed29..9d61878b27 100644 --- a/include/deal.II/distributed/solution_transfer.h +++ b/include/deal.II/distributed/solution_transfer.h @@ -203,7 +203,7 @@ namespace parallel * hp::DoFHandler hp_dof_handler(triangulation); * // We need to introduce our dof_handler to the fe_collection * // before setting all active_fe_indices. - * hp_dof_handler.distribute_dofs(fe_collection); + * hp_dof_handler.set_fe(fe_collection); * hp_dof_handler.deserialize_active_fe_indices(); * hp_dof_handler.distribute_dofs(fe_collection); * diff --git a/include/deal.II/dofs/dof_handler.h b/include/deal.II/dofs/dof_handler.h index 638e98b535..1da5931739 100644 --- a/include/deal.II/dofs/dof_handler.h +++ b/include/deal.II/dofs/dof_handler.h @@ -472,6 +472,25 @@ public: initialize(const Triangulation &tria, const FiniteElement &fe); + /** + * Assign a FiniteElement @p fe to this object. + * + * @note This function makes a copy of the finite element given as + * argument, and stores it as a member variable. Consequently, it is + * possible to write code such as + * @code + * dof_handler.set_fe(FE_Q(2)); + * @endcode + * You can then access the finite element later on by calling + * DoFHandler::get_fe(). However, it is often more convenient to + * keep a named finite element object as a member variable in your + * main class and refer to it directly whenever you need to access + * properties of the finite element (such as + * FiniteElementData::dofs_per_cell). This is what all tutorial programs do. + */ + virtual void + set_fe(const FiniteElement &fe); + /** * Go through the triangulation and "distribute" the degrees of * freedom needed for the given finite element. "Distributing" @@ -498,17 +517,8 @@ public: * step-2 tutorial program. * * @note This function makes a copy of the finite element given as - * argument, and stores it as a member variable. Consequently, it is - * possible to write code such as - * @code - * dof_handler.distribute_dofs (FE_Q(2)); - * @endcode - * You can then access the finite element later on by calling - * DoFHandler::get_fe(). However, it is often more convenient to - * keep a named finite element object as a member variable in your - * main class and refer to it directly whenever you need to access - * properties of the finite element (such as FiniteElement::dofs_per_cell). - * This is what all tutorial programs do. + * argument, and stores it as a member variable, similarly to the above + * function set_fe(). */ virtual void distribute_dofs(const FiniteElement &fe); diff --git a/include/deal.II/hp/dof_handler.h b/include/deal.II/hp/dof_handler.h index 29a3746ec8..3b73789941 100644 --- a/include/deal.II/hp/dof_handler.h +++ b/include/deal.II/hp/dof_handler.h @@ -417,6 +417,19 @@ namespace hp initialize(const Triangulation & tria, const hp::FECollection &fe); + /** + * Assign a hp::FECollection @p fe to this object. + * + * In case a parallel::Triangulation is assigned to this object, + * the active_fe_indices will be exchanged between processors so that + * each one knows the indices on its own cells and all ghost cells. + * + * @note In accordance with dealii::DoFHandler::set_fe(), + * this function also makes a copy of the object given as argument. + */ + virtual void + set_fe(const hp::FECollection &fe); + /** * Go through the triangulation and "distribute" the degrees of * freedom needed for the given finite element. "Distributing" diff --git a/source/dofs/dof_handler.cc b/source/dofs/dof_handler.cc index 03603ee5a0..f5b0a0fd20 100644 --- a/source/dofs/dof_handler.cc +++ b/source/dofs/dof_handler.cc @@ -1197,6 +1197,18 @@ DoFHandler::memory_consumption() const +template +void +DoFHandler::set_fe(const FiniteElement &ff) +{ + // Only recreate the FECollection if we don't already store + // the exact same FiniteElement object. + if (fe_collection.size() == 0 || fe_collection[0] != ff) + fe_collection = hp::FECollection(ff); +} + + + template void DoFHandler::distribute_dofs( @@ -1210,10 +1222,8 @@ DoFHandler::distribute_dofs( Assert(tria->n_levels() > 0, ExcMessage("The Triangulation you are using is empty!")); - // Only recreate the FECollection if we don't already store - // the exact same FiniteElement object. - if (fe_collection.size() == 0 || fe_collection[0] != ff) - fe_collection = hp::FECollection(ff); + // first, assign the finite_element + set_fe(ff); // delete all levels and set them // up newly. note that we still diff --git a/source/hp/dof_handler.cc b/source/hp/dof_handler.cc index 01900459d8..35e4a17666 100644 --- a/source/hp/dof_handler.cc +++ b/source/hp/dof_handler.cc @@ -1390,6 +1390,33 @@ namespace hp + template + void + DoFHandler::set_fe(const hp::FECollection &ff) + { + // don't create a new object if the one we have is already appropriate + if (fe_collection != ff) + fe_collection = hp::FECollection(ff); + + // ensure that the active_fe_indices vectors are initialized correctly + create_active_fe_table(); + + // make sure every processor knows the active_fe_indices + // on both its own cells and all ghost cells + dealii::internal::hp::DoFHandlerImplementation::Implementation:: + communicate_active_fe_indices(*this); + + // make sure that the fe collection is large enough to + // cover all fe indices presently in use on the mesh + for (const auto &cell : active_cell_iterators()) + if (cell->is_locally_owned()) + Assert(cell->active_fe_index() < fe_collection.size(), + ExcInvalidFEIndex(cell->active_fe_index(), + fe_collection.size())); + } + + + template void DoFHandler::distribute_dofs( @@ -1404,14 +1431,8 @@ namespace hp ExcMessage("The Triangulation you are using is empty!")); Assert(ff.size() > 0, ExcMessage("The hp::FECollection given is empty!")); - // don't create a new object if the one we have is already appropriate - if (fe_collection != ff) - fe_collection = hp::FECollection(ff); - - // at the beginning, make sure every processor knows the - // active_fe_indices on both its own cells and all ghost cells - dealii::internal::hp::DoFHandlerImplementation::Implementation:: - communicate_active_fe_indices(*this); + // first, assign the fe_collection + set_fe(ff); // If an underlying shared::Tria allows artificial cells, // then save the current set of subdomain ids, and set @@ -1425,51 +1446,29 @@ namespace hp { saved_subdomain_ids.resize(shared_tria->n_active_cells()); - typename parallel::shared::Triangulation:: - active_cell_iterator cell = get_triangulation().begin_active(), - endc = get_triangulation().end(); - const std::vector &true_subdomain_ids = shared_tria->get_true_subdomain_ids_of_cells(); - for (unsigned int index = 0; cell != endc; ++cell, ++index) + for (const auto &cell : shared_tria->active_cell_iterators()) { + const unsigned int index = cell->active_cell_index(); saved_subdomain_ids[index] = cell->subdomain_id(); cell->set_subdomain_id(true_subdomain_ids[index]); } } - // ensure that the active_fe_indices vectors are - // initialized correctly. - create_active_fe_table(); - - // up front make sure that the fe collection is large enough to - // cover all fe indices presently in use on the mesh - for (active_cell_iterator cell = begin_active(); cell != end(); ++cell) - if (cell->is_locally_owned()) - Assert(cell->active_fe_index() < fe_collection.size(), - ExcInvalidFEIndex(cell->active_fe_index(), - fe_collection.size())); - - - // then allocate space for all the other tables + // then allocate space for all tables dealii::internal::hp::DoFHandlerImplementation::Implementation:: reserve_space(*this); - // now undo the subdomain modification if (const parallel::shared::Triangulation *shared_tria = (dynamic_cast *>( &get_triangulation()))) if (shared_tria->with_artificial_cells()) - { - typename parallel::shared::Triangulation:: - active_cell_iterator cell = get_triangulation().begin_active(), - endc = get_triangulation().end(); - - for (unsigned int index = 0; cell != endc; ++cell, ++index) - cell->set_subdomain_id(saved_subdomain_ids[index]); - } + for (const auto &cell : shared_tria->active_cell_iterators()) + cell->set_subdomain_id( + saved_subdomain_ids[cell->active_cell_index()]); // Clear user flags because we will need them. But first we save diff --git a/tests/mpi/hp_active_fe_indices_transfer_01.cc b/tests/mpi/hp_active_fe_indices_transfer_01.cc index 2d5cb00ab2..5fd0cc5108 100644 --- a/tests/mpi/hp_active_fe_indices_transfer_01.cc +++ b/tests/mpi/hp_active_fe_indices_transfer_01.cc @@ -50,9 +50,8 @@ test() for (unsigned int i = 0; i < max_degree; ++i) fe_collection.push_back(FE_Q(max_degree - i)); - // this distribute_dofs() call is necessary // we need to introduce dof_handler to its fe_collection first - dh.distribute_dofs(fe_collection); + dh.set_fe(fe_collection); unsigned int i = 0; for (auto &cell : dh.active_cell_iterators()) diff --git a/tests/mpi/hp_active_fe_indices_transfer_02.cc b/tests/mpi/hp_active_fe_indices_transfer_02.cc index 6539345740..e40dc29a2b 100644 --- a/tests/mpi/hp_active_fe_indices_transfer_02.cc +++ b/tests/mpi/hp_active_fe_indices_transfer_02.cc @@ -48,10 +48,9 @@ test() GridGenerator::subdivided_hyper_cube(tria, 2); tria.refine_global(1); - // this distribute_dofs() call is necessary - // we need to introduce dof_handler to its fe_collection first hp::DoFHandler dh(tria); - dh.distribute_dofs(fe_collection); + // we need to introduce dof_handler to its fe_collection first + dh.set_fe(fe_collection); unsigned int i = 0; for (auto &cell : dh.active_cell_iterators()) @@ -85,10 +84,9 @@ test() GridGenerator::subdivided_hyper_cube(tria, 2); // triangulation has to be initialized with correct coarse cells - // this distribute_dofs() call is necessary // we need to introduce dof_handler to its fe_collection first hp::DoFHandler dh(tria); - dh.distribute_dofs(fe_collection); + dh.set_fe(fe_collection); // ----- transfer ----- tria.load("file"); diff --git a/tests/mpi/hp_cell_weights_01.cc b/tests/mpi/hp_cell_weights_01.cc index 6d15d5841b..6edf118412 100644 --- a/tests/mpi/hp_cell_weights_01.cc +++ b/tests/mpi/hp_cell_weights_01.cc @@ -57,17 +57,12 @@ test() fe_collection.push_back(FE_Q(5)); hp::DoFHandler dh(tria); + dh.set_fe(fe_collection); // default: active_fe_index = 0 for (auto &cell : dh.active_cell_iterators()) if (cell->is_locally_owned()) if (cell->id().to_string() == "0_2:00") cell->set_active_fe_index(1); - dh.distribute_dofs(fe_collection); - - - parallel::CellWeights cell_weights(dh); - cell_weights.register_ndofs_weighting(100000); - deallog << "Number of cells before repartitioning: " << tria.n_locally_owned_active_cells() << std::endl; @@ -80,8 +75,10 @@ test() } + parallel::CellWeights cell_weights(dh); + cell_weights.register_ndofs_weighting(100000); + tria.repartition(); - dh.distribute_dofs(fe_collection); deallog << "Number of cells after repartitioning: " diff --git a/tests/mpi/hp_cell_weights_02.cc b/tests/mpi/hp_cell_weights_02.cc index 5d13dff774..e116925d70 100644 --- a/tests/mpi/hp_cell_weights_02.cc +++ b/tests/mpi/hp_cell_weights_02.cc @@ -63,17 +63,12 @@ test() fe_collection.push_back(FE_Q(7)); hp::DoFHandler dh(tria); + dh.set_fe(fe_collection); // default: active_fe_index = 0 for (auto &cell : dh.active_cell_iterators()) if (cell->is_locally_owned()) if (cell->id().to_string() == "0_3:000") cell->set_active_fe_index(1); - dh.distribute_dofs(fe_collection); - - - parallel::CellWeights cell_weights(dh); - cell_weights.register_ndofs_weighting(100000); - deallog << "Number of cells before repartitioning: " << tria.n_locally_owned_active_cells() << std::endl; @@ -86,8 +81,10 @@ test() } + parallel::CellWeights cell_weights(dh); + cell_weights.register_ndofs_weighting(100000); + tria.repartition(); - dh.distribute_dofs(fe_collection); deallog << "Number of cells after repartitioning: " diff --git a/tests/mpi/hp_cell_weights_03.cc b/tests/mpi/hp_cell_weights_03.cc index c2eccc249f..afe9d5be68 100644 --- a/tests/mpi/hp_cell_weights_03.cc +++ b/tests/mpi/hp_cell_weights_03.cc @@ -63,17 +63,12 @@ test() fe_collection.push_back(FE_Q(5)); hp::DoFHandler dh(tria); + dh.set_fe(fe_collection); // default: active_fe_index = 0 for (auto &cell : dh.active_cell_iterators()) if (cell->is_locally_owned()) if (cell->id().to_string() == "0_2:00") cell->set_active_fe_index(1); - dh.distribute_dofs(fe_collection); - - - parallel::CellWeights cell_weights(dh); - cell_weights.register_ndofs_weighting(100000); - deallog << "Number of cells before repartitioning: " << tria.n_locally_owned_active_cells() << std::endl; @@ -86,9 +81,11 @@ test() } + parallel::CellWeights cell_weights(dh); + cell_weights.register_ndofs_weighting(100000); + // we didn't mark any cells, but we want to repartition our domain tria.execute_coarsening_and_refinement(); - dh.distribute_dofs(fe_collection); deallog << "Number of cells after repartitioning: " diff --git a/tests/mpi/p4est_save_06.cc b/tests/mpi/p4est_save_06.cc index 5af46a8696..453ed58389 100644 --- a/tests/mpi/p4est_save_06.cc +++ b/tests/mpi/p4est_save_06.cc @@ -134,7 +134,7 @@ test() for (unsigned int i = 0; i < max_degree; ++i) fe_collection.push_back(FE_Q(max_degree - i)); - dh.distribute_dofs(fe_collection); + dh.set_fe(fe_collection); dh.deserialize_active_fe_indices(); dh.distribute_dofs(fe_collection);