From: Peter Munch Date: Wed, 9 Mar 2022 19:04:52 +0000 (+0100) Subject: Refine MGTwoLevelTransfer::enable_inplace_operations_if_possible() X-Git-Tag: v9.4.0-rc1~374^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4225e6cb62b7f14e4a7e2a9b178643870eedb770;p=dealii.git Refine MGTwoLevelTransfer::enable_inplace_operations_if_possible() --- diff --git a/include/deal.II/multigrid/mg_transfer_global_coarsening.h b/include/deal.II/multigrid/mg_transfer_global_coarsening.h index 339fcad875..cc6b5552a9 100644 --- a/include/deal.II/multigrid/mg_transfer_global_coarsening.h +++ b/include/deal.II/multigrid/mg_transfer_global_coarsening.h @@ -644,7 +644,7 @@ MGTransferGlobalCoarsening::build( const unsigned int min_level = transfer.min_level(); const unsigned int max_level = transfer.max_level(); - AssertDimension(external_partitioners.size(), max_level - min_level + 1); + AssertDimension(external_partitioners.size(), transfer.n_levels()); this->initialize_dof_vector = [external_partitioners, min_level]( @@ -669,18 +669,19 @@ MGTransferGlobalCoarsening::build( { if (initialize_dof_vector) { - const unsigned int n_levels = - transfer.max_level() - transfer.min_level() + 1; + const unsigned int min_level = transfer.min_level(); + const unsigned int max_level = transfer.max_level(); + const unsigned int n_levels = transfer.n_levels(); std::vector> external_partitioners(n_levels); - for (unsigned int level = 0; level < n_levels; ++level) + for (unsigned int l = min_level; l <= max_level; ++l) { LinearAlgebra::distributed::Vector vector; - initialize_dof_vector(level, vector); - external_partitioners[level] = vector.get_partitioner(); + initialize_dof_vector(l, vector); + external_partitioners[l - min_level] = vector.get_partitioner(); } build(external_partitioners); diff --git a/include/deal.II/multigrid/mg_transfer_global_coarsening.templates.h b/include/deal.II/multigrid/mg_transfer_global_coarsening.templates.h index 94c7ca8eef..9f0f74af6b 100644 --- a/include/deal.II/multigrid/mg_transfer_global_coarsening.templates.h +++ b/include/deal.II/multigrid/mg_transfer_global_coarsening.templates.h @@ -2905,19 +2905,73 @@ void MGTwoLevelTransfer>:: enable_inplace_operations_if_possible( const std::shared_ptr - &partitioner_coarse, - const std::shared_ptr &partitioner_fine) + &external_partitioner_coarse, + const std::shared_ptr + &external_partitioner_fine) { - if (this->partitioner_coarse->is_globally_compatible(*partitioner_coarse)) + const auto is_partitioner_contained = + [](const auto &partitioner, const auto &external_partitioner) -> bool { + // no external partitioner has been given + if (external_partitioner.get() == nullptr) + return false; + + // check if locally owned ranges are the same + if (external_partitioner->size() != partitioner->size()) + return false; + + if (external_partitioner->locally_owned_range() != + partitioner->locally_owned_range()) + return false; + + const int ghosts_locally_contained = + ((external_partitioner->ghost_indices() & partitioner->ghost_indices()) == + partitioner->ghost_indices()) ? + 1 : + 0; + + // check if ghost values are contained in external partititioner + return Utilities::MPI::min(ghosts_locally_contained, + partitioner->get_mpi_communicator()) == 1; + }; + + if (this->partitioner_coarse->is_globally_compatible( + *external_partitioner_coarse)) { - this->partitioner_coarse = partitioner_coarse; this->vec_coarse.reinit(0); + this->partitioner_coarse = external_partitioner_coarse; + } + else if (is_partitioner_contained(this->partitioner_coarse, + external_partitioner_coarse)) + { + this->vec_coarse.reinit(0); + + for (auto &i : constraint_info.dof_indices) + i = external_partitioner_coarse->global_to_local( + this->partitioner_coarse->local_to_global(i)); + + for (auto &i : constraint_info.plain_dof_indices) + i = external_partitioner_coarse->global_to_local( + this->partitioner_coarse->local_to_global(i)); + + this->partitioner_coarse = external_partitioner_coarse; } - if (this->partitioner_fine->is_globally_compatible(*partitioner_fine)) + if (this->partitioner_fine->is_globally_compatible( + *external_partitioner_fine)) { - this->partitioner_fine = partitioner_fine; this->vec_fine.reinit(0); + this->partitioner_fine = external_partitioner_fine; + } + else if (is_partitioner_contained(this->partitioner_fine, + external_partitioner_fine)) + { + this->vec_fine.reinit(0); + + for (auto &i : level_dof_indices_fine) + i = external_partitioner_fine->global_to_local( + this->partitioner_fine->local_to_global(i)); + + this->partitioner_fine = external_partitioner_fine; } }