17 #include <deal.II/base/logstream.h> 18 #include <deal.II/base/memory_consumption.h> 19 #include <deal.II/base/utilities.h> 21 #include <deal.II/distributed/p4est_wrappers.h> 22 #include <deal.II/distributed/tria.h> 24 #include <deal.II/grid/grid_tools.h> 25 #include <deal.II/grid/tria.h> 26 #include <deal.II/grid/tria_accessor.h> 27 #include <deal.II/grid/tria_iterator.h> 29 #include <deal.II/lac/dynamic_sparsity_pattern.h> 30 #include <deal.II/lac/sparsity_tools.h> 38 DEAL_II_NAMESPACE_OPEN
41 #ifdef DEAL_II_WITH_P4EST 45 template <
int dim,
int spacedim>
47 get_vertex_to_cell_mappings(
49 std::vector<unsigned int> & vertex_touch_count,
50 std::vector<std::list<
52 unsigned int>>> & vertex_to_cell)
54 vertex_touch_count.resize(triangulation.n_vertices());
55 vertex_to_cell.resize(triangulation.n_vertices());
58 triangulation.begin_active();
59 cell != triangulation.end();
61 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
63 ++vertex_touch_count[cell->vertex_index(v)];
64 vertex_to_cell[cell->vertex_index(v)].emplace_back(cell, v);
70 template <
int dim,
int spacedim>
72 get_edge_to_cell_mappings(
74 std::vector<unsigned int> & edge_touch_count,
75 std::vector<std::list<
77 unsigned int>>> & edge_to_cell)
81 edge_touch_count.resize(triangulation.n_active_lines());
82 edge_to_cell.resize(triangulation.n_active_lines());
85 triangulation.begin_active();
86 cell != triangulation.end();
88 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
90 ++edge_touch_count[cell->line(l)->index()];
91 edge_to_cell[cell->line(l)->index()].emplace_back(cell, l);
101 template <
int dim,
int spacedim>
103 set_vertex_and_cell_info(
105 const std::vector<unsigned int> & vertex_touch_count,
106 const std::vector<std::list<
108 unsigned int>>> & vertex_to_cell,
109 const std::vector<types::global_dof_index>
110 & coarse_cell_to_p4est_tree_permutation,
111 const bool set_vertex_info,
120 Assert(triangulation.get_used_vertices().size() ==
121 triangulation.get_vertices().size(),
123 Assert(std::find(triangulation.get_used_vertices().begin(),
124 triangulation.get_used_vertices().end(),
125 false) == triangulation.get_used_vertices().end(),
127 if (set_vertex_info ==
true)
128 for (
unsigned int v = 0; v < triangulation.n_vertices(); ++v)
130 connectivity->vertices[3 * v] = triangulation.get_vertices()[v][0];
131 connectivity->vertices[3 * v + 1] =
132 triangulation.get_vertices()[v][1];
133 connectivity->vertices[3 * v + 2] =
134 (spacedim == 2 ? 0 : triangulation.get_vertices()[v][2]);
143 cell = triangulation.begin_active(),
144 endc = triangulation.end();
145 for (; cell != endc; ++cell)
147 const unsigned int index =
148 coarse_cell_to_p4est_tree_permutation[cell->index()];
150 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
152 if (set_vertex_info ==
true)
155 v] = cell->vertex_index(v);
158 v] = cell->vertex_index(v);
163 for (
unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f)
164 if (cell->face(f)->at_boundary() ==
false)
167 coarse_cell_to_p4est_tree_permutation[cell->neighbor(f)->index()];
171 coarse_cell_to_p4est_tree_permutation[cell->index()];
175 for (
unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f)
176 if (cell->face(f)->at_boundary() ==
false)
182 connectivity->tree_to_face
184 cell->neighbor_of_neighbor(f);
203 connectivity->tree_to_face[index * 6 + f] =
204 cell->neighbor_of_neighbor(f);
206 unsigned int face_idx_list[2] = {
207 f, cell->neighbor_of_neighbor(f)};
209 cell_list[2] = {cell, cell->neighbor(f)};
210 unsigned int smaller_idx = 0;
212 if (f > cell->neighbor_of_neighbor(f))
215 unsigned int larger_idx = (smaller_idx + 1) % 2;
223 unsigned int g_idx = cell_list[smaller_idx]->vertex_index(
225 face_idx_list[smaller_idx],
227 cell_list[smaller_idx]->face_orientation(
228 face_idx_list[smaller_idx]),
229 cell_list[smaller_idx]->face_flip(
230 face_idx_list[smaller_idx]),
231 cell_list[smaller_idx]->face_rotation(
232 face_idx_list[smaller_idx])));
236 for (
unsigned int i = 0;
237 i < GeometryInfo<dim>::vertices_per_face;
241 cell_list[larger_idx]->vertex_index(
243 face_idx_list[larger_idx], i));
252 connectivity->tree_to_face[index * 6 + f] += 6 * v;
266 connectivity->ctt_offset[0] = 0;
267 std::partial_sum(vertex_touch_count.begin(),
268 vertex_touch_count.end(),
269 &connectivity->ctt_offset[1]);
272 std::accumulate(vertex_touch_count.begin(), vertex_touch_count.end(), 0u);
274 Assert(connectivity->ctt_offset[triangulation.n_vertices()] == num_vtt,
277 for (
unsigned int v = 0; v < triangulation.n_vertices(); ++v)
279 Assert(vertex_to_cell[v].size() == vertex_touch_count[v],
283 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
284 unsigned int>>::const_iterator p =
285 vertex_to_cell[v].begin();
286 for (
unsigned int c = 0; c < vertex_touch_count[v]; ++c, ++p)
288 connectivity->corner_to_tree[connectivity->ctt_offset[v] + c] =
289 coarse_cell_to_p4est_tree_permutation[p->first->index()];
290 connectivity->corner_to_corner[connectivity->ctt_offset[v] + c] =
298 template <
int dim,
int spacedim>
304 Assert(coarse_grid_cell < parallel_forest->connectivity->num_trees,
306 return ((coarse_grid_cell >= parallel_forest->first_local_tree) &&
307 (coarse_grid_cell <= parallel_forest->last_local_tree));
311 template <
int dim,
int spacedim>
313 delete_all_children_and_self(
316 if (cell->has_children())
317 for (
unsigned int c = 0; c < cell->n_children(); ++c)
318 delete_all_children_and_self<dim, spacedim>(cell->child(c));
320 cell->set_coarsen_flag();
325 template <
int dim,
int spacedim>
330 if (cell->has_children())
331 for (
unsigned int c = 0; c < cell->n_children(); ++c)
332 delete_all_children_and_self<dim, spacedim>(cell->child(c));
336 template <
int dim,
int spacedim>
338 determine_level_subdomain_id_recursively(
345 const std::vector<std::vector<bool>> & marked_vertices)
352 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
354 if (marked_vertices[dealii_cell->level()]
355 [dealii_cell->vertex_index(v)])
374 if (!used && dealii_cell->active() &&
375 dealii_cell->is_artificial() ==
false &&
376 dealii_cell->level() + 1 <
static_cast<int>(marked_vertices.size()))
378 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
381 if (marked_vertices[dealii_cell->level() + 1]
382 [dealii_cell->vertex_index(v)])
391 if (!used && dealii_cell->active() &&
392 dealii_cell->is_artificial() ==
false && dealii_cell->level() > 0)
394 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
397 if (marked_vertices[dealii_cell->level() - 1]
398 [dealii_cell->vertex_index(v)])
409 &forest, tree_index, &p4est_cell, my_subdomain);
410 Assert((owner != -2) && (owner != -1),
412 dealii_cell->set_level_subdomain_id(owner);
416 if (dealii_cell->has_children())
420 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
425 P4EST_QUADRANT_INIT(&p4est_child[c]);
428 P8EST_QUADRANT_INIT(&p4est_child[c]);
438 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
441 determine_level_subdomain_id_recursively<dim, spacedim>(
444 dealii_cell->child(c),
454 template <
int dim,
int spacedim>
456 match_tree_recursively(
464 if (sc_array_bsearch(const_cast<sc_array_t *>(&tree.quadrants),
470 delete_all_children<dim, spacedim>(dealii_cell);
471 if (!dealii_cell->has_children())
472 dealii_cell->set_subdomain_id(my_subdomain);
481 if (dealii_cell->has_children() ==
false)
482 dealii_cell->set_refine_flag();
487 for (
unsigned int c = 0;
488 c < GeometryInfo<dim>::max_children_per_cell;
493 P4EST_QUADRANT_INIT(&p4est_child[c]);
496 P8EST_QUADRANT_INIT(&p4est_child[c]);
506 for (
unsigned int c = 0;
507 c < GeometryInfo<dim>::max_children_per_cell;
512 &p4est_child[c]) ==
false)
518 delete_all_children<dim, spacedim>(dealii_cell->child(c));
519 dealii_cell->child(c)->recursively_set_subdomain_id(
526 match_tree_recursively<dim, spacedim>(tree,
527 dealii_cell->child(c),
537 template <
int dim,
int spacedim>
540 const ::Triangulation<dim, spacedim> * tria,
541 unsigned int dealii_index,
545 const int l = ghost_quadrant.level;
547 for (
int i = 0; i <
l; ++i)
552 if (cell->has_children() ==
false)
554 cell->clear_coarsen_flag();
555 cell->set_refine_flag();
562 dealii_index = cell->child_index(child_id);
568 if (cell->has_children())
569 delete_all_children<dim, spacedim>(cell);
572 cell->clear_coarsen_flag();
573 cell->set_subdomain_id(ghost_owner);
584 template <
int dim,
int spacedim>
585 class RefineAndCoarsenList
589 const std::vector<types::global_dof_index>
590 &p4est_tree_to_coarse_cell_permutation,
618 pointers_are_at_end()
const;
621 std::vector<typename internal::p4est::types<dim>::quadrant> refine_list;
622 typename std::vector<typename internal::p4est::types<dim>::quadrant>::
623 const_iterator current_refine_pointer;
625 std::vector<typename internal::p4est::types<dim>::quadrant> coarsen_list;
626 typename std::vector<typename internal::p4est::types<dim>::quadrant>::
627 const_iterator current_coarsen_pointer;
638 template <
int dim,
int spacedim>
640 RefineAndCoarsenList<dim, spacedim>::pointers_are_at_end()
const 642 return ((current_refine_pointer == refine_list.end()) &&
643 (current_coarsen_pointer == coarsen_list.end()));
648 template <
int dim,
int spacedim>
649 RefineAndCoarsenList<dim, spacedim>::RefineAndCoarsenList(
651 const std::vector<types::global_dof_index>
652 & p4est_tree_to_coarse_cell_permutation,
656 unsigned int n_refine_flags = 0, n_coarsen_flags = 0;
658 triangulation.begin_active();
659 cell != triangulation.end();
663 if (cell->subdomain_id() != my_subdomain)
666 if (cell->refine_flag_set())
668 else if (cell->coarsen_flag_set())
672 refine_list.reserve(n_refine_flags);
673 coarsen_list.reserve(n_coarsen_flags);
683 for (
unsigned int c = 0; c < triangulation.n_cells(0); ++c)
685 unsigned int coarse_cell_index =
686 p4est_tree_to_coarse_cell_permutation[c];
689 &triangulation, 0, coarse_cell_index);
695 p4est_cell.p.which_tree = c;
696 build_lists(cell, p4est_cell, my_subdomain);
704 for (
unsigned int i = 1; i < refine_list.size(); ++i)
705 Assert(refine_list[i].p.which_tree >= refine_list[i - 1].p.which_tree,
707 for (
unsigned int i = 1; i < coarsen_list.size(); ++i)
708 Assert(coarsen_list[i].p.which_tree >= coarsen_list[i - 1].p.which_tree,
711 current_refine_pointer = refine_list.begin();
712 current_coarsen_pointer = coarsen_list.begin();
717 template <
int dim,
int spacedim>
719 RefineAndCoarsenList<dim, spacedim>::build_lists(
724 if (!cell->has_children())
726 if (cell->subdomain_id() == my_subdomain)
728 if (cell->refine_flag_set())
729 refine_list.push_back(p4est_cell);
730 else if (cell->coarsen_flag_set())
731 coarsen_list.push_back(p4est_cell);
738 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
743 P4EST_QUADRANT_INIT(&p4est_child[c]);
746 P8EST_QUADRANT_INIT(&p4est_child[c]);
753 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
756 p4est_child[c].p.which_tree = p4est_cell.p.which_tree;
757 build_lists(cell->child(c), p4est_child[c], my_subdomain);
763 template <
int dim,
int spacedim>
765 RefineAndCoarsenList<dim, spacedim>::refine_callback(
770 RefineAndCoarsenList<dim, spacedim> *this_object =
771 reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *
>(
772 forest->user_pointer);
776 if (this_object->current_refine_pointer == this_object->refine_list.end())
779 Assert(coarse_cell_index <=
780 this_object->current_refine_pointer->p.which_tree,
785 if (coarse_cell_index < this_object->current_refine_pointer->p.which_tree)
789 Assert(coarse_cell_index <=
790 this_object->current_refine_pointer->p.which_tree,
796 quadrant, &*this_object->current_refine_pointer) <= 0,
801 quadrant, &*this_object->current_refine_pointer))
803 ++this_object->current_refine_pointer;
813 template <
int dim,
int spacedim>
815 RefineAndCoarsenList<dim, spacedim>::coarsen_callback(
820 RefineAndCoarsenList<dim, spacedim> *this_object =
821 reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *
>(
822 forest->user_pointer);
826 if (this_object->current_coarsen_pointer == this_object->coarsen_list.end())
829 Assert(coarse_cell_index <=
830 this_object->current_coarsen_pointer->p.which_tree,
835 if (coarse_cell_index < this_object->current_coarsen_pointer->p.which_tree)
839 Assert(coarse_cell_index <=
840 this_object->current_coarsen_pointer->p.which_tree,
846 children[0], &*this_object->current_coarsen_pointer) <= 0,
852 children[0], &*this_object->current_coarsen_pointer))
855 ++this_object->current_coarsen_pointer;
859 for (
unsigned int c = 1; c < GeometryInfo<dim>::max_children_per_cell;
863 children[c], &*this_object->current_coarsen_pointer),
865 ++this_object->current_coarsen_pointer;
883 template <
int dim,
int spacedim>
884 class PartitionWeights
892 explicit PartitionWeights(
const std::vector<unsigned int> &cell_weights);
907 std::vector<unsigned int> cell_weights_list;
908 std::vector<unsigned int>::const_iterator current_pointer;
912 template <
int dim,
int spacedim>
913 PartitionWeights<dim, spacedim>::PartitionWeights(
914 const std::vector<unsigned int> &cell_weights)
915 : cell_weights_list(cell_weights)
919 current_pointer = cell_weights_list.begin();
923 template <
int dim,
int spacedim>
925 PartitionWeights<dim, spacedim>::cell_weight(
934 PartitionWeights<dim, spacedim> *this_object =
935 reinterpret_cast<PartitionWeights<dim, spacedim> *
>(forest->user_pointer);
937 Assert(this_object->current_pointer >=
938 this_object->cell_weights_list.begin(),
940 Assert(this_object->current_pointer < this_object->cell_weights_list.end(),
944 return *this_object->current_pointer++;
949 template <
int dim,
int spacedim>
950 using quadrant_cell_relation_t =
typename std::tuple<
951 typename ::internal::p4est::types<dim>::quadrant *,
952 typename ::Triangulation<dim, spacedim>::CellStatus,
953 typename ::Triangulation<dim, spacedim>::cell_iterator>;
966 template <
int dim,
int spacedim>
968 add_single_quadrant_cell_relation(
969 std::vector<quadrant_cell_relation_t<dim, spacedim>> & quad_cell_rel,
970 const typename ::internal::p4est::types<dim>::tree & tree,
971 const unsigned int idx,
975 const unsigned int local_quadrant_index = tree.quadrants_offset + idx;
978 static_cast<typename ::internal::p4est::types<dim>::quadrant *
>(
979 sc_array_index(const_cast<sc_array_t *>(&tree.quadrants), idx));
985 quad_cell_rel[local_quadrant_index] =
986 std::make_tuple(q, status, dealii_cell);
1000 template <
int dim,
int spacedim>
1002 update_quadrant_cell_relations_recursively(
1003 std::vector<quadrant_cell_relation_t<dim, spacedim>> & quad_cell_rel,
1004 const typename ::internal::p4est::types<dim>::tree & tree,
1006 const typename ::internal::p4est::types<dim>::quadrant &p4est_cell)
1009 const int idx = sc_array_bsearch(
1010 const_cast<sc_array_t *>(&tree.quadrants),
1015 const_cast<typename ::internal::p4est::types<dim>::tree *
>(
1017 &p4est_cell) ==
false))
1022 const bool p4est_has_children = (idx == -1);
1023 if (p4est_has_children && dealii_cell->has_children())
1026 typename ::internal::p4est::types<dim>::quadrant
1029 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1034 P4EST_QUADRANT_INIT(&p4est_child[c]);
1037 P8EST_QUADRANT_INIT(&p4est_child[c]);
1044 &p4est_cell, p4est_child);
1046 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1049 update_quadrant_cell_relations_recursively<dim, spacedim>(
1050 quad_cell_rel, tree, dealii_cell->child(c), p4est_child[c]);
1053 else if (!p4est_has_children && !dealii_cell->has_children())
1057 add_single_quadrant_cell_relation<dim, spacedim>(
1064 else if (p4est_has_children)
1072 typename ::internal::p4est::types<dim>::quadrant
1074 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1079 P4EST_QUADRANT_INIT(&p4est_child[c]);
1082 P8EST_QUADRANT_INIT(&p4est_child[c]);
1089 &p4est_cell, p4est_child);
1096 for (
unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_cell;
1099 child_idx = sc_array_bsearch(
1100 const_cast<sc_array_t *>(&tree.quadrants),
1107 add_single_quadrant_cell_relation<dim, spacedim>(
1108 quad_cell_rel, tree, child_idx, dealii_cell, cell_status);
1116 add_single_quadrant_cell_relation<dim, spacedim>(
1130 namespace distributed
1135 template <
int dim,
int spacedim>
1137 MPI_Comm mpi_communicator)
1138 : mpi_communicator(mpi_communicator)
1139 , variable_size_data_stored(false)
1144 template <
int dim,
int spacedim>
1147 const std::vector<quadrant_cell_relation_t> &quad_cell_relations,
1148 const std::vector<typename CellAttachedData::pack_callback_t>
1149 &pack_callbacks_fixed,
1150 const std::vector<typename CellAttachedData::pack_callback_t>
1151 &pack_callbacks_variable)
1153 Assert(src_data_fixed.size() == 0,
1154 ExcMessage(
"Previously packed data has not been released yet!"));
1157 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
1158 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
1162 variable_size_data_stored = (n_callbacks_variable > 0);
1168 std::vector<unsigned int> cell_sizes_variable_cumulative(
1169 n_callbacks_variable);
1183 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
1184 quad_cell_relations.size());
1185 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
1186 variable_size_data_stored ? quad_cell_relations.size() : 0);
1194 auto quad_cell_rel_it = quad_cell_relations.cbegin();
1195 auto data_cell_fixed_it = packed_fixed_size_data.begin();
1196 auto data_cell_variable_it = packed_variable_size_data.begin();
1197 for (; quad_cell_rel_it != quad_cell_relations.cend();
1198 ++quad_cell_rel_it, ++data_cell_fixed_it)
1200 const auto &cell_status = std::get<1>(*quad_cell_rel_it);
1201 const auto &dealii_cell = std::get<2>(*quad_cell_rel_it);
1204 switch (cell_status)
1222 for (
unsigned int c = 0;
1223 c < GeometryInfo<dim>::max_children_per_cell;
1246 const unsigned int n_fixed_size_data_sets_on_cell =
1250 spacedim>::CELL_INVALID) ?
1252 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
1253 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
1256 auto data_fixed_it = data_cell_fixed_it->begin();
1269 spacedim>::CELL_INVALID)
1272 for (
auto callback_it = pack_callbacks_fixed.cbegin();
1273 callback_it != pack_callbacks_fixed.cend();
1274 ++callback_it, ++data_fixed_it)
1276 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
1283 if (variable_size_data_stored)
1285 const unsigned int n_variable_size_data_sets_on_cell =
1290 n_callbacks_variable);
1291 data_cell_variable_it->resize(
1292 n_variable_size_data_sets_on_cell);
1294 auto callback_it = pack_callbacks_variable.cbegin();
1295 auto data_variable_it = data_cell_variable_it->begin();
1296 auto sizes_variable_it =
1297 cell_sizes_variable_cumulative.begin();
1298 for (; callback_it != pack_callbacks_variable.cend();
1299 ++callback_it, ++data_variable_it, ++sizes_variable_it)
1302 (*callback_it)(dealii_cell, cell_status);
1306 *sizes_variable_it = data_variable_it->size();
1310 std::partial_sum(cell_sizes_variable_cumulative.begin(),
1311 cell_sizes_variable_cumulative.end(),
1312 cell_sizes_variable_cumulative.begin());
1318 data_fixed_it->resize(n_callbacks_variable *
1319 sizeof(
unsigned int));
1320 for (
unsigned int i = 0; i < n_callbacks_variable; ++i)
1321 std::memcpy(&(data_fixed_it->at(i *
1322 sizeof(
unsigned int))),
1323 &(cell_sizes_variable_cumulative.at(i)),
1324 sizeof(
unsigned int));
1331 Assert(data_fixed_it == data_cell_fixed_it->end(),
1338 if (variable_size_data_stored)
1339 ++data_cell_variable_it;
1356 std::vector<unsigned int> local_sizes_fixed(
1357 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
1358 for (
const auto &data_cell : packed_fixed_size_data)
1360 if (data_cell.size() == local_sizes_fixed.size())
1362 auto sizes_fixed_it = local_sizes_fixed.begin();
1363 auto data_fixed_it = data_cell.cbegin();
1364 for (; data_fixed_it != data_cell.cend();
1365 ++data_fixed_it, ++sizes_fixed_it)
1367 *sizes_fixed_it = data_fixed_it->size();
1375 for (
auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
1376 data_cell_fixed_it != packed_fixed_size_data.cend();
1377 ++data_cell_fixed_it)
1379 Assert((data_cell_fixed_it->size() == 1) ||
1380 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
1387 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
1389 this->mpi_communicator,
1390 global_sizes_fixed);
1394 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
1395 std::partial_sum(global_sizes_fixed.begin(),
1396 global_sizes_fixed.end(),
1397 sizes_fixed_cumulative.begin());
1402 if (variable_size_data_stored)
1404 src_sizes_variable.reserve(packed_variable_size_data.size());
1405 for (
const auto &data_cell : packed_variable_size_data)
1407 int variable_data_size_on_cell = 0;
1409 for (
const auto &data : data_cell)
1410 variable_data_size_on_cell += data.size();
1412 src_sizes_variable.push_back(variable_data_size_on_cell);
1419 const unsigned int expected_size_fixed =
1420 quad_cell_relations.size() * sizes_fixed_cumulative.back();
1421 const unsigned int expected_size_variable =
1422 std::accumulate(src_sizes_variable.begin(),
1423 src_sizes_variable.end(),
1424 std::vector<int>::size_type(0));
1427 src_data_fixed.reserve(expected_size_fixed);
1428 for (
const auto &data_cell_fixed : packed_fixed_size_data)
1432 for (
const auto &data_fixed : data_cell_fixed)
1433 std::move(data_fixed.begin(),
1435 std::back_inserter(src_data_fixed));
1441 if ((data_cell_fixed.size() == 1) &&
1442 (sizes_fixed_cumulative.size() > 1))
1444 const std::size_t bytes_skipped =
1445 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
1447 src_data_fixed.insert(src_data_fixed.end(),
1449 static_cast<char>(-1));
1455 if (variable_size_data_stored)
1457 src_data_variable.reserve(expected_size_variable);
1458 for (
const auto &data_cell : packed_variable_size_data)
1462 for (
const auto &data : data_cell)
1463 std::move(data.begin(),
1465 std::back_inserter(src_data_variable));
1471 Assert(src_data_variable.size() == expected_size_variable,
1477 template <
int dim,
int spacedim>
1480 const typename ::internal::p4est::types<dim>::forest
1482 const typename ::internal::p4est::types<dim>::gloidx
1483 *previous_global_first_quadrant)
1485 Assert(sizes_fixed_cumulative.size() > 0,
1489 dest_data_fixed.resize(parallel_forest->local_num_quadrants *
1490 sizes_fixed_cumulative.back());
1493 typename ::internal::p4est::types<dim>::transfer_context
1497 parallel_forest->global_first_quadrant,
1498 previous_global_first_quadrant,
1499 parallel_forest->mpicomm,
1501 dest_data_fixed.data(),
1502 src_data_fixed.data(),
1503 sizes_fixed_cumulative.back());
1505 if (variable_size_data_stored)
1508 dest_sizes_variable.resize(parallel_forest->local_num_quadrants);
1513 parallel_forest->global_first_quadrant,
1514 previous_global_first_quadrant,
1515 parallel_forest->mpicomm,
1517 dest_sizes_variable.data(),
1518 src_sizes_variable.data(),
1525 src_data_fixed.clear();
1526 src_data_fixed.shrink_to_fit();
1528 if (variable_size_data_stored)
1531 dest_data_variable.resize(
1532 std::accumulate(dest_sizes_variable.begin(),
1533 dest_sizes_variable.end(),
1534 std::vector<int>::size_type(0)));
1536 # if DEAL_II_P4EST_VERSION_GTE(2, 0, 65, 0) 1543 if (src_sizes_variable.size() == 0)
1544 src_sizes_variable.resize(1);
1545 if (dest_sizes_variable.size() == 0)
1546 dest_sizes_variable.resize(1);
1551 parallel_forest->global_first_quadrant,
1552 previous_global_first_quadrant,
1553 parallel_forest->mpicomm,
1555 dest_data_variable.data(),
1556 dest_sizes_variable.data(),
1557 src_data_variable.data(),
1558 src_sizes_variable.data());
1561 src_sizes_variable.clear();
1562 src_sizes_variable.shrink_to_fit();
1563 src_data_variable.clear();
1564 src_data_variable.shrink_to_fit();
1570 template <
int dim,
int spacedim>
1573 std::vector<quadrant_cell_relation_t> &quad_cell_relations)
const 1575 Assert(sizes_fixed_cumulative.size() > 0,
1577 if (quad_cell_relations.size() > 0)
1579 Assert(dest_data_fixed.size() > 0,
1584 const unsigned int size = sizes_fixed_cumulative.front();
1590 auto quad_cell_rel_it = quad_cell_relations.begin();
1591 auto dest_fixed_it = dest_data_fixed.cbegin();
1592 for (; quad_cell_rel_it != quad_cell_relations.end();
1593 ++quad_cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
1595 std::get<1>(*quad_cell_rel_it) =
1597 Triangulation<dim, spacedim>::CellStatus>(
1599 dest_fixed_it + size,
1606 template <
int dim,
int spacedim>
1609 const std::vector<quadrant_cell_relation_t> &quad_cell_relations,
1610 const unsigned int handle,
1611 const std::function<
void(
1612 const typename ::Triangulation<dim, spacedim>::cell_iterator &,
1613 const typename ::Triangulation<dim, spacedim>::CellStatus &,
1614 const boost::iterator_range<std::vector<char>::const_iterator> &)>
1615 &unpack_callback)
const 1621 const bool callback_variable_transfer = (handle % 2 == 0);
1622 const unsigned int callback_index = handle / 2;
1624 Assert(sizes_fixed_cumulative.size() > 0,
1626 if (quad_cell_relations.size() > 0)
1628 Assert(dest_data_fixed.size() > 0,
1631 if (callback_variable_transfer)
1632 Assert(dest_data_variable.size() > 0,
1636 std::vector<char>::const_iterator dest_data_it;
1637 std::vector<char>::const_iterator dest_sizes_cell_it;
1647 if (callback_variable_transfer)
1660 const unsigned int offset_variable_data_sizes =
1661 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
1668 dest_sizes_cell_it = dest_data_fixed.cbegin() +
1669 offset_variable_data_sizes +
1670 callback_index *
sizeof(
unsigned int);
1673 dest_data_it = dest_data_variable.cbegin();
1680 offset = sizes_fixed_cumulative[callback_index];
1681 size = sizes_fixed_cumulative[callback_index + 1] - offset;
1682 data_increment = sizes_fixed_cumulative.back();
1688 dest_data_it = dest_data_fixed.cbegin() + offset;
1692 auto quad_cell_rel_it = quad_cell_relations.begin();
1693 auto dest_sizes_it = dest_sizes_variable.cbegin();
1694 for (; quad_cell_rel_it != quad_cell_relations.end();
1695 ++quad_cell_rel_it, dest_data_it += data_increment)
1697 const auto &cell_status = std::get<1>(*quad_cell_rel_it);
1698 const auto &dealii_cell = std::get<2>(*quad_cell_rel_it);
1700 if (callback_variable_transfer)
1704 data_increment = *dest_sizes_it;
1708 spacedim>::CELL_INVALID)
1712 if (callback_index == 0)
1715 std::memcpy(&offset,
1716 &(*(dest_sizes_cell_it -
sizeof(
unsigned int))),
1717 sizeof(
unsigned int));
1720 &(*dest_sizes_cell_it),
1721 sizeof(
unsigned int));
1728 dest_data_it += offset;
1729 data_increment -= offset;
1733 dest_sizes_cell_it += sizes_fixed_cumulative.back();
1737 switch (cell_status)
1740 spacedim>::CELL_PERSIST:
1742 spacedim>::CELL_COARSEN:
1743 unpack_callback(dealii_cell,
1745 boost::make_iterator_range(dest_data_it,
1751 spacedim>::CELL_REFINE:
1752 unpack_callback(dealii_cell->parent(),
1754 boost::make_iterator_range(dest_data_it,
1760 spacedim>::CELL_INVALID:
1773 template <
int dim,
int spacedim>
1776 const typename ::internal::p4est::types<dim>::forest
1778 const std::string &filename)
const 1784 Assert(sizes_fixed_cumulative.size() > 0,
1793 const std::string fname_fixed = std::string(filename) +
"_fixed.data";
1796 int ierr = MPI_Info_create(&info);
1800 ierr = MPI_File_open(mpi_communicator,
1801 DEAL_II_MPI_CONST_CAST(fname_fixed.c_str()),
1802 MPI_MODE_CREATE | MPI_MODE_WRONLY,
1807 ierr = MPI_File_set_size(fh, 0);
1811 ierr = MPI_Barrier(mpi_communicator);
1813 ierr = MPI_Info_free(&info);
1825 const unsigned int *data = sizes_fixed_cumulative.data();
1827 ierr = MPI_File_write_at(fh,
1829 DEAL_II_MPI_CONST_CAST(data),
1830 sizes_fixed_cumulative.size(),
1837 const unsigned int offset_fixed =
1838 sizes_fixed_cumulative.size() *
sizeof(
unsigned int);
1840 const char *data = src_data_fixed.data();
1842 ierr = MPI_File_write_at(
1845 parallel_forest->global_first_quadrant[myrank] *
1846 sizes_fixed_cumulative.back(),
1847 DEAL_II_MPI_CONST_CAST(data),
1848 src_data_fixed.size(),
1853 ierr = MPI_File_close(&fh);
1860 if (variable_size_data_stored)
1862 const std::string fname_variable =
1863 std::string(filename) +
"_variable.data";
1868 int ierr = MPI_Info_create(&info);
1872 ierr = MPI_File_open(mpi_communicator,
1873 DEAL_II_MPI_CONST_CAST(fname_variable.c_str()),
1874 MPI_MODE_CREATE | MPI_MODE_WRONLY,
1879 ierr = MPI_File_set_size(fh, 0);
1883 ierr = MPI_Barrier(mpi_communicator);
1885 ierr = MPI_Info_free(&info);
1890 const int *data = src_sizes_variable.data();
1892 MPI_File_write_at(fh,
1893 parallel_forest->global_first_quadrant[myrank] *
1895 DEAL_II_MPI_CONST_CAST(data),
1896 src_sizes_variable.size(),
1903 const unsigned int offset_variable =
1904 parallel_forest->global_num_quadrants *
sizeof(int);
1907 const unsigned int size_on_proc = src_data_variable.size();
1910 std::vector<unsigned int> sizes_on_all_procs(n_procs);
1911 ierr = MPI_Allgather(DEAL_II_MPI_CONST_CAST(&size_on_proc),
1914 sizes_on_all_procs.data(),
1922 std::partial_sum(sizes_on_all_procs.begin(),
1923 sizes_on_all_procs.end(),
1924 sizes_on_all_procs.begin());
1926 const char *data = src_data_variable.data();
1929 ierr = MPI_File_write_at(
1934 sizes_on_all_procs[myrank - 1]),
1935 DEAL_II_MPI_CONST_CAST(data),
1936 src_data_variable.size(),
1941 ierr = MPI_File_close(&fh);
1948 template <
int dim,
int spacedim>
1951 const typename ::internal::p4est::types<dim>::forest
1953 const std::string &filename,
1954 const unsigned int n_attached_deserialize_fixed,
1955 const unsigned int n_attached_deserialize_variable)
1961 Assert(dest_data_fixed.size() == 0,
1962 ExcMessage(
"Previously loaded data has not been released yet!"));
1964 variable_size_data_stored = (n_attached_deserialize_variable > 0);
1972 const std::string fname_fixed = std::string(filename) +
"_fixed.data";
1975 int ierr = MPI_Info_create(&info);
1979 ierr = MPI_File_open(mpi_communicator,
1980 DEAL_II_MPI_CONST_CAST(fname_fixed.c_str()),
1986 ierr = MPI_Info_free(&info);
1996 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1997 (variable_size_data_stored ? 1 : 0));
1998 ierr = MPI_File_read_at(fh,
2000 sizes_fixed_cumulative.data(),
2001 sizes_fixed_cumulative.size(),
2007 dest_data_fixed.resize(parallel_forest->local_num_quadrants *
2008 sizes_fixed_cumulative.back());
2011 const unsigned int offset =
2012 sizes_fixed_cumulative.size() *
sizeof(
unsigned int);
2014 ierr = MPI_File_read_at(
2016 offset + parallel_forest->global_first_quadrant[myrank] *
2017 sizes_fixed_cumulative.back(),
2018 dest_data_fixed.data(),
2019 dest_data_fixed.size(),
2024 ierr = MPI_File_close(&fh);
2031 if (variable_size_data_stored)
2033 const std::string fname_variable =
2034 std::string(filename) +
"_variable.data";
2039 int ierr = MPI_Info_create(&info);
2043 ierr = MPI_File_open(mpi_communicator,
2044 DEAL_II_MPI_CONST_CAST(fname_variable.c_str()),
2050 ierr = MPI_Info_free(&info);
2054 dest_sizes_variable.resize(parallel_forest->local_num_quadrants);
2056 MPI_File_read_at(fh,
2057 parallel_forest->global_first_quadrant[myrank] *
2059 dest_sizes_variable.data(),
2060 dest_sizes_variable.size(),
2065 const unsigned int offset =
2066 parallel_forest->global_num_quadrants *
sizeof(int);
2068 const unsigned int size_on_proc =
2069 std::accumulate(dest_sizes_variable.begin(),
2070 dest_sizes_variable.end(),
2074 std::vector<unsigned int> sizes_on_all_procs(n_procs);
2075 ierr = MPI_Allgather(DEAL_II_MPI_CONST_CAST(&size_on_proc),
2078 sizes_on_all_procs.data(),
2085 std::partial_sum(sizes_on_all_procs.begin(),
2086 sizes_on_all_procs.end(),
2087 sizes_on_all_procs.begin());
2089 dest_data_variable.resize(size_on_proc);
2090 ierr = MPI_File_read_at(fh,
2091 offset + ((myrank == 0) ?
2093 sizes_on_all_procs[myrank - 1]),
2094 dest_data_variable.data(),
2095 dest_data_variable.size(),
2100 ierr = MPI_File_close(&fh);
2107 template <
int dim,
int spacedim>
2111 variable_size_data_stored =
false;
2114 sizes_fixed_cumulative.
clear();
2115 sizes_fixed_cumulative.shrink_to_fit();
2118 src_data_fixed.clear();
2119 src_data_fixed.shrink_to_fit();
2121 dest_data_fixed.clear();
2122 dest_data_fixed.shrink_to_fit();
2125 src_sizes_variable.clear();
2126 src_sizes_variable.shrink_to_fit();
2128 src_data_variable.clear();
2129 src_data_variable.shrink_to_fit();
2131 dest_sizes_variable.clear();
2132 dest_sizes_variable.shrink_to_fit();
2134 dest_data_variable.clear();
2135 dest_data_variable.shrink_to_fit();
2143 template <
int dim,
int spacedim>
2145 MPI_Comm mpi_communicator,
2146 const typename ::Triangulation<dim, spacedim>::MeshSmoothing
2154 (settings_ & construct_multigrid_hierarchy) ?
2158 Triangulation<dim, spacedim>::limit_level_difference_at_vertices) :
2161 , settings(settings_)
2162 , triangulation_has_content(false)
2163 , connectivity(nullptr)
2164 , parallel_forest(nullptr)
2165 , cell_attached_data({0, 0, {}, {}})
2166 , data_transfer(mpi_communicator)
2168 parallel_ghost =
nullptr;
2173 template <
int dim,
int spacedim>
2193 template <
int dim,
int spacedim>
2203 vertices, cells, subcelldata);
2206 const typename ::Triangulation<dim, spacedim>::DistortedCellList
2217 triangulation_has_content =
true;
2219 setup_coarse_cell_to_p4est_tree_permutation();
2221 copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
2225 copy_local_forest_to_triangulation();
2234 this->update_number_cache();
2235 this->update_periodic_face_map();
2241 namespace CommunicateLocallyMovedVertices
2250 template <
int dim,
int spacedim>
2255 std::vector<unsigned int> tree_index;
2258 std::vector<typename ::internal::p4est::types<dim>::quadrant>
2262 std::vector<unsigned int> vertex_indices;
2265 std::vector<::Point<spacedim>> vertices;
2269 std::vector<unsigned int *> first_vertex_indices;
2270 std::vector<::Point<spacedim> *> first_vertices;
2273 bytes_for_buffer()
const 2275 return sizeof(
unsigned int) +
2276 tree_index.size() *
sizeof(
unsigned int) +
2278 sizeof(typename ::internal::p4est ::types<
2280 vertex_indices.size() *
sizeof(
unsigned int) +
2285 pack_data(std::vector<char> &buffer)
const 2287 buffer.resize(bytes_for_buffer());
2289 char *ptr = buffer.data();
2291 const unsigned int num_cells = tree_index.size();
2292 std::memcpy(ptr, &num_cells,
sizeof(
unsigned int));
2293 ptr +=
sizeof(
unsigned int);
2297 num_cells *
sizeof(
unsigned int));
2298 ptr += num_cells *
sizeof(
unsigned int);
2304 sizeof(typename ::internal::p4est::types<dim>::quadrant));
2307 sizeof(typename ::internal::p4est::types<dim>::quadrant);
2310 vertex_indices.data(),
2311 vertex_indices.size() *
sizeof(
unsigned int));
2312 ptr += vertex_indices.size() *
sizeof(
unsigned int);
2322 unpack_data(
const std::vector<char> &buffer)
2324 const char * ptr = buffer.data();
2326 memcpy(&cells, ptr,
sizeof(
unsigned int));
2327 ptr +=
sizeof(
unsigned int);
2329 tree_index.resize(cells);
2330 memcpy(tree_index.data(), ptr,
sizeof(
unsigned int) * cells);
2331 ptr +=
sizeof(
unsigned int) * cells;
2333 quadrants.resize(cells);
2334 memcpy(quadrants.data(),
2337 typename ::internal::p4est::types<dim>::quadrant) *
2340 sizeof(typename ::internal::p4est::types<dim>::quadrant) *
2343 vertex_indices.clear();
2344 first_vertex_indices.resize(cells);
2345 std::vector<unsigned int> n_vertices_on_cell(cells);
2346 std::vector<unsigned int> first_indices(cells);
2347 for (
unsigned int c = 0; c < cells; ++c)
2352 const unsigned int *
const vertex_index =
2353 reinterpret_cast<const unsigned int *
>(ptr);
2354 first_indices[c] = vertex_indices.size();
2355 vertex_indices.push_back(*vertex_index);
2356 n_vertices_on_cell[c] = *vertex_index;
2357 ptr +=
sizeof(
unsigned int);
2359 vertex_indices.resize(vertex_indices.size() +
2360 n_vertices_on_cell[c]);
2361 memcpy(&vertex_indices[vertex_indices.size() -
2362 n_vertices_on_cell[c]],
2364 n_vertices_on_cell[c] *
sizeof(
unsigned int));
2365 ptr += n_vertices_on_cell[c] *
sizeof(
unsigned int);
2367 for (
unsigned int c = 0; c < cells; ++c)
2368 first_vertex_indices[c] = &vertex_indices[first_indices[c]];
2371 first_vertices.resize(cells);
2372 for (
unsigned int c = 0; c < cells; ++c)
2374 first_indices[c] = vertices.size();
2375 vertices.resize(vertices.size() + n_vertices_on_cell[c]);
2376 memcpy(&vertices[vertices.size() - n_vertices_on_cell[c]],
2381 for (
unsigned int c = 0; c < cells; ++c)
2382 first_vertices[c] = &vertices[first_indices[c]];
2402 template <
int dim,
int spacedim>
2404 fill_vertices_recursively(
2407 const unsigned int tree_index,
2410 const typename ::internal::p4est::types<dim>::quadrant
2412 const std::map<
unsigned int, std::set<::types::subdomain_id>>
2413 & vertices_with_ghost_neighbors,
2414 const std::vector<bool> &vertex_locally_moved,
2420 if (dealii_cell->has_children())
2422 typename ::internal::p4est::types<dim>::quadrant
2424 ::internal::p4est::init_quadrant_children<dim>(p4est_cell,
2428 for (
unsigned int c = 0;
2429 c < GeometryInfo<dim>::max_children_per_cell;
2431 fill_vertices_recursively<dim, spacedim>(
2434 dealii_cell->child(c),
2436 vertices_with_ghost_neighbors,
2437 vertex_locally_moved,
2449 if (dealii_cell->is_locally_owned())
2451 std::set<::types::subdomain_id> send_to;
2452 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
2455 const std::map<
unsigned int,
2456 std::set<::types::subdomain_id>>::
2457 const_iterator neighbor_subdomains_of_vertex =
2458 vertices_with_ghost_neighbors.find(
2459 dealii_cell->vertex_index(v));
2461 if (neighbor_subdomains_of_vertex !=
2462 vertices_with_ghost_neighbors.end())
2464 Assert(neighbor_subdomains_of_vertex->second.size() != 0,
2467 neighbor_subdomains_of_vertex->second.begin(),
2468 neighbor_subdomains_of_vertex->second.end());
2472 if (send_to.size() > 0)
2474 std::vector<unsigned int> vertex_indices;
2475 std::vector<::Point<spacedim>> local_vertices;
2476 for (
unsigned int v = 0;
2477 v < GeometryInfo<dim>::vertices_per_cell;
2479 if (vertex_locally_moved[dealii_cell->vertex_index(v)])
2481 vertex_indices.push_back(v);
2482 local_vertices.push_back(dealii_cell->vertex(v));
2485 if (vertex_indices.size() > 0)
2486 for (
const auto subdomain : send_to)
2491 const typename std::map<
2493 CellInfo<dim, spacedim>>::iterator p =
2495 .insert(std::make_pair(subdomain,
2496 CellInfo<dim, spacedim>()))
2499 p->second.tree_index.push_back(tree_index);
2500 p->second.quadrants.push_back(p4est_cell);
2502 p->second.vertex_indices.push_back(
2503 vertex_indices.size());
2504 p->second.vertex_indices.insert(
2505 p->second.vertex_indices.end(),
2506 vertex_indices.begin(),
2507 vertex_indices.end());
2509 p->second.vertices.insert(p->second.vertices.end(),
2510 local_vertices.begin(),
2511 local_vertices.end());
2528 template <
int dim,
int spacedim>
2530 set_vertices_recursively(
2532 const typename ::internal::p4est::types<dim>::quadrant
2536 const typename ::internal::p4est::types<dim>::quadrant
2538 const ::Point<spacedim> *
const vertices,
2539 const unsigned int *
const vertex_indices)
2541 if (::internal::p4est::quadrant_is_equal<dim>(p4est_cell,
2548 const unsigned int n_vertices = vertex_indices[0];
2551 for (
unsigned int i = 0; i < n_vertices; ++i)
2552 dealii_cell->vertex(vertex_indices[i + 1]) = vertices[i];
2557 if (!dealii_cell->has_children())
2560 if (!::internal::p4est::quadrant_is_ancestor<dim>(p4est_cell,
2564 typename ::internal::p4est::types<dim>::quadrant
2566 ::internal::p4est::init_quadrant_children<dim>(p4est_cell,
2569 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
2571 set_vertices_recursively<dim, spacedim>(tria,
2573 dealii_cell->child(c),
2583 template <
int dim,
int spacedim>
2587 triangulation_has_content =
false;
2589 cell_attached_data = {0, 0, {}, {}};
2590 data_transfer.clear();
2592 if (parallel_ghost !=
nullptr)
2596 parallel_ghost =
nullptr;
2599 if (parallel_forest !=
nullptr)
2602 parallel_forest =
nullptr;
2605 if (connectivity !=
nullptr)
2609 connectivity =
nullptr;
2612 coarse_cell_to_p4est_tree_permutation.resize(0);
2613 p4est_tree_to_coarse_cell_permutation.resize(0);
2617 this->update_number_cache();
2622 template <
int dim,
int spacedim>
2626 if (this->n_global_levels() <= 1)
2635 bool have_coarser_cell =
false;
2637 this->begin_active(this->n_global_levels() - 2);
2638 cell != this->end(this->n_global_levels() - 2);
2640 if (cell->is_locally_owned())
2642 have_coarser_cell =
true;
2648 this->mpi_communicator);
2653 template <
int dim,
int spacedim>
2658 ::GridTools::get_vertex_connectivity_of_cells(*
this,
2660 coarse_cell_to_p4est_tree_permutation.resize(this->n_cells(0));
2662 cell_connectivity, coarse_cell_to_p4est_tree_permutation);
2664 p4est_tree_to_coarse_cell_permutation =
2670 template <
int dim,
int spacedim>
2673 const std::string &file_basename)
const 2675 Assert(parallel_forest !=
nullptr,
2676 ExcMessage(
"Can't produce output when no forest is created yet."));
2678 parallel_forest,
nullptr, file_basename.c_str());
2683 template <
int dim,
int spacedim>
2688 cell_attached_data.n_attached_deserialize == 0,
2690 "not all SolutionTransfer's got deserialized after the last load()"));
2691 Assert(this->n_cells() > 0,
2692 ExcMessage(
"Can not save() an empty Triangulation."));
2695 this->signals.pre_distributed_save();
2697 if (this->my_subdomain == 0)
2699 std::string fname = std::string(filename) +
".info";
2700 std::ofstream f(fname.c_str());
2701 f <<
"version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_coarse_cells" 2705 << cell_attached_data.pack_callbacks_fixed.size() <<
" " 2706 << cell_attached_data.pack_callbacks_variable.size() <<
" " 2707 << this->n_cells(0) << std::endl;
2711 for (
const auto &quad_cell_rel : local_quadrant_cell_relations)
2713 (void)quad_cell_rel;
2715 (std::get<1>(quad_cell_rel) ==
2720 if (cell_attached_data.n_attached_data_sets > 0)
2723 auto tria =
const_cast< 2728 tria->data_transfer.pack_data(
2729 local_quadrant_cell_relations,
2730 cell_attached_data.pack_callbacks_fixed,
2731 cell_attached_data.pack_callbacks_variable);
2734 tria->data_transfer.save(parallel_forest, filename);
2737 tria->data_transfer.clear();
2752 tria->cell_attached_data.n_attached_data_sets = 0;
2753 tria->cell_attached_data.pack_callbacks_fixed.clear();
2754 tria->cell_attached_data.pack_callbacks_variable.clear();
2758 this->signals.post_distributed_save();
2763 template <
int dim,
int spacedim>
2766 const bool autopartition)
2769 this->n_cells() > 0,
2771 "load() only works if the Triangulation already contains a coarse mesh!"));
2773 this->n_levels() == 1,
2775 "Triangulation may only contain coarse cells when calling load()."));
2778 this->signals.pre_distributed_load();
2780 if (parallel_ghost !=
nullptr)
2784 parallel_ghost =
nullptr;
2787 parallel_forest =
nullptr;
2790 connectivity =
nullptr;
2792 unsigned int version, numcpus, attached_count_fixed,
2793 attached_count_variable, n_coarse_cells;
2795 std::string fname = std::string(filename) +
".info";
2796 std::ifstream f(fname.c_str());
2798 std::string firstline;
2799 getline(f, firstline);
2800 f >> version >> numcpus >> attached_count_fixed >>
2801 attached_count_variable >> n_coarse_cells;
2805 ExcMessage(
"Incompatible version found in .info file."));
2806 Assert(this->n_cells(0) == n_coarse_cells,
2807 ExcMessage(
"Number of coarse cells differ!"));
2811 cell_attached_data.n_attached_data_sets = 0;
2812 cell_attached_data.n_attached_deserialize =
2813 attached_count_fixed + attached_count_variable;
2817 this->mpi_communicator,
2835 copy_local_forest_to_triangulation();
2847 if (cell_attached_data.n_attached_deserialize > 0)
2849 data_transfer.load(parallel_forest,
2851 attached_count_fixed,
2852 attached_count_variable);
2854 data_transfer.unpack_cell_status(local_quadrant_cell_relations);
2857 for (
const auto &quad_cell_rel : local_quadrant_cell_relations)
2859 (void)quad_cell_rel;
2861 (std::get<1>(quad_cell_rel) ==
2863 spacedim>::CELL_PERSIST),
2868 this->update_number_cache();
2871 this->signals.post_distributed_load();
2873 this->update_periodic_face_map();
2878 template <
int dim,
int spacedim>
2882 Assert(parallel_forest !=
nullptr,
2884 "Can't produce a check sum when no forest is created yet."));
2885 return ::internal::p4est::functions<dim>::checksum(parallel_forest);
2890 template <
int dim,
int spacedim>
2891 const typename ::internal::p4est::types<dim>::forest *
2894 Assert(parallel_forest !=
nullptr,
2895 ExcMessage(
"The forest has not been allocated yet."));
2896 return parallel_forest;
2901 template <
int dim,
int spacedim>
2907 if (settings & construct_multigrid_hierarchy)
2913 template <
int dim,
int spacedim>
2914 typename ::internal::p4est::types<dim>::tree *
2916 const int dealii_coarse_cell_index)
const 2918 const unsigned int tree_index =
2919 coarse_cell_to_p4est_tree_permutation[dealii_coarse_cell_index];
2920 typename ::internal::p4est::types<dim>::tree *tree =
2921 static_cast<typename ::internal::p4est::types<dim>::tree *
>(
2922 sc_array_index(parallel_forest->trees, tree_index));
2932 std::integral_constant<int, 2>)
2934 const unsigned int dim = 2, spacedim = 2;
2942 std::vector<unsigned int> vertex_touch_count;
2944 std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2947 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
2948 const ::internal::p4est::types<2>::locidx num_vtt =
2949 std::accumulate(vertex_touch_count.begin(),
2950 vertex_touch_count.end(),
2956 const bool set_vertex_info
2965 (set_vertex_info ==
true ? this->n_vertices() : 0),
2970 set_vertex_and_cell_info(*
this,
2973 coarse_cell_to_p4est_tree_permutation,
2977 Assert(p4est_connectivity_is_valid(connectivity) == 1,
2982 this->mpi_communicator,
2999 std::integral_constant<int, 2>)
3001 const unsigned int dim = 2, spacedim = 3;
3009 std::vector<unsigned int> vertex_touch_count;
3011 std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
3014 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
3015 const ::internal::p4est::types<2>::locidx num_vtt =
3016 std::accumulate(vertex_touch_count.begin(),
3017 vertex_touch_count.end(),
3023 const bool set_vertex_info
3032 (set_vertex_info ==
true ? this->n_vertices() : 0),
3037 set_vertex_and_cell_info(*
this,
3040 coarse_cell_to_p4est_tree_permutation,
3044 Assert(p4est_connectivity_is_valid(connectivity) == 1,
3049 this->mpi_communicator,
3064 std::integral_constant<int, 3>)
3066 const int dim = 3, spacedim = 3;
3074 std::vector<unsigned int> vertex_touch_count;
3075 std::vector<std::list<
3076 std::pair<Triangulation<3>::active_cell_iterator,
unsigned int>>>
3078 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
3079 const ::internal::p4est::types<2>::locidx num_vtt =
3080 std::accumulate(vertex_touch_count.begin(),
3081 vertex_touch_count.end(),
3084 std::vector<unsigned int> edge_touch_count;
3085 std::vector<std::list<
3086 std::pair<Triangulation<3>::active_cell_iterator,
unsigned int>>>
3088 get_edge_to_cell_mappings(*
this, edge_touch_count, edge_to_cell);
3089 const ::internal::p4est::types<2>::locidx num_ett =
3090 std::accumulate(edge_touch_count.begin(), edge_touch_count.end(), 0u);
3093 const bool set_vertex_info
3102 (set_vertex_info ==
true ? this->n_vertices() : 0),
3104 this->n_active_lines(),
3109 set_vertex_and_cell_info(*
this,
3112 coarse_cell_to_p4est_tree_permutation,
3141 const unsigned int deal_to_p4est_line_index[12] = {
3142 4, 5, 0, 1, 6, 7, 2, 3, 8, 9, 10, 11};
3145 this->begin_active();
3146 cell != this->end();
3149 const unsigned int index =
3150 coarse_cell_to_p4est_tree_permutation[cell->index()];
3151 for (
unsigned int e = 0; e < GeometryInfo<3>::lines_per_cell; ++
e)
3153 deal_to_p4est_line_index[e]] =
3154 cell->line(e)->index();
3159 connectivity->ett_offset[0] = 0;
3160 std::partial_sum(edge_touch_count.begin(),
3161 edge_touch_count.end(),
3162 &connectivity->ett_offset[1]);
3164 Assert(connectivity->ett_offset[this->n_active_lines()] == num_ett,
3167 for (
unsigned int v = 0; v < this->n_active_lines(); ++v)
3169 Assert(edge_to_cell[v].size() == edge_touch_count[v],
3173 std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
3174 unsigned int>>::const_iterator p =
3175 edge_to_cell[v].begin();
3176 for (
unsigned int c = 0; c < edge_touch_count[v]; ++c, ++p)
3178 connectivity->edge_to_tree[connectivity->ett_offset[v] + c] =
3179 coarse_cell_to_p4est_tree_permutation[p->first->index()];
3180 connectivity->edge_to_edge[connectivity->ett_offset[v] + c] =
3181 deal_to_p4est_line_index[p->second];
3185 Assert(p8est_connectivity_is_valid(connectivity) == 1,
3190 this->mpi_communicator,
3206 template <
int dim,
int spacedim>
3208 enforce_mesh_balance_over_periodic_boundaries(
3214 std::vector<bool> flags_before[2];
3218 std::vector<unsigned int> topological_vertex_numbering(
3220 for (
unsigned int i = 0; i < topological_vertex_numbering.size(); ++i)
3221 topological_vertex_numbering[i] = i;
3237 using cell_iterator =
3239 typename std::map<std::pair<cell_iterator, unsigned int>,
3240 std::pair<std::pair<cell_iterator, unsigned int>,
3241 std::bitset<3>>>::const_iterator it;
3246 const cell_iterator &cell_1 = it->first.first;
3247 const unsigned int face_no_1 = it->first.second;
3248 const cell_iterator &cell_2 = it->second.first.first;
3249 const unsigned int face_no_2 = it->second.first.second;
3250 const std::bitset<3> face_orientation = it->second.second;
3252 if (cell_1->level() == cell_2->level())
3254 for (
unsigned int v = 0;
3260 const unsigned int vface0 =
3263 face_orientation[0],
3264 face_orientation[1],
3265 face_orientation[2]);
3266 const unsigned int vi0 =
3267 topological_vertex_numbering[cell_1->face(face_no_1)
3268 ->vertex_index(vface0)];
3269 const unsigned int vi1 =
3270 topological_vertex_numbering[cell_2->face(face_no_2)
3272 const unsigned int min_index = std::min(vi0, vi1);
3273 topological_vertex_numbering[cell_1->face(face_no_1)
3274 ->vertex_index(vface0)] =
3275 topological_vertex_numbering[cell_2->face(face_no_2)
3276 ->vertex_index(v)] =
3283 for (
unsigned int i = 0; i < topological_vertex_numbering.size(); ++i)
3285 const unsigned int j = topological_vertex_numbering[i];
3293 bool continue_iterating =
true;
3294 std::vector<int> vertex_level(tria.
n_vertices());
3295 while (continue_iterating)
3299 std::fill(vertex_level.begin(), vertex_level.end(), 0);
3303 for (; cell != endc; ++cell)
3305 if (cell->refine_flag_set())
3306 for (
unsigned int vertex = 0;
3307 vertex < GeometryInfo<dim>::vertices_per_cell;
3309 vertex_level[topological_vertex_numbering
3310 [cell->vertex_index(vertex)]] =
3311 std::max(vertex_level[topological_vertex_numbering
3312 [cell->vertex_index(vertex)]],
3314 else if (!cell->coarsen_flag_set())
3315 for (
unsigned int vertex = 0;
3316 vertex < GeometryInfo<dim>::vertices_per_cell;
3318 vertex_level[topological_vertex_numbering
3319 [cell->vertex_index(vertex)]] =
3320 std::max(vertex_level[topological_vertex_numbering
3321 [cell->vertex_index(vertex)]],
3332 for (
unsigned int vertex = 0;
3333 vertex < GeometryInfo<dim>::vertices_per_cell;
3335 vertex_level[topological_vertex_numbering
3336 [cell->vertex_index(vertex)]] =
3337 std::max(vertex_level[topological_vertex_numbering
3338 [cell->vertex_index(vertex)]],
3343 continue_iterating =
false;
3354 for (cell = tria.
last_active(); cell != endc; --cell)
3355 if (cell->refine_flag_set() ==
false)
3357 for (
unsigned int vertex = 0;
3358 vertex < GeometryInfo<dim>::vertices_per_cell;
3360 if (vertex_level[topological_vertex_numbering
3361 [cell->vertex_index(vertex)]] >=
3365 cell->clear_coarsen_flag();
3370 if (vertex_level[topological_vertex_numbering
3371 [cell->vertex_index(vertex)]] >
3374 cell->set_refine_flag();
3375 continue_iterating =
true;
3377 for (
unsigned int v = 0;
3378 v < GeometryInfo<dim>::vertices_per_cell;
3380 vertex_level[topological_vertex_numbering
3381 [cell->vertex_index(v)]] =
3383 vertex_level[topological_vertex_numbering
3384 [cell->vertex_index(v)]],
3404 const unsigned int n_children = cell->n_children();
3405 unsigned int flagged_children = 0;
3406 for (
unsigned int child = 0; child < n_children; ++child)
3407 if (cell->child(child)->active() &&
3408 cell->child(child)->coarsen_flag_set())
3413 if (flagged_children < n_children)
3414 for (
unsigned int child = 0; child < n_children; ++child)
3415 if (cell->child(child)->active())
3416 cell->child(child)->clear_coarsen_flag();
3419 std::vector<bool> flags_after[2];
3422 return ((flags_before[0] != flags_after[0]) ||
3423 (flags_before[1] != flags_after[1]));
3429 template <
int dim,
int spacedim>
3433 std::vector<bool> flags_before[2];
3434 this->save_coarsen_flags(flags_before[0]);
3435 this->save_refine_flags(flags_before[1]);
3437 bool mesh_changed =
false;
3442 this->update_periodic_face_map();
3444 mesh_changed = enforce_mesh_balance_over_periodic_boundaries(*
this);
3446 while (mesh_changed);
3450 std::vector<bool> flags_after[2];
3451 this->save_coarsen_flags(flags_after[0]);
3452 this->save_refine_flags(flags_after[1]);
3453 return ((flags_before[0] != flags_after[0]) ||
3454 (flags_before[1] != flags_after[1]));
3459 template <
int dim,
int spacedim>
3480 if (settings & construct_multigrid_hierarchy)
3483 spacedim>::limit_level_difference_at_vertices;
3487 bool mesh_changed =
false;
3495 if (settings & mesh_reconstruction_after_repartitioning)
3496 while (this->begin_active()->level() > 0)
3499 cell = this->begin_active();
3500 cell != this->end();
3503 cell->set_coarsen_flag();
3506 this->prepare_coarsening_and_refinement();
3523 if (parallel_ghost !=
nullptr)
3527 parallel_ghost =
nullptr;
3531 (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
3532 P4EST_CONNECT_CORNER) :
3533 typename ::internal::p4est::types<dim>::balance_type(
3534 P8EST_CONNECT_CORNER)));
3543 cell != this->end(0);
3551 cell != this->end(0);
3557 if (tree_exists_locally<dim, spacedim>(
3559 coarse_cell_to_p4est_tree_permutation[cell->index()]) ==
3562 delete_all_children<dim, spacedim>(cell);
3563 if (!cell->has_children())
3572 typename ::internal::p4est::types<dim>::quadrant
3574 typename ::internal::p4est::types<dim>::tree *tree =
3575 init_tree(cell->index());
3577 ::internal::p4est::init_coarse_quadrant<dim>(
3580 match_tree_recursively<dim, spacedim>(*tree,
3584 this->my_subdomain);
3591 typename ::internal::p4est::types<dim>::quadrant *quadr;
3593 typename ::internal::p4est::types<dim>::topidx ghost_tree = 0;
3595 for (
unsigned int g_idx = 0;
3596 g_idx < parallel_ghost->ghosts.elem_count;
3599 while (g_idx >= static_cast<unsigned int>(
3600 parallel_ghost->proc_offsets[ghost_owner + 1]))
3602 while (g_idx >= static_cast<unsigned int>(
3603 parallel_ghost->tree_offsets[ghost_tree + 1]))
3606 quadr =
static_cast< 3607 typename ::internal::p4est::types<dim>::quadrant *
>(
3608 sc_array_index(¶llel_ghost->ghosts, g_idx));
3610 unsigned int coarse_cell_index =
3611 p4est_tree_to_coarse_cell_permutation[ghost_tree];
3613 match_quadrant<dim, spacedim>(
this,
3620 this->prepare_coarsening_and_refinement();
3623 mesh_changed =
false;
3625 cell = this->begin_active();
3626 cell != this->end();
3628 if (cell->refine_flag_set() || cell->coarsen_flag_set())
3630 mesh_changed =
true;
3649 while (mesh_changed);
3653 unsigned int num_ghosts = 0;
3656 this->begin_active();
3657 cell != this->end();
3660 if (cell->subdomain_id() != this->my_subdomain &&
3665 Assert(num_ghosts == parallel_ghost->ghosts.elem_count,
3675 if (settings & construct_multigrid_hierarchy)
3681 for (
unsigned int lvl = this->n_levels(); lvl > 0;)
3685 endc = this->end(lvl);
3686 for (cell = this->begin(lvl); cell != endc; ++cell)
3688 if ((!cell->has_children() &&
3689 cell->subdomain_id() ==
3690 this->locally_owned_subdomain()) ||
3691 (cell->has_children() &&
3692 cell->child(0)->level_subdomain_id() ==
3693 this->locally_owned_subdomain()))
3694 cell->set_level_subdomain_id(
3695 this->locally_owned_subdomain());
3699 cell->set_level_subdomain_id(
3707 std::vector<std::vector<bool>> marked_vertices(this->n_levels());
3708 for (
unsigned int lvl = 0; lvl < this->n_levels(); ++lvl)
3709 marked_vertices[lvl] = mark_locally_active_vertices_on_level(lvl);
3713 cell != this->end(0);
3716 typename ::internal::p4est::types<dim>::quadrant
3718 const unsigned int tree_index =
3719 coarse_cell_to_p4est_tree_permutation[cell->index()];
3720 typename ::internal::p4est::types<dim>::tree *tree =
3721 init_tree(cell->index());
3723 ::internal::p4est::init_coarse_quadrant<dim>(
3726 determine_level_subdomain_id_recursively<dim, spacedim>(
3737 for (
unsigned int lvl = this->n_levels(); lvl > 0;)
3741 endc = this->end(lvl);
3742 for (cell = this->begin(lvl); cell != endc; ++cell)
3744 if (cell->has_children())
3745 for (
unsigned int c = 0;
3746 c < GeometryInfo<dim>::max_children_per_cell;
3749 if (cell->child(c)->level_subdomain_id() ==
3750 this->locally_owned_subdomain())
3755 cell->child(0)->level_subdomain_id();
3759 cell->set_level_subdomain_id(mark);
3775 const unsigned int total_local_cells = this->n_active_cells();
3776 (void)total_local_cells;
3780 Assert(static_cast<unsigned int>(
3781 parallel_forest->local_num_quadrants) == total_local_cells,
3786 Assert(static_cast<unsigned int>(
3787 parallel_forest->local_num_quadrants) <= total_local_cells,
3792 unsigned int n_owned = 0;
3794 this->begin_active();
3795 cell != this->end();
3798 if (cell->subdomain_id() == this->my_subdomain)
3802 Assert(static_cast<unsigned int>(
3803 parallel_forest->local_num_quadrants) == n_owned,
3807 this->smooth_grid = save_smooth;
3813 update_quadrant_cell_relations();
3818 template <
int dim,
int spacedim>
3825 this->begin_active();
3826 cell != this->end();
3828 if (cell->is_locally_owned() && cell->refine_flag_set())
3829 Assert(cell->refine_flag_set() ==
3832 "This class does not support anisotropic refinement"));
3837 if (this->n_levels() ==
3841 cell = this->begin_active(
3849 !(cell->refine_flag_set()),
3851 "Fatal Error: maximum refinement level of p4est reached."));
3855 this->prepare_coarsening_and_refinement();
3858 this->signals.pre_distributed_refinement();
3864 this->begin_active();
3865 cell != this->end();
3867 if (cell->is_ghost() || cell->is_artificial())
3869 cell->clear_refine_flag();
3870 cell->clear_coarsen_flag();
3876 RefineAndCoarsenList<dim, spacedim> refine_and_coarsen_list(
3877 *
this, p4est_tree_to_coarse_cell_permutation, this->my_subdomain);
3884 parallel_forest->user_pointer = &refine_and_coarsen_list;
3886 if (parallel_ghost !=
nullptr)
3890 parallel_ghost =
nullptr;
3895 &RefineAndCoarsenList<dim, spacedim>::refine_callback,
3900 &RefineAndCoarsenList<dim, spacedim>::coarsen_callback,
3907 parallel_forest->user_pointer =
this;
3913 (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
3914 P4EST_CONNECT_FULL) :
3915 typename ::internal::p4est::types<dim>::balance_type(
3916 P8EST_CONNECT_FULL)),
3921 update_quadrant_cell_relations();
3926 std::vector<typename ::internal::p4est::types<dim>::gloidx>
3927 previous_global_first_quadrant;
3930 if (cell_attached_data.n_attached_data_sets > 0)
3932 data_transfer.pack_data(local_quadrant_cell_relations,
3933 cell_attached_data.pack_callbacks_fixed,
3934 cell_attached_data.pack_callbacks_variable);
3938 previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
3939 std::memcpy(previous_global_first_quadrant.data(),
3940 parallel_forest->global_first_quadrant,
3942 typename ::internal::p4est::types<dim>::gloidx) *
3943 (parallel_forest->mpisize + 1));
3946 if (!(settings & no_automatic_repartitioning))
3950 if (this->signals.cell_weight.num_slots() == 0)
3958 const std::vector<unsigned int> cell_weights = get_cell_weights();
3960 PartitionWeights<dim, spacedim> partition_weights(cell_weights);
3965 parallel_forest->user_pointer = &partition_weights;
3971 &PartitionWeights<dim, spacedim>::cell_weight);
3975 parallel_forest, 0,
nullptr,
nullptr);
3977 parallel_forest->user_pointer =
this;
3985 this->begin_active();
3986 cell != this->end();
3989 cell->clear_refine_flag();
3990 cell->clear_coarsen_flag();
3995 copy_local_forest_to_triangulation();
4006 if (cell_attached_data.n_attached_data_sets > 0)
4009 data_transfer.execute_transfer(parallel_forest,
4010 previous_global_first_quadrant.data());
4013 data_transfer.unpack_cell_status(local_quadrant_cell_relations);
4032 if (settings & construct_multigrid_hierarchy)
4034 for (
unsigned int lvl = 0; lvl < this->n_global_levels(); ++lvl)
4036 std::vector<bool> active_verts =
4037 this->mark_locally_active_vertices_on_level(lvl);
4039 const unsigned int maybe_coarser_lvl =
4040 (lvl > 0) ? (lvl - 1) : lvl;
4042 cell = this->begin(maybe_coarser_lvl),
4043 endc = this->end(lvl);
4044 for (; cell != endc; ++cell)
4045 if (cell->level() ==
static_cast<int>(lvl) || cell->active())
4047 const bool is_level_artificial =
4048 (cell->level_subdomain_id() ==
4050 bool need_to_know =
false;
4051 for (
unsigned int vertex = 0;
4052 vertex < GeometryInfo<dim>::vertices_per_cell;
4054 if (active_verts[cell->vertex_index(vertex)])
4056 need_to_know =
true;
4061 !need_to_know || !is_level_artificial,
4063 "Internal error: the owner of cell" +
4064 cell->id().to_string() +
4065 " is unknown even though it is needed for geometric multigrid."));
4071 this->update_number_cache();
4073 this->update_periodic_face_map();
4076 this->signals.post_distributed_refinement();
4081 template <
int dim,
int spacedim>
4087 this->begin_active();
4088 cell != this->end();
4090 if (cell->is_locally_owned())
4092 !cell->refine_flag_set() && !cell->coarsen_flag_set(),
4094 "Error: There shouldn't be any cells flagged for coarsening/refinement when calling repartition()."));
4098 this->signals.pre_distributed_repartition();
4102 std::vector<typename ::internal::p4est::types<dim>::gloidx>
4103 previous_global_first_quadrant;
4106 if (cell_attached_data.n_attached_data_sets > 0)
4108 data_transfer.pack_data(local_quadrant_cell_relations,
4109 cell_attached_data.pack_callbacks_fixed,
4110 cell_attached_data.pack_callbacks_variable);
4114 previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
4115 std::memcpy(previous_global_first_quadrant.data(),
4116 parallel_forest->global_first_quadrant,
4118 typename ::internal::p4est::types<dim>::gloidx) *
4119 (parallel_forest->mpisize + 1));
4122 if (this->signals.cell_weight.num_slots() == 0)
4134 const std::vector<unsigned int> cell_weights = get_cell_weights();
4136 PartitionWeights<dim, spacedim> partition_weights(cell_weights);
4141 parallel_forest->user_pointer = &partition_weights;
4147 &PartitionWeights<dim, spacedim>::cell_weight);
4150 parallel_forest->user_pointer =
this;
4155 copy_local_forest_to_triangulation();
4166 if (cell_attached_data.n_attached_data_sets > 0)
4169 data_transfer.execute_transfer(parallel_forest,
4170 previous_global_first_quadrant.data());
4174 this->update_number_cache();
4176 this->update_periodic_face_map();
4179 this->signals.post_distributed_repartition();
4184 template <
int dim,
int spacedim>
4187 const std::vector<bool> &vertex_locally_moved)
4189 Assert(vertex_locally_moved.size() == this->n_vertices(),
4191 this->n_vertices()));
4194 const std::vector<bool> locally_owned_vertices =
4195 ::GridTools::get_locally_owned_vertices(*
this);
4196 for (
unsigned int i = 0; i < locally_owned_vertices.size(); ++i)
4197 Assert((vertex_locally_moved[i] ==
false) ||
4198 (locally_owned_vertices[i] ==
true),
4199 ExcMessage(
"The vertex_locally_moved argument must not " 4200 "contain vertices that are not locally owned"));
4210 const std::map<unsigned int, std::set<::types::subdomain_id>>
4211 vertices_with_ghost_neighbors = compute_vertices_with_ghost_neighbors();
4217 CommunicateLocallyMovedVertices::CellInfo<dim, spacedim>>;
4218 cellmap_t needs_to_get_cells;
4222 cell != this->end(0);
4225 typename ::internal::p4est::types<dim>::quadrant
4227 ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
4229 CommunicateLocallyMovedVertices::fill_vertices_recursively<dim,
4232 this->get_coarse_cell_to_p4est_tree_permutation()[cell->index()],
4235 vertices_with_ghost_neighbors,
4236 vertex_locally_moved,
4237 needs_to_get_cells);
4241 std::vector<std::vector<char>> sendbuffers(needs_to_get_cells.size());
4242 std::vector<std::vector<char>>::iterator buffer = sendbuffers.begin();
4243 std::vector<MPI_Request> requests(needs_to_get_cells.size());
4244 std::vector<unsigned int> destinations;
4246 unsigned int idx = 0;
4248 for (
typename cellmap_t::iterator it = needs_to_get_cells.begin();
4249 it != needs_to_get_cells.end();
4250 ++it, ++buffer, ++idx)
4252 const unsigned int num_cells = it->second.tree_index.size();
4254 destinations.push_back(it->first);
4266 it->second.pack_data(*buffer);
4267 const int ierr = MPI_Isend(buffer->data(),
4272 this->get_communicator(),
4277 Assert(destinations.size() == needs_to_get_cells.size(),
4282 const unsigned int n_senders =
4284 this->get_communicator(), destinations);
4287 std::vector<char> receive;
4288 CommunicateLocallyMovedVertices::CellInfo<dim, spacedim> cellinfo;
4289 for (
unsigned int i = 0; i < n_senders; ++i)
4294 MPI_Probe(MPI_ANY_SOURCE, 123, this->get_communicator(), &status);
4296 ierr = MPI_Get_count(&status, MPI_BYTE, &len);
4298 receive.resize(len);
4300 char *ptr = receive.data();
4301 ierr = MPI_Recv(ptr,
4306 this->get_communicator(),
4310 cellinfo.unpack_data(receive);
4311 const unsigned int cells = cellinfo.tree_index.size();
4312 for (
unsigned int c = 0; c < cells; ++c)
4314 typename ::parallel::distributed::
4315 Triangulation<dim, spacedim>::cell_iterator cell(
4318 this->get_p4est_tree_to_coarse_cell_permutation()
4319 [cellinfo.tree_index[c]]);
4321 typename ::internal::p4est::types<dim>::quadrant
4323 ::internal::p4est::init_coarse_quadrant<dim>(
4326 CommunicateLocallyMovedVertices::set_vertices_recursively<
4331 cellinfo.quadrants[c],
4332 cellinfo.first_vertices[c],
4333 cellinfo.first_vertex_indices[c]);
4339 if (requests.size() > 0)
4342 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
4348 this->get_communicator()) ==
4355 template <
int dim,
int spacedim>
4358 const std::function<std::vector<char>(
const cell_iterator &,
4360 const bool returns_variable_size_data)
4366 if (returns_variable_size_data)
4368 handle = 2 * cell_attached_data.pack_callbacks_variable.size();
4369 cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
4373 handle = 2 * cell_attached_data.pack_callbacks_fixed.size() + 1;
4374 cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
4378 ++cell_attached_data.n_attached_data_sets;
4385 template <
int dim,
int spacedim>
4388 const unsigned int handle,
4389 const std::function<
4392 const boost::iterator_range<std::vector<char>::const_iterator> &)>
4395 Assert(cell_attached_data.n_attached_data_sets > 0,
4396 ExcMessage(
"The notify_ready_to_unpack() has already been called " 4397 "once for each registered callback."));
4401 Assert(local_quadrant_cell_relations.size() ==
4402 static_cast<unsigned int>(parallel_forest->local_num_quadrants),
4409 const unsigned int callback_index = handle / 2;
4410 if (handle % 2 == 0)
4413 cell_attached_data.pack_callbacks_variable.size(),
4416 Assert(cell_attached_data.pack_callbacks_variable[callback_index] !=
4419 cell_attached_data.pack_callbacks_variable[callback_index] =
nullptr;
4424 cell_attached_data.pack_callbacks_fixed.size(),
4427 Assert(cell_attached_data.pack_callbacks_fixed[callback_index] !=
4430 cell_attached_data.pack_callbacks_fixed[callback_index] =
nullptr;
4435 data_transfer.unpack_data(local_quadrant_cell_relations,
4440 --cell_attached_data.n_attached_data_sets;
4441 if (cell_attached_data.n_attached_deserialize > 0)
4442 --cell_attached_data.n_attached_deserialize;
4450 if (cell_attached_data.n_attached_data_sets == 0 &&
4451 cell_attached_data.n_attached_deserialize == 0)
4454 cell_attached_data.pack_callbacks_fixed.clear();
4455 cell_attached_data.pack_callbacks_variable.clear();
4456 data_transfer.clear();
4459 for (
auto &quad_cell_rel : local_quadrant_cell_relations)
4460 std::get<1>(quad_cell_rel) =
4467 template <
int dim,
int spacedim>
4468 const std::vector<types::global_dof_index> &
4472 return p4est_tree_to_coarse_cell_permutation;
4477 template <
int dim,
int spacedim>
4478 const std::vector<types::global_dof_index> &
4482 return coarse_cell_to_p4est_tree_permutation;
4487 template <
int dim,
int spacedim>
4488 std::map<unsigned int, std::set<::types::subdomain_id>>
4493 return ::internal::p4est::compute_vertices_with_ghost_neighbors<
4495 spacedim>(*
this, this->parallel_forest, this->parallel_ghost);
4500 template <
int dim,
int spacedim>
4503 const int level)
const 4507 std::vector<bool> marked_vertices(this->n_vertices(),
false);
4508 cell_iterator cell = this->begin(level), endc = this->end(level);
4509 for (; cell != endc; ++cell)
4510 if (cell->level_subdomain_id() == this->locally_owned_subdomain())
4511 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
4513 marked_vertices[cell->vertex_index(v)] =
true;
4520 typename std::map<std::pair<cell_iterator, unsigned int>,
4521 std::pair<std::pair<cell_iterator, unsigned int>,
4522 std::bitset<3>>>::const_iterator it;
4534 for (
unsigned int repetition = 0; repetition < dim; ++repetition)
4535 for (it = this->get_periodic_face_map().begin();
4536 it != this->get_periodic_face_map().end();
4540 const unsigned int face_no_1 = it->first.second;
4542 const unsigned int face_no_2 = it->second.first.second;
4543 const std::bitset<3> &face_orientation = it->second.second;
4545 if (cell_1->level() == level && cell_2->level() == level)
4547 for (
unsigned int v = 0;
4553 const unsigned int vface0 =
4556 face_orientation[0],
4557 face_orientation[1],
4558 face_orientation[2]);
4559 if (marked_vertices[cell_1->face(face_no_1)->vertex_index(
4561 marked_vertices[cell_2->face(face_no_2)->vertex_index(
4563 marked_vertices[cell_1->face(face_no_1)->vertex_index(
4565 marked_vertices[cell_2->face(face_no_2)->vertex_index(
4571 return marked_vertices;
4576 template <
int dim,
int spacedim>
4580 &periodicity_vector)
4582 Assert(triangulation_has_content ==
true,
4584 Assert(this->n_levels() == 1,
4585 ExcMessage(
"The triangulation is refined!"));
4588 std::vector<::GridTools::PeriodicFacePair<cell_iterator>>;
4589 typename FaceVector::const_iterator it, periodic_end;
4590 it = periodicity_vector.begin();
4591 periodic_end = periodicity_vector.end();
4593 for (; it < periodic_end; ++it)
4597 const unsigned int face_left = it->face_idx[0];
4598 const unsigned int face_right = it->face_idx[1];
4601 const unsigned int tree_left =
4602 coarse_cell_to_p4est_tree_permutation[std::distance(this->begin(),
4604 const unsigned int tree_right =
4605 coarse_cell_to_p4est_tree_permutation[std::distance(this->begin(),
4615 unsigned int p4est_orientation = 0;
4617 p4est_orientation = it->orientation[1];
4620 const unsigned int face_idx_list[] = {face_left, face_right};
4621 const cell_iterator cell_list[] = {first_cell, second_cell};
4622 unsigned int lower_idx, higher_idx;
4623 if (face_left <= face_right)
4636 unsigned int first_p4est_idx_on_cell =
4637 p8est_face_corners[face_idx_list[lower_idx]][0];
4638 unsigned int first_dealii_idx_on_face =
4640 for (
unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face;
4643 const unsigned int first_dealii_idx_on_cell =
4645 face_idx_list[lower_idx],
4647 cell_list[lower_idx]->face_orientation(
4648 face_idx_list[lower_idx]),
4649 cell_list[lower_idx]->face_flip(face_idx_list[lower_idx]),
4650 cell_list[lower_idx]->face_rotation(
4651 face_idx_list[lower_idx]));
4652 if (first_p4est_idx_on_cell == first_dealii_idx_on_cell)
4654 first_dealii_idx_on_face = i;
4661 const unsigned int left_to_right[8][4] = {{0, 2, 1, 3},
4669 const unsigned int right_to_left[8][4] = {{0, 2, 1, 3},
4677 const unsigned int second_dealii_idx_on_face =
4678 lower_idx == 0 ? left_to_right[it->orientation.to_ulong()]
4679 [first_dealii_idx_on_face] :
4680 right_to_left[it->orientation.to_ulong()]
4681 [first_dealii_idx_on_face];
4682 const unsigned int second_dealii_idx_on_cell =
4684 face_idx_list[higher_idx],
4685 second_dealii_idx_on_face,
4686 cell_list[higher_idx]->face_orientation(
4687 face_idx_list[higher_idx]),
4688 cell_list[higher_idx]->face_flip(face_idx_list[higher_idx]),
4689 cell_list[higher_idx]->face_rotation(
4690 face_idx_list[higher_idx]));
4692 const unsigned int second_p4est_idx_on_face =
4693 p8est_corner_face_corners[second_dealii_idx_on_cell]
4694 [face_idx_list[higher_idx]];
4695 p4est_orientation = second_p4est_idx_on_face;
4715 this->mpi_communicator,
4727 copy_local_forest_to_triangulation();
4740 this->update_number_cache();
4745 template <
int dim,
int spacedim>
4751 spacedim>::memory_consumption() +
4756 cell_attached_data.n_attached_data_sets) +
4763 coarse_cell_to_p4est_tree_permutation) +
4765 p4est_tree_to_coarse_cell_permutation) +
4766 memory_consumption_p4est();
4773 template <
int dim,
int spacedim>
4777 return ::internal::p4est::functions<dim>::forest_memory_used(
4785 template <
int dim,
int spacedim>
4788 const ::Triangulation<dim, spacedim> &other_tria)
4796 const typename ::Triangulation<dim, spacedim>::DistortedCellList
4807 triangulation_has_content =
true;
4809 Assert(other_tria.n_levels() == 1,
4811 "Parallel distributed triangulations can only be copied, " 4812 "if they are not refined!"));
4814 if (const ::parallel::distributed::Triangulation<dim, spacedim>
4816 dynamic_cast<const ::parallel::distributed::
4817 Triangulation<dim, spacedim> *
>(&other_tria))
4819 coarse_cell_to_p4est_tree_permutation =
4820 other_tria_x->coarse_cell_to_p4est_tree_permutation;
4821 p4est_tree_to_coarse_cell_permutation =
4822 other_tria_x->p4est_tree_to_coarse_cell_permutation;
4823 cell_attached_data = other_tria_x->cell_attached_data;
4824 data_transfer = other_tria_x->data_transfer;
4826 settings = other_tria_x->settings;
4830 setup_coarse_cell_to_p4est_tree_permutation();
4833 copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
4837 copy_local_forest_to_triangulation();
4846 this->update_number_cache();
4847 this->update_periodic_face_map();
4852 template <
int dim,
int spacedim>
4857 local_quadrant_cell_relations.resize(
4858 parallel_forest->local_num_quadrants);
4859 local_quadrant_cell_relations.shrink_to_fit();
4864 cell != this->end(0);
4868 if (tree_exists_locally<dim, spacedim>(
4870 coarse_cell_to_p4est_tree_permutation[cell->index()]) ==
false)
4874 typename ::internal::p4est::types<dim>::quadrant
4876 ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
4879 typename ::internal::p4est::types<dim>::tree *tree =
4880 init_tree(cell->index());
4882 update_quadrant_cell_relations_recursively<dim, spacedim>(
4883 local_quadrant_cell_relations, *tree, cell, p4est_coarse_cell);
4889 template <
int dim,
int spacedim>
4890 std::vector<unsigned int>
4895 Assert(local_quadrant_cell_relations.size() ==
4896 static_cast<unsigned int>(parallel_forest->local_num_quadrants),
4904 std::vector<unsigned int> weights;
4905 weights.reserve(this->n_active_cells());
4913 for (
const auto &quad_cell_rel : local_quadrant_cell_relations)
4915 const auto &cell_status = std::get<1>(quad_cell_rel);
4916 const auto &cell_it = std::get<2>(quad_cell_rel);
4918 switch (cell_status)
4921 spacedim>::CELL_PERSIST:
4922 weights.push_back(1000);
4923 weights.back() += this->signals.cell_weight(
4926 spacedim>::CELL_PERSIST);
4930 spacedim>::CELL_REFINE:
4932 spacedim>::CELL_INVALID:
4935 unsigned int parent_weight = 1000;
4936 parent_weight += this->signals.cell_weight(
4942 weights.push_back(parent_weight);
4947 spacedim>::CELL_COARSEN:
4948 weights.push_back(1000);
4949 weights.back() += this->signals.cell_weight(
4952 spacedim>::CELL_COARSEN);
4966 template <
int spacedim>
4968 MPI_Comm mpi_communicator,
4969 const typename ::Triangulation<1, spacedim>::MeshSmoothing
4980 template <
int spacedim>
4988 template <
int spacedim>
4991 const std::vector<bool> & )
4998 template <
int spacedim>
5001 const std::function<std::vector<char>(
5002 const typename ::Triangulation<1, spacedim>::cell_iterator &,
5003 const typename ::Triangulation<1, spacedim>::CellStatus)>
5013 template <
int spacedim>
5016 const unsigned int ,
5017 const std::function<
5018 void(
const typename ::Triangulation<1, spacedim>::cell_iterator &,
5019 const typename ::Triangulation<1, spacedim>::CellStatus,
5020 const boost::iterator_range<std::vector<char>::const_iterator> &)>
5028 template <
int spacedim>
5029 const std::vector<types::global_dof_index> &
5033 static std::vector<types::global_dof_index> a;
5039 template <
int spacedim>
5040 std::map<unsigned int, std::set<::types::subdomain_id>>
5044 return std::map<unsigned int, std::set<::types::subdomain_id>>();
5049 template <
int spacedim>
5050 std::map<unsigned int, std::set<::types::subdomain_id>>
5052 const unsigned int )
const 5056 return std::map<unsigned int, std::set<::types::subdomain_id>>();
5061 template <
int spacedim>
5064 const unsigned int)
const 5067 return std::vector<bool>();
5072 template <
int spacedim>
5081 template <
int spacedim>
5092 #endif // DEAL_II_WITH_P4EST 5097 #include "tria.inst" 5100 DEAL_II_NAMESPACE_CLOSE
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
unsigned int n_vertices() const
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const CellStatus)> &pack_callback, const bool returns_variable_size_data)
static const unsigned int invalid_unsigned_int
#define AssertNothrow(cond, exc)
virtual bool has_hanging_nodes() const
static unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
void load(const std::string &filename, const bool autopartition=true)
static ::ExceptionBase & ExcIO()
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
unsigned int compute_n_point_to_point_communications(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
typename ::Triangulation< dim, spacedim >::active_cell_iterator active_cell_iterator
void fill_level_ghost_owners()
active_cell_iterator begin_active(const unsigned int level=0) const
#define AssertThrow(cond, exc)
void save(const std::string &filename) const
cell_iterator begin(const unsigned int level=0) const
const std::vector< types::global_dof_index > & get_p4est_tree_to_coarse_cell_permutation() const
cell_iterator end() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator >> &)
virtual void execute_coarsening_and_refinement()
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &old_tria) override
virtual bool prepare_coarsening_and_refinement()
static ::ExceptionBase & ExcMessage(std::string arg1)
unsigned int subdomain_id
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
T sum(const T &t, const MPI_Comm &mpi_communicator)
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata)
#define Assert(cond, exc)
virtual void update_number_cache()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void load(Archive &ar, const unsigned int version)
void save_coarsen_flags(std::ostream &out) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
void save_refine_flags(std::ostream &out) const
virtual std::size_t memory_consumption() const
void save(Archive &ar, const unsigned int version) const
static unsigned int standard_to_real_face_vertex(const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
const types::subdomain_id artificial_subdomain_id
void communicate_locally_moved_vertices(const std::vector< bool > &vertex_locally_moved)
#define AssertThrowMPI(error_code)
virtual ~Triangulation() override
virtual ~Triangulation() override
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
static ::ExceptionBase & ExcNotImplemented()
active_cell_iterator last_active() const
typename ::Triangulation< dim, spacedim >::cell_iterator cell_iterator
std::vector< bool > mark_locally_active_vertices_on_level(const int level) const
T max(const T &t, const MPI_Comm &mpi_communicator)
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > & get_periodic_face_map() const
virtual void clear() override
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
static ::ExceptionBase & ExcInternalError()
virtual std::map< unsigned int, std::set<::types::subdomain_id > > compute_vertices_with_ghost_neighbors() const override