61 std::vector<std::vector<
62 std::pair<types::global_dof_index, types::global_dof_index>>>
64 std::vector<std::vector<
65 std::pair<types::global_dof_index, types::global_dof_index>>>
66 ©_indices_global_mine,
67 std::vector<std::vector<
68 std::pair<types::global_dof_index, types::global_dof_index>>>
69 ©_indices_level_mine,
70 const bool skip_interface_dofs)
83 std::vector<DoFPair> send_data_temp;
85 const unsigned int n_levels =
87 copy_indices.resize(n_levels);
88 copy_indices_global_mine.resize(n_levels);
89 copy_indices_level_mine.resize(n_levels);
93 std::vector<types::global_dof_index> global_dof_indices(dofs_per_cell);
94 std::vector<types::global_dof_index> level_dof_indices(dofs_per_cell);
98 std::vector<bool> dof_touched(owned_dofs.
n_elements(),
false);
106 std::vector<types::global_dof_index> unrolled_copy_indices;
109 copy_indices_global_mine[
level].clear();
111 for (
const auto &level_cell :
116 (level_cell->level_subdomain_id() ==
118 level_cell->subdomain_id() ==
122 unrolled_copy_indices.resize(owned_dofs.
n_elements(),
127 level_cell->get_dof_indices(global_dof_indices);
128 level_cell->get_mg_dof_indices(level_dof_indices);
130 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
134 if (skip_interface_dofs && mg_constrained_dofs !=
nullptr &&
136 level, level_dof_indices[i]))
148 owned_level_dofs.
is_element(level_dof_indices[i]);
150 if (global_mine && level_mine)
155 unrolled_copy_indices[global_index_in_set] =
156 level_dof_indices[i];
158 else if (global_mine &&
159 dof_touched[global_index_in_set] ==
false)
161 copy_indices_global_mine[
level].emplace_back(
162 global_dof_indices[i], level_dof_indices[i]);
165 send_data_temp.emplace_back(
level,
166 global_dof_indices[i],
167 level_dof_indices[i]);
168 dof_touched[global_index_in_set] =
true;
179 if (!unrolled_copy_indices.empty())
181 copy_indices[
level].clear();
185 if (copy_indices_global_mine[
level].empty())
186 copy_indices[
level].reserve(unrolled_copy_indices.size());
191 for (
unsigned int i = 0; i < unrolled_copy_indices.size(); ++i)
193 copy_indices[
level].emplace_back(
198 const ::parallel::TriangulationBase<dim, spacedim> *tria =
199 (
dynamic_cast<const ::parallel::TriangulationBase<dim, spacedim>
202 send_data_temp.empty() || tria !=
nullptr,
204 "We should only be sending information with a parallel Triangulation!"));
206#ifdef DEAL_II_WITH_MPI
208 tria->get_mpi_communicator()) > 0)
210 const std::set<types::subdomain_id> &neighbors =
211 tria->level_ghost_owners();
212 std::map<int, std::vector<DoFPair>> send_data;
214 std::sort(send_data_temp.begin(),
215 send_data_temp.end(),
217 if (lhs.level < rhs.level)
219 if (lhs.level > rhs.level)
222 if (lhs.level_dof_index < rhs.level_dof_index)
224 if (lhs.level_dof_index > rhs.level_dof_index)
227 if (lhs.global_dof_index < rhs.global_dof_index)
232 send_data_temp.erase(
233 std::unique(send_data_temp.begin(),
234 send_data_temp.end(),
236 return (lhs.level == rhs.level) &&
237 (lhs.level_dof_index == rhs.level_dof_index) &&
238 (lhs.global_dof_index == rhs.global_dof_index);
240 send_data_temp.end());
247 std::vector<types::global_dof_index> level_dof_indices;
248 std::vector<types::global_dof_index> global_dof_indices;
249 for (
const auto &dofpair : send_data_temp)
250 if (dofpair.level ==
level)
252 level_dof_indices.push_back(dofpair.level_dof_index);
253 global_dof_indices.push_back(dofpair.global_dof_index);
258 level_dof_indices.end());
264 owned_level_dofs, is_ghost, tria->get_mpi_communicator());
266 AssertThrow(level_dof_indices.size() == index_owner.size(),
269 for (
unsigned int i = 0; i < index_owner.size(); ++i)
270 send_data[index_owner[i]].emplace_back(
level,
271 global_dof_indices[i],
272 level_dof_indices[i]);
279 mutex, tria->get_mpi_communicator());
285 std::vector<MPI_Request> requests;
287 for (
const auto dest : neighbors)
289 requests.push_back(MPI_Request());
290 std::vector<DoFPair> &
data = send_data[dest];
293 MPI_Isend(
data.data(),
294 data.size() *
sizeof(
decltype(*
data.data())),
298 tria->get_mpi_communicator(),
299 &*requests.rbegin());
307 std::vector<DoFPair> receive_buffer;
308 for (
unsigned int counter = 0; counter < neighbors.size();
312 int ierr = MPI_Probe(MPI_ANY_SOURCE,
314 tria->get_mpi_communicator(),
318 ierr = MPI_Get_count(&status, MPI_BYTE, &len);
323 ierr = MPI_Recv(
nullptr,
328 tria->get_mpi_communicator(),
334 int count = len /
sizeof(
DoFPair);
337 receive_buffer.resize(count);
339 void *ptr = receive_buffer.data();
345 tria->get_mpi_communicator(),
349 for (
const auto &dof_pair : receive_buffer)
351 copy_indices_level_mine[dof_pair.level].emplace_back(
352 dof_pair.global_dof_index, dof_pair.level_dof_index);
358 if (requests.size() > 0)
360 const int ierr = MPI_Waitall(requests.size(),
362 MPI_STATUSES_IGNORE);
371 const int ierr = MPI_Barrier(tria->get_mpi_communicator());
381 std::less<std::pair<types::global_dof_index, types::global_dof_index>>
383 for (
auto &level_indices : copy_indices_level_mine)
384 std::sort(level_indices.begin(), level_indices.end(), compare);
385 for (
auto &level_indices : copy_indices_global_mine)
386 std::sort(level_indices.begin(), level_indices.end(), compare);
396 std::vector<types::global_dof_index> &ghosted_level_dofs,
397 const std::shared_ptr<const Utilities::MPI::Partitioner>
398 &external_partitioner,
400 std::shared_ptr<const Utilities::MPI::Partitioner> &target_partitioner,
403 std::sort(ghosted_level_dofs.begin(), ghosted_level_dofs.end());
405 ghosted_dofs.
add_indices(ghosted_level_dofs.begin(),
406 ghosted_level_dofs.end());
410 if (target_partitioner.get() !=
nullptr &&
411 target_partitioner->size() == locally_owned.
size())
413 ghosted_dofs.
add_indices(target_partitioner->ghost_indices());
418 const bool ghosts_locally_contained =
419 external_partitioner.get() !=
nullptr &&
420 (external_partitioner->ghost_indices() & ghosted_dofs) == ghosted_dofs;
421 if (external_partitioner.get() !=
nullptr &&
427 if (target_partitioner.get() !=
nullptr &&
428 target_partitioner->size() == locally_owned.
size())
429 for (
unsigned int i = 0; i < copy_indices_global_mine.n_cols(); ++i)
430 copy_indices_global_mine(1, i) =
431 external_partitioner->global_to_local(
432 target_partitioner->local_to_global(
433 copy_indices_global_mine(1, i)));
434 target_partitioner = external_partitioner;
438 if (target_partitioner.get() !=
nullptr &&
439 target_partitioner->size() == locally_owned.
size())
440 for (
unsigned int i = 0; i < copy_indices_global_mine.n_cols(); ++i)
441 copy_indices_global_mine(1, i) =
444 target_partitioner->local_to_global(
445 copy_indices_global_mine(1, i)));
447 std::make_shared<Utilities::MPI::Partitioner>(locally_owned,
614 const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
615 &external_partitioners,
617 std::vector<std::vector<unsigned int>> &level_dof_indices,
618 std::vector<std::vector<std::pair<unsigned int, unsigned int>>>
619 &parent_child_connect,
620 std::vector<unsigned int> &n_owned_level_cells,
621 std::vector<std::vector<std::vector<unsigned short>>> &dirichlet_indices,
622 std::vector<std::vector<Number>> &weights_on_refined,
624 MGLevelObject<std::shared_ptr<const Utilities::MPI::Partitioner>>
625 &target_partitioners)
627 level_dof_indices.clear();
628 parent_child_connect.clear();
629 n_owned_level_cells.clear();
630 dirichlet_indices.clear();
631 weights_on_refined.clear();
635 if (mg_constrained_dofs)
637 const unsigned int n_levels =
640 for (
unsigned int l = 0; l < n_levels; ++l)
642 const auto &constraints =
648 for (
const auto dof : constraints.get_local_lines())
650 const auto *entries_ptr =
651 constraints.get_constraint_entries(dof);
653 if (entries_ptr ==
nullptr)
657 Assert((entries_ptr->size() == 0) ||
658 ((entries_ptr->size() == 1) &&
659 (
std::abs((*entries_ptr)[0].second - 1.) <
660 100 * std::numeric_limits<double>::epsilon())),
679 const std::size_t template_starts = fe_name.find_first_of(
'<');
680 Assert(fe_name[template_starts + 1] ==
681 (dim == 1 ?
'1' : (dim == 2 ?
'2' :
'3')),
683 fe_name[template_starts + 1] =
'1';
685 const std::unique_ptr<FiniteElement<1>> fe(
686 FETools::get_fe_by_name<1, 1>(fe_name));
692 const unsigned int n_levels = tria.n_global_levels();
693 level_dof_indices.resize(n_levels);
694 parent_child_connect.resize(n_levels - 1);
695 n_owned_level_cells.resize(n_levels - 1);
696 std::vector<std::vector<unsigned int>> coarse_level_indices(n_levels - 1);
697 for (
unsigned int level = 0;
700 coarse_level_indices[
level].resize(tria.n_raw_cells(
level),
702 std::vector<types::global_dof_index> local_dof_indices(
704 dirichlet_indices.resize(n_levels - 1);
707 Assert(external_partitioners.empty() ||
708 external_partitioners.size() == n_levels,
713 unsigned int counter = 0;
714 std::vector<types::global_dof_index> global_level_dof_indices;
715 std::vector<types::global_dof_index> global_level_dof_indices_remote;
716 std::vector<types::global_dof_index> ghosted_level_dofs;
717 std::vector<types::global_dof_index> global_level_dof_indices_l0;
718 std::vector<types::global_dof_index> ghosted_level_dofs_l0;
723 for (cell = dof_handler.
begin(
level - 1); cell != endc; ++cell)
727 if (!cell->has_children())
731 (tria.locally_owned_subdomain() ==
733 cell->level_subdomain_id() == tria.locally_owned_subdomain());
738 const bool cell_is_remote = !consider_cell;
739 for (
unsigned int c = 0;
740 c < GeometryInfo<dim>::max_children_per_cell;
742 if (cell->child(c)->level_subdomain_id() ==
743 tria.locally_owned_subdomain())
745 consider_cell =
true;
760 std::vector<types::global_dof_index> &next_indices =
761 cell_is_remote ? global_level_dof_indices_remote :
762 global_level_dof_indices;
763 const std::size_t start_index = next_indices.size();
766 for (
unsigned int c = 0;
767 c < GeometryInfo<dim>::max_children_per_cell;
770 if (cell_is_remote && cell->child(c)->level_subdomain_id() !=
771 tria.locally_owned_subdomain())
773 cell->child(c)->get_mg_dof_indices(local_dof_indices);
781 for (
const auto local_dof_index : local_dof_indices)
782 if (!owned_level_dofs.
is_element(local_dof_index))
783 ghosted_level_dofs.push_back(local_dof_index);
785 add_child_indices<dim>(c,
786 fe->n_dofs_per_cell() -
787 fe->n_dofs_per_vertex(),
791 &next_indices[start_index]);
794 if (cell->child(c)->has_children() &&
795 (tria.locally_owned_subdomain() ==
797 cell->child(c)->level_subdomain_id() ==
798 tria.locally_owned_subdomain()))
800 const unsigned int child_index =
801 coarse_level_indices[
level][cell->child(c)->index()];
804 unsigned int parent_index = counter;
815 parent_child_connect[
level][child_index] =
816 std::make_pair(parent_index, c);
818 static_cast<unsigned short>(-1));
822 if (mg_constrained_dofs !=
nullptr)
823 for (
unsigned int i = 0;
824 i < dof_handler.
get_fe().n_dofs_per_cell();
830 dirichlet_indices[
level][child_index].push_back(i);
836 coarse_level_indices[
level - 1].size());
837 coarse_level_indices[
level - 1][cell->index()] = counter++;
844 if (
level == 1 && !cell_is_remote)
846 cell->get_mg_dof_indices(local_dof_indices);
852 const IndexSet &owned_level_dofs_l0 =
854 for (
const auto local_dof_index : local_dof_indices)
855 if (!owned_level_dofs_l0.
is_element(local_dof_index))
856 ghosted_level_dofs_l0.push_back(local_dof_index);
858 const std::size_t start_index =
859 global_level_dof_indices_l0.
size();
860 global_level_dof_indices_l0.resize(
863 add_child_indices<dim>(
865 fe->n_dofs_per_cell() - fe->n_dofs_per_vertex(),
869 &global_level_dof_indices_l0[start_index]);
871 dirichlet_indices[0].emplace_back();
872 if (mg_constrained_dofs !=
nullptr)
873 for (
unsigned int i = 0;
874 i < dof_handler.
get_fe().n_dofs_per_cell();
878 local_dof_indices[elem_info
880 dirichlet_indices[0].back().push_back(i);
888 global_level_dof_indices.size());
889 n_owned_level_cells[
level - 1] = counter;
890 dirichlet_indices[
level - 1].resize(counter);
891 parent_child_connect[
level - 1].resize(
899 if (
level < n_levels - 1)
900 for (std::vector<std::pair<unsigned int, unsigned int>>::iterator
902 i != parent_child_connect[
level].end();
904 if (i->first >= tria.n_cells(
level))
906 i->first -= tria.n_cells(
level);
918 external_partitioners.empty() ?
920 external_partitioners[
level],
921 tria.get_mpi_communicator(),
922 target_partitioners[
level],
923 copy_indices_global_mine[
level]);
926 global_level_dof_indices,
927 global_level_dof_indices_remote,
928 level_dof_indices[
level]);
932 for (
unsigned int i = 0; i < parent_child_connect[0].size(); ++i)
933 parent_child_connect[0][i] = std::make_pair(i, 0U);
936 ghosted_level_dofs_l0,
937 external_partitioners.empty() ?
939 external_partitioners[0],
940 tria.get_mpi_communicator(),
941 target_partitioners[0],
942 copy_indices_global_mine[0]);
945 *target_partitioners[0],
946 global_level_dof_indices_l0,
947 std::vector<types::global_dof_index>(),
948 level_dof_indices[0]);
954 const unsigned int n_child_dofs_1d =
955 fe->degree + 1 + fe->n_dofs_per_cell() - fe->n_dofs_per_vertex();
959 weights_on_refined.resize(n_levels - 1);
963 target_partitioners[
level]);
964 for (
unsigned int c = 0; c < n_owned_level_cells[
level - 1]; ++c)
972 std::vector<unsigned int> degree_to_3(n_child_dofs_1d);
974 for (
unsigned int i = 1; i < n_child_dofs_1d - 1; ++i)
976 degree_to_3.back() = 2;
980 weights_on_refined[
level - 1].resize(n_owned_level_cells[
level - 1] *
981 Utilities::fixed_power<dim>(3));
982 for (
unsigned int c = 0; c < n_owned_level_cells[
level - 1]; ++c)
983 for (
unsigned int k = 0, m = 0; k < (dim > 2 ? n_child_dofs_1d : 1);
985 for (
unsigned int j = 0; j < (dim > 1 ? n_child_dofs_1d : 1); ++j)
987 unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
988 for (
unsigned int i = 0; i < n_child_dofs_1d; ++i, ++m)
989 weights_on_refined[
level -
990 1][c * Utilities::fixed_power<dim>(3) +
991 shift + degree_to_3[i]] =
994 level_dof_indices[
level]