16#include <deal.II/base/mpi.templates.h>
43 template <
int dim,
int spacedim>
49 const
bool check_for_distorted_cells)
51 check_for_distorted_cells)
52 , mpi_communicator(mpi_communicator)
53 , my_subdomain(
Utilities::
MPI::this_mpi_process(this->mpi_communicator))
54 , n_subdomains(
Utilities::
MPI::n_mpi_processes(this->mpi_communicator))
56#ifndef DEAL_II_WITH_MPI
63 template <
int dim,
int spacedim>
68#ifndef DEAL_II_WITH_MPI
74 if (const ::parallel::TriangulationBase<dim, spacedim> *other_tria_x =
75 dynamic_cast<const ::parallel::TriangulationBase<dim, spacedim>
88 template <
int dim,
int spacedim>
97 number_cache.n_global_active_cells) +
104 template <
int dim,
int spacedim>
116 template <
int dim,
int spacedim>
119 : n_locally_owned_active_cells(0)
120 , n_global_active_cells(0)
121 , number_of_global_coarse_cells(0)
127 template <
int dim,
int spacedim>
137 template <
int dim,
int spacedim>
146 template <
int dim,
int spacedim>
151 return number_cache.n_global_active_cells;
156 template <
int dim,
int spacedim>
160 return mpi_communicator;
165#ifdef DEAL_II_WITH_MPI
166 template <
int dim,
int spacedim>
171 number_cache.level_ghost_owners.clear();
172 number_cache.n_locally_owned_active_cells = 0;
174 if (this->n_levels() == 0)
181 number_cache.n_global_active_cells = 0;
182 number_cache.n_global_levels = 0;
189 for (
const auto &cell : this->active_cell_iterators())
190 if (cell->is_ghost())
191 number_cache.ghost_owners.insert(cell->subdomain_id());
193 Assert(number_cache.ghost_owners.size() <
198 if (this->n_levels() > 0)
199 number_cache.n_locally_owned_active_cells = std::count_if(
200 this->begin_active(),
203 [](
const auto &i) {
return i.is_locally_owned(); });
205 number_cache.n_locally_owned_active_cells = 0;
209 number_cache.n_global_active_cells =
211 number_cache.n_locally_owned_active_cells),
212 this->mpi_communicator);
214 number_cache.n_global_levels =
219 if (this->is_multilevel_hierarchy_constructed() ==
true)
221 number_cache.level_ghost_owners.clear();
224 if (this->n_levels() == 0)
228 for (
const auto &cell : this->cell_iterators())
229 if (cell->level_subdomain_id() !=
numbers::artificial_subdomain_id &&
230 cell->level_subdomain_id() != this->locally_owned_subdomain())
231 this->number_cache.level_ghost_owners.insert(
232 cell->level_subdomain_id());
239 int ierr = MPI_Barrier(this->mpi_communicator);
246 std::vector<MPI_Request> requests(
247 this->number_cache.level_ghost_owners.size());
248 unsigned int dummy = 0;
249 unsigned int req_counter = 0;
251 for (
const auto &it : this->number_cache.level_ghost_owners)
253 ierr = MPI_Isend(&dummy,
258 this->mpi_communicator,
259 &requests[req_counter]);
264 for (
const auto &it : this->number_cache.level_ghost_owners)
267 ierr = MPI_Recv(&dummy,
272 this->mpi_communicator,
277 if (requests.size() > 0)
279 ierr = MPI_Waitall(requests.size(),
281 MPI_STATUSES_IGNORE);
285 ierr = MPI_Barrier(this->mpi_communicator);
290 Assert(this->number_cache.level_ghost_owners.size() <
295 this->number_cache.number_of_global_coarse_cells = this->
n_cells(0);
298 this->reset_global_cell_indices();
303 template <
int dim,
int spacedim>
312 template <
int dim,
int spacedim>
322 template <
int dim,
int spacedim>
324 const std::set<types::subdomain_id>
327 return number_cache.ghost_owners;
332 template <
int dim,
int spacedim>
334 const std::set<types::subdomain_id>
337 return number_cache.level_ghost_owners;
342 template <
int dim,
int spacedim>
345 get_boundary_ids()
const
349 this->mpi_communicator);
354 template <
int dim,
int spacedim>
357 get_manifold_ids()
const
361 this->mpi_communicator);
366 template <
int dim,
int spacedim>
370#ifndef DEAL_II_WITH_MPI
376 if (pst->with_artificial_cells() ==
false)
382 std::vector<unsigned int> cell_counter(n_subdomains + 1);
385 for (
const auto &cell : this->active_cell_iterators())
386 cell_counter[cell->subdomain_id() + 1]++;
389 for (
unsigned int i = 0; i < n_subdomains; ++i)
390 cell_counter[i + 1] += cell_counter[i];
395 IndexSet is_local(this->n_active_cells());
396 is_local.
add_range(cell_counter[my_subdomain],
397 cell_counter[my_subdomain + 1]);
398 number_cache.active_cell_index_partitioner =
399 std::make_shared<const Utilities::MPI::Partitioner>(
402 this->mpi_communicator);
405 for (
const auto &cell : this->active_cell_iterators())
406 cell->set_global_active_cell_index(
407 cell_counter[cell->subdomain_id()]++);
409 Assert(this->is_multilevel_hierarchy_constructed() ==
false,
417 this->n_locally_owned_active_cells();
422 const int ierr = MPI_Exscan(
423 &n_locally_owned_cells,
428 this->mpi_communicator);
433 std::pair<types::global_cell_index, types::global_cell_index> my_range;
436 for (
const auto &cell : this->active_cell_iterators())
437 if (cell->is_locally_owned())
438 cell->set_global_active_cell_index(
cell_index++);
445 std::vector<types::global_dof_index> is_ghost_vector;
446 GridTools::exchange_cell_data_to_ghosts<types::global_cell_index>(
448 [](
const auto &cell) {
return cell->global_active_cell_index(); },
449 [&is_ghost_vector](
const auto &cell,
const auto &id) {
450 cell->set_global_active_cell_index(
id);
451 is_ghost_vector.push_back(
id);
455 IndexSet is_local(this->n_global_active_cells());
456 is_local.
add_range(my_range.first, my_range.second);
458 std::sort(is_ghost_vector.begin(), is_ghost_vector.end());
459 IndexSet is_ghost(this->n_global_active_cells());
460 is_ghost.add_indices(is_ghost_vector.begin(), is_ghost_vector.end());
462 number_cache.active_cell_index_partitioner =
463 std::make_shared<const Utilities::MPI::Partitioner>(
464 is_local, is_ghost, this->mpi_communicator);
467 if (this->is_multilevel_hierarchy_constructed() ==
true)
470 std::vector<types::global_cell_index> n_cells_level(
471 this->n_global_levels(), 0);
473 for (
auto cell : this->cell_iterators())
474 if (cell->level_subdomain_id() == this->locally_owned_subdomain())
475 n_cells_level[cell->
level()]++;
478 std::vector<types::global_cell_index>
cell_index(
479 this->n_global_levels(), 0);
481 int ierr = MPI_Exscan(
482 n_cells_level.data(),
484 this->n_global_levels(),
487 this->mpi_communicator);
492 this->mpi_communicator,
498 std::pair<types::global_cell_index, types::global_cell_index>>
499 my_ranges(this->n_global_levels());
500 for (
unsigned int l = 0; l < this->n_global_levels(); ++l)
503 for (
auto cell : this->cell_iterators())
504 if (cell->level_subdomain_id() == this->locally_owned_subdomain())
509 for (
unsigned int l = 0; l < this->n_global_levels(); ++l)
513 std::vector<std::vector<types::global_dof_index>> is_ghost_vectors(
514 this->n_global_levels());
519 [](
const auto &cell) {
return cell->global_level_cell_index(); },
520 [&is_ghost_vectors](
const auto &cell,
const auto &id) {
521 cell->set_global_level_cell_index(
id);
522 is_ghost_vectors[cell->level()].push_back(
id);
525 number_cache.level_cell_index_partitioners.resize(
526 this->n_global_levels());
529 for (
unsigned int l = 0; l < this->n_global_levels(); ++l)
531 IndexSet is_local(n_cells_level[l]);
534 IndexSet is_ghost(n_cells_level[l]);
535 std::sort(is_ghost_vectors[l].
begin(), is_ghost_vectors[l].
end());
536 is_ghost.add_indices(is_ghost_vectors[l].
begin(),
537 is_ghost_vectors[l].
end());
539 number_cache.level_cell_index_partitioners[l] =
540 std::make_shared<const Utilities::MPI::Partitioner>(
541 is_local, is_ghost, this->mpi_communicator);
550 template <
int dim,
int spacedim>
553 const
std::vector<
bool> &vertex_locally_moved)
559 const std::vector<bool> locally_owned_vertices =
561 for (
unsigned int i = 0; i < locally_owned_vertices.size(); ++i)
562 Assert((vertex_locally_moved[i] ==
false) ||
563 (locally_owned_vertices[i] ==
true),
564 ExcMessage(
"The vertex_locally_moved argument must not "
565 "contain vertices that are not locally owned"));
570 for (
unsigned int d = 0; d < spacedim; ++d)
571 invalid_point[d] = std::numeric_limits<double>::quiet_NaN();
573 const auto pack = [&](
const auto &cell) {
574 std::vector<Point<spacedim>> vertices(cell->n_vertices());
576 for (
const auto v : cell->vertex_indices())
577 if (vertex_locally_moved[cell->vertex_index(v)])
578 vertices[v] = cell->vertex(v);
580 vertices[v] = invalid_point;
585 const auto unpack = [&](
const auto &cell,
const auto &vertices) {
586 for (
const auto v : cell->vertex_indices())
588 cell->vertex(v) = vertices[v];
591 if (this->is_multilevel_hierarchy_constructed())
598 GridTools::exchange_cell_data_to_ghosts<std::vector<Point<spacedim>>>(
606 template <
int dim,
int spacedim>
610 spacedim>::global_active_cell_index_partitioner()
const
612 return number_cache.active_cell_index_partitioner;
617 template <
int dim,
int spacedim>
621 global_level_cell_index_partitioner(
const unsigned int level)
const
626 return number_cache.level_cell_index_partitioners[
level];
631 template <
int dim,
int spacedim>
636 return number_cache.number_of_global_coarse_cells;
641 template <
int dim,
int spacedim>
647 const
bool check_for_distorted_cells)
651 check_for_distorted_cells)
656 template <
int dim,
int spacedim>
667 template <
int dim,
int spacedim>
671 if (this->n_global_levels() <= 1)
680 const bool have_coarser_cell =
681 std::any_of(this->begin_active(this->n_global_levels() - 2),
682 this->end_active(this->n_global_levels() - 2),
689 this->mpi_communicator);
698#include "distributed/tria_base.inst"
bool is_locally_owned() const
void add_range(const size_type begin, const size_type end)
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual std::size_t memory_consumption() const
const std::set< types::subdomain_id > & level_ghost_owners() const
virtual types::global_cell_index n_global_active_cells() const override
const std::set< types::subdomain_id > & ghost_owners() const
types::subdomain_id locally_owned_subdomain() const override
virtual unsigned int n_global_levels() const override
unsigned int n_locally_owned_active_cells() const
virtual types::coarse_cell_id n_global_coarse_cells() const override
virtual void update_number_cache()
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcNeedsMPI()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
IndexSet complete_index_set(const IndexSet::size_type N)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
T sum(const T &t, const MPI_Comm mpi_communicator)
T logical_or(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
T max(const T &t, const MPI_Comm mpi_communicator)
std::vector< T > compute_set_union(const std::vector< T > &vec, const MPI_Comm comm)
const MPI_Datatype mpi_type_id_for_type
void release_all_unused_memory()
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
constexpr types::global_dof_index invalid_dof_index
bool is_nan(const double x)
unsigned int global_cell_index