16#include <deal.II/base/mpi.templates.h>
32 template <
int dim,
int spacedim>
42 namespace fullydistributed
44 template <
int dim,
int spacedim>
50 const
unsigned int n_partitions) {
53 , currently_processing_create_triangulation_for_internal_usage(
false)
54 , currently_processing_prepare_coarsening_and_refinement_for_internal_usage(
60 template <
int dim,
int spacedim>
68 Assert(construction_data.comm == this->mpi_communicator,
69 ExcMessage(
"MPI communicators do not match!"));
72 settings = construction_data.settings;
77 this->set_mesh_smoothing(
79 typename ::Triangulation<dim, spacedim>::MeshSmoothing
>(
83 this->set_mesh_smoothing(
85 typename ::Triangulation<dim, spacedim>::MeshSmoothing
>(
88 this->set_mesh_smoothing(construction_data.smoothing);
91 this->coarse_cell_id_to_coarse_cell_index_vector.clear();
92 this->coarse_cell_index_to_coarse_cell_id_vector.clear();
95 if (construction_data.coarse_cell_vertices.empty())
98 currently_processing_create_triangulation_for_internal_usage =
true;
100 currently_processing_create_triangulation_for_internal_usage =
false;
103 auto cell = this->
begin();
105 cell->set_level_subdomain_id(
110 this->coarse_cell_id_to_coarse_cell_index_vector.emplace_back(
112 this->coarse_cell_index_to_coarse_cell_id_vector.emplace_back(
118 this->coarse_cell_index_to_coarse_cell_id_vector =
119 construction_data.coarse_cell_index_to_coarse_cell_id;
122 this->coarse_cell_id_to_coarse_cell_index_vector.resize(
123 construction_data.coarse_cell_index_to_coarse_cell_id.size());
124 for (
unsigned int i = 0;
125 i < construction_data.coarse_cell_index_to_coarse_cell_id.size();
127 this->coarse_cell_id_to_coarse_cell_index_vector[i] =
129 construction_data.coarse_cell_index_to_coarse_cell_id[i], i);
131 std::sort(this->coarse_cell_id_to_coarse_cell_index_vector.begin(),
132 this->coarse_cell_id_to_coarse_cell_index_vector.end(),
133 [](
const auto &a,
const auto &b) {
134 return a.first < b.first;
138 currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
140 currently_processing_create_triangulation_for_internal_usage =
true;
143 currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
145 currently_processing_create_triangulation_for_internal_usage =
false;
148 auto cell_infos = construction_data.cell_infos;
153 std::sort(cell_info.begin(),
160 const auto a_coarse_cell_index =
161 this->coarse_cell_id_to_coarse_cell_index(
163 const auto b_coarse_cell_index =
164 this->coarse_cell_id_to_coarse_cell_index(
172 if (a_coarse_cell_index != b_coarse_cell_index)
173 return a_coarse_cell_index < b_coarse_cell_index;
180 for (
const auto &cell : this->cell_iterators())
182 if (cell->is_active())
183 cell->set_subdomain_id(
186 cell->set_level_subdomain_id(
191 for (
unsigned int level = 0;
200 while (cell_info->id != cell->id().template to_binary<dim>())
204 if (cell->is_active())
205 cell->set_subdomain_id(cell_info->subdomain_id);
209 construct_multigrid_hierarchy)
210 cell->set_level_subdomain_id(cell_info->level_subdomain_id);
215 this->update_number_cache();
216 this->update_cell_relations();
223 this->reference_cells =
225 this->mpi_communicator);
230 template <
int dim,
int spacedim>
233 const
std::vector<
Point<spacedim>> &vertices,
238 currently_processing_create_triangulation_for_internal_usage,
240 "You have called the overload of\n"
242 " parallel::fullydistributed::Triangulation::"
243 "create_triangulation()\n"
245 "which takes 3 arguments. This function is not yet implemented for "
246 "this class. If you have not called this function directly, it "
247 "might have been called via a function from the GridGenerator or "
248 "GridIn namespace. To set up a fully-distributed Triangulation with "
249 "these utility functions, please start by using the same process to "
250 "set up a serial Triangulation, parallel::shared::Triangulation, or "
251 "a parallel::distributed::Triangulation. Once that is complete use "
252 "the copy_triangulation() member function to finish setting up the "
253 "original fully distributed Triangulation. Alternatively, you can "
254 "use TriangulationDescription::Utilities::"
255 "create_description_from_triangulation() or "
256 "create_description_from_triangulation_in_groups() to create the "
257 "description of the local partition, and pass that description to "
258 "parallel::fullydistributed::Triangulation::create_triangulation()."));
267 template <
int dim,
int spacedim>
276 const ::Triangulation<dim, spacedim> *other_tria_ptr = &other_tria;
285 if (
dynamic_cast<const ::parallel::TriangulationBase<dim, spacedim>
286 *
>(&other_tria) ==
nullptr)
292 this->partitioner(serial_tria,
294 this->mpi_communicator));
297 if (this->is_multilevel_hierarchy_constructed())
301 other_tria_ptr = &serial_tria;
307 this->mpi_communicator,
311 this->create_triangulation(construction_data);
316 template <
int dim,
int spacedim>
320 const
unsigned int)> &partitioner,
323 this->partitioner = partitioner;
324 this->settings = settings;
329 template <
int dim,
int spacedim>
335 this->partitioner_distributed = &partitioner;
336 this->settings = settings;
341 template <
int dim,
int spacedim>
346 this->signals.pre_distributed_repartition();
352 this->partitioner_distributed->partition(*
this),
357 this->coarse_cell_id_to_coarse_cell_index_vector.clear();
358 this->coarse_cell_index_to_coarse_cell_id_vector.clear();
361 this->create_triangulation(construction_data);
364 this->signals.post_distributed_repartition();
369 template <
int dim,
int spacedim>
378 template <
int dim,
int spacedim>
383 currently_processing_prepare_coarsening_and_refinement_for_internal_usage,
384 ExcMessage(
"No coarsening and refinement is supported!"));
386 return ::Triangulation<dim, spacedim>::
387 prepare_coarsening_and_refinement();
392 template <
int dim,
int spacedim>
396 const std::size_t mem =
400 coarse_cell_id_to_coarse_cell_index_vector) +
402 coarse_cell_index_to_coarse_cell_id_vector);
408 template <
int dim,
int spacedim>
420 template <
int dim,
int spacedim>
423 coarse_cell_id_to_coarse_cell_index(
424 const
types::coarse_cell_id coarse_cell_id)
const
426 const auto coarse_cell_index = std::lower_bound(
427 coarse_cell_id_to_coarse_cell_index_vector.begin(),
428 coarse_cell_id_to_coarse_cell_index_vector.end(),
430 [](
const std::pair<types::coarse_cell_id, unsigned int> &pair,
432 if (coarse_cell_index !=
433 coarse_cell_id_to_coarse_cell_index_vector.cend())
434 return coarse_cell_index->second;
441 template <
int dim,
int spacedim>
445 const unsigned int coarse_cell_index)
const
448 coarse_cell_index_to_coarse_cell_id_vector.size());
450 const auto coarse_cell_id =
451 coarse_cell_index_to_coarse_cell_id_vector[coarse_cell_index];
453 ExcMessage(
"You are trying to access a dummy cell!"));
454 return coarse_cell_id;
458 template <
int dim,
int spacedim>
463 this->local_cell_relations.
clear();
464 this->local_cell_relations.reserve(this->n_locally_owned_active_cells());
466 for (
const auto &cell : this->active_cell_iterators())
467 if (cell->is_locally_owned())
468 this->local_cell_relations.emplace_back(
474 template <
int dim,
int spacedim>
478#ifdef DEAL_II_WITH_MPI
481 this->cell_attached_data.n_attached_deserialize == 0,
483 "Not all SolutionTransfer objects have been deserialized after the last call to load()."));
484 Assert(this->n_cells() > 0,
485 ExcMessage(
"Can not save() an empty Triangulation."));
493 unsigned int n_locally_owned_cells = this->n_locally_owned_active_cells();
495 unsigned int global_first_cell = 0;
497 int ierr = MPI_Exscan(&n_locally_owned_cells,
502 this->mpi_communicator);
505 global_first_cell *=
sizeof(
unsigned int);
510 std::string fname = std::string(filename) +
".info";
511 std::ofstream f(fname);
512 f <<
"version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_global_active_cells"
517 <<
" " << this->cell_attached_data.pack_callbacks_fixed.size()
518 <<
" " << this->cell_attached_data.pack_callbacks_variable.size()
519 <<
" " << this->n_global_active_cells() << std::endl;
523 this->save_attached_data(global_first_cell,
524 this->n_global_active_cells(),
530 int ierr = MPI_Info_create(&info);
533 const std::string fname_tria = filename +
"_triangulation.data";
537 ierr = MPI_File_open(this->mpi_communicator,
539 MPI_MODE_CREATE | MPI_MODE_WRONLY,
544 ierr = MPI_File_set_size(fh, 0);
548 ierr = MPI_Barrier(this->mpi_communicator);
550 ierr = MPI_Info_free(&info);
557 this->mpi_communicator,
561 std::vector<char> buffer;
565 const std::uint64_t buffer_size = buffer.size();
567 std::uint64_t offset = 0;
575 this->mpi_communicator);
579 ierr = MPI_File_write_at(
581 myrank *
sizeof(std::uint64_t),
589 const std::uint64_t global_position =
590 mpisize *
sizeof(std::uint64_t) + offset;
602 ierr = MPI_File_close(&fh);
614 template <
int dim,
int spacedim>
618#ifdef DEAL_II_WITH_MPI
619 Assert(this->n_cells() == 0,
620 ExcMessage(
"load() only works if the Triangulation is empty!"));
623 unsigned int version, numcpus, attached_count_fixed,
624 attached_count_variable, n_global_active_cells;
626 std::string fname = std::string(filename) +
".info";
627 std::ifstream f(fname);
629 std::string firstline;
630 getline(f, firstline);
631 f >> version >> numcpus >> attached_count_fixed >>
632 attached_count_variable >> n_global_active_cells;
635 const auto expected_version = ::internal::
636 CellAttachedDataSerializer<dim, spacedim>::version_number;
639 ExcMessage(
"Incompatible version found in .info file."));
652 int ierr = MPI_Info_create(&info);
655 const std::string fname_tria = filename +
"_triangulation.data";
658 ierr = MPI_File_open(this->mpi_communicator,
665 ierr = MPI_Info_free(&info);
669 std::uint64_t buffer_size;
671 ierr = MPI_File_read_at(
673 myrank *
sizeof(std::uint64_t),
680 std::uint64_t offset = 0;
688 this->mpi_communicator);
692 const std::uint64_t global_position =
693 mpisize *
sizeof(std::uint64_t) + offset;
696 std::vector<char> buffer(buffer_size);
706 ierr = MPI_File_close(&fh);
709 auto construction_data = ::Utilities::template unpack<
714 construction_data.
comm = this->mpi_communicator;
716 this->create_triangulation(construction_data);
720 unsigned int n_locally_owned_cells = this->n_locally_owned_active_cells();
722 unsigned int global_first_cell = 0;
724 int ierr = MPI_Exscan(&n_locally_owned_cells,
729 this->mpi_communicator);
732 global_first_cell *=
sizeof(
unsigned int);
734 Assert(this->n_global_active_cells() == n_global_active_cells,
735 ExcMessage(
"Number of global active cells differ!"));
739 this->cell_attached_data.n_attached_data_sets = 0;
740 this->cell_attached_data.n_attached_deserialize =
741 attached_count_fixed + attached_count_variable;
744 this->load_attached_data(global_first_cell,
745 this->n_global_active_cells(),
746 this->n_locally_owned_active_cells(),
748 attached_count_fixed,
749 attached_count_variable);
751 this->update_cell_relations();
752 this->update_periodic_face_map();
753 this->update_number_cache();
763 template <
int dim,
int spacedim>
772 for (
const auto &cell : this->active_cell_iterators())
773 if (!cell->is_artificial())
774 number_of_global_coarse_cells =
775 std::max(number_of_global_coarse_cells,
776 cell->id().get_coarse_cell_id());
778 number_of_global_coarse_cells =
780 this->mpi_communicator) +
783 this->number_cache.number_of_global_coarse_cells =
784 number_of_global_coarse_cells;
794#include "distributed/fully_distributed_tria.inst"
types::coarse_cell_id get_coarse_cell_id() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual std::size_t memory_consumption() const override
virtual void update_number_cache()
virtual void clear() override
virtual types::coarse_cell_id coarse_cell_index_to_coarse_cell_id(const unsigned int coarse_cell_index) const override
void create_triangulation(const TriangulationDescription::Description< dim, spacedim > &construction_data) override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcNeedsMPI()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void hyper_cube(Triangulation< dim, spacedim > &tria, const double left=0., const double right=1., const bool colorize=false)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
Description< dim, spacedim > create_description_from_triangulation(const ::Triangulation< dim, spacedim > &tria, const MPI_Comm comm, const TriangulationDescription::Settings settings=TriangulationDescription::Settings::default_setting, const unsigned int my_rank_in=numbers::invalid_unsigned_int)
@ construct_multigrid_hierarchy
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
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)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
const MPI_Datatype mpi_type_id_for_type
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
constexpr unsigned int invalid_unsigned_int
constexpr types::subdomain_id artificial_subdomain_id
constexpr types::coarse_cell_id invalid_coarse_cell_id
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
std::vector< std::vector< CellData< dim > > > cell_infos