63 std::vector<std::vector<
64 std::pair<types::global_dof_index, types::global_dof_index>>>
66 std::vector<std::vector<
67 std::pair<types::global_dof_index, types::global_dof_index>>>
68 ©_indices_global_mine,
69 std::vector<std::vector<
70 std::pair<types::global_dof_index, types::global_dof_index>>>
71 ©_indices_level_mine,
72 const bool skip_interface_dofs)
85 std::vector<DoFPair> send_data_temp;
87 const unsigned int n_levels =
89 copy_indices.resize(n_levels);
90 copy_indices_global_mine.resize(n_levels);
91 copy_indices_level_mine.resize(n_levels);
95 std::vector<types::global_dof_index> global_dof_indices(dofs_per_cell);
96 std::vector<types::global_dof_index> level_dof_indices(dofs_per_cell);
100 std::vector<bool> dof_touched(owned_dofs.
n_elements(),
false);
108 std::vector<types::global_dof_index> unrolled_copy_indices;
111 copy_indices_global_mine[
level].clear();
113 for (
const auto &level_cell :
118 (level_cell->level_subdomain_id() ==
120 level_cell->subdomain_id() ==
124 unrolled_copy_indices.resize(owned_dofs.
n_elements(),
129 level_cell->get_dof_indices(global_dof_indices);
130 level_cell->get_mg_dof_indices(level_dof_indices);
132 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
136 if (skip_interface_dofs && mg_constrained_dofs !=
nullptr &&
138 level, level_dof_indices[i]))
150 owned_level_dofs.
is_element(level_dof_indices[i]);
152 if (global_mine && level_mine)
157 unrolled_copy_indices[global_index_in_set] =
158 level_dof_indices[i];
160 else if (global_mine &&
161 dof_touched[global_index_in_set] ==
false)
163 copy_indices_global_mine[
level].emplace_back(
164 global_dof_indices[i], level_dof_indices[i]);
167 send_data_temp.emplace_back(
level,
168 global_dof_indices[i],
169 level_dof_indices[i]);
170 dof_touched[global_index_in_set] =
true;
181 if (!unrolled_copy_indices.empty())
183 copy_indices[
level].clear();
187 if (copy_indices_global_mine[
level].empty())
188 copy_indices[
level].reserve(unrolled_copy_indices.size());
193 for (
unsigned int i = 0; i < unrolled_copy_indices.size(); ++i)
195 copy_indices[
level].emplace_back(
200 const ::parallel::TriangulationBase<dim, spacedim> *tria =
201 (
dynamic_cast<const ::parallel::TriangulationBase<dim, spacedim>
204 send_data_temp.empty() || tria !=
nullptr,
206 "We should only be sending information with a parallel Triangulation!"));
208#ifdef DEAL_II_WITH_MPI
210 tria->get_communicator()) > 0)
212 const std::set<types::subdomain_id> &neighbors =
213 tria->level_ghost_owners();
214 std::map<int, std::vector<DoFPair>> send_data;
216 std::sort(send_data_temp.begin(),
217 send_data_temp.end(),
219 if (lhs.level < rhs.level)
221 if (lhs.level > rhs.level)
224 if (lhs.level_dof_index < rhs.level_dof_index)
226 if (lhs.level_dof_index > rhs.level_dof_index)
229 if (lhs.global_dof_index < rhs.global_dof_index)
234 send_data_temp.erase(
235 std::unique(send_data_temp.begin(),
236 send_data_temp.end(),
238 return (lhs.level == rhs.level) &&
239 (lhs.level_dof_index == rhs.level_dof_index) &&
240 (lhs.global_dof_index == rhs.global_dof_index);
242 send_data_temp.end());
249 std::vector<types::global_dof_index> level_dof_indices;
250 std::vector<types::global_dof_index> global_dof_indices;
251 for (
const auto &dofpair : send_data_temp)
252 if (dofpair.level ==
level)
254 level_dof_indices.push_back(dofpair.level_dof_index);
255 global_dof_indices.push_back(dofpair.global_dof_index);
260 level_dof_indices.end());
265 const auto index_owner =
268 tria->get_communicator());
270 AssertThrow(level_dof_indices.size() == index_owner.size(),
273 for (
unsigned int i = 0; i < index_owner.size(); ++i)
274 send_data[index_owner[i]].emplace_back(
level,
275 global_dof_indices[i],
276 level_dof_indices[i]);
283 mutex, tria->get_communicator());
289 std::vector<MPI_Request> requests;
291 for (
const auto dest : neighbors)
293 requests.push_back(MPI_Request());
294 std::vector<DoFPair> &data = send_data[dest];
297 MPI_Isend(data.data(),
298 data.size() *
sizeof(
decltype(*data.data())),
302 tria->get_communicator(),
303 &*requests.rbegin());
311 std::vector<DoFPair> receive_buffer;
312 for (
unsigned int counter = 0; counter < neighbors.size();
316 int ierr = MPI_Probe(MPI_ANY_SOURCE,
318 tria->get_communicator(),
322 ierr = MPI_Get_count(&status, MPI_BYTE, &len);
327 ierr = MPI_Recv(
nullptr,
332 tria->get_communicator(),
338 int count = len /
sizeof(
DoFPair);
341 receive_buffer.resize(count);
343 void *ptr = receive_buffer.data();
349 tria->get_communicator(),
353 for (
const auto &dof_pair : receive_buffer)
355 copy_indices_level_mine[dof_pair.level].emplace_back(
356 dof_pair.global_dof_index, dof_pair.level_dof_index);
362 if (requests.size() > 0)
364 const int ierr = MPI_Waitall(requests.size(),
366 MPI_STATUSES_IGNORE);
374 const int ierr = MPI_Barrier(tria->get_communicator());
384 std::less<std::pair<types::global_dof_index, types::global_dof_index>>
386 for (
auto &level_indices : copy_indices_level_mine)
387 std::sort(level_indices.begin(), level_indices.end(), compare);
388 for (
auto &level_indices : copy_indices_global_mine)
389 std::sort(level_indices.begin(), level_indices.end(), compare);
399 std::vector<types::global_dof_index> &ghosted_level_dofs,
400 const std::shared_ptr<const Utilities::MPI::Partitioner>
401 &external_partitioner,
403 std::shared_ptr<const Utilities::MPI::Partitioner> &target_partitioner,
406 std::sort(ghosted_level_dofs.begin(), ghosted_level_dofs.end());
408 ghosted_dofs.
add_indices(ghosted_level_dofs.begin(),
409 ghosted_level_dofs.end());
413 if (target_partitioner.get() !=
nullptr &&
414 target_partitioner->size() == locally_owned.
size())
416 ghosted_dofs.
add_indices(target_partitioner->ghost_indices());
421 const int ghosts_locally_contained =
422 (external_partitioner.get() !=
nullptr &&
423 (external_partitioner->ghost_indices() & ghosted_dofs) ==
427 if (external_partitioner.get() !=
nullptr &&
433 if (target_partitioner.get() !=
nullptr &&
434 target_partitioner->size() == locally_owned.
size())
435 for (
unsigned int i = 0; i < copy_indices_global_mine.n_cols(); ++i)
436 copy_indices_global_mine(1, i) =
437 external_partitioner->global_to_local(
438 target_partitioner->local_to_global(
439 copy_indices_global_mine(1, i)));
440 target_partitioner = external_partitioner;
444 if (target_partitioner.get() !=
nullptr &&
445 target_partitioner->size() == locally_owned.
size())
446 for (
unsigned int i = 0; i < copy_indices_global_mine.n_cols(); ++i)
447 copy_indices_global_mine(1, i) =
450 target_partitioner->local_to_global(
451 copy_indices_global_mine(1, i)));
453 std::make_shared<Utilities::MPI::Partitioner>(locally_owned,
620 const std::vector<std::shared_ptr<const Utilities::MPI::Partitioner>>
621 &external_partitioners,
623 std::vector<std::vector<unsigned int>> &level_dof_indices,
624 std::vector<std::vector<std::pair<unsigned int, unsigned int>>>
625 &parent_child_connect,
626 std::vector<unsigned int> &n_owned_level_cells,
627 std::vector<std::vector<std::vector<unsigned short>>> &dirichlet_indices,
628 std::vector<std::vector<Number>> &weights_on_refined,
630 MGLevelObject<std::shared_ptr<const Utilities::MPI::Partitioner>>
631 &target_partitioners)
633 level_dof_indices.clear();
634 parent_child_connect.clear();
635 n_owned_level_cells.clear();
636 dirichlet_indices.clear();
637 weights_on_refined.clear();
640 if (mg_constrained_dofs)
642 const unsigned int n_levels =
645 for (
unsigned int l = 0; l < n_levels; ++l)
647 const auto &constraints =
653 for (
const auto dof : constraints.get_local_lines())
655 const auto *entries_ptr =
656 constraints.get_constraint_entries(dof);
658 if (entries_ptr ==
nullptr)
662 Assert((entries_ptr->size() == 0) ||
663 ((entries_ptr->size() == 1) &&
664 (
std::abs((*entries_ptr)[0].second - 1.) <
665 100 * std::numeric_limits<double>::epsilon())),
684 const std::size_t template_starts = fe_name.find_first_of(
'<');
685 Assert(fe_name[template_starts + 1] ==
686 (dim == 1 ?
'1' : (dim == 2 ?
'2' :
'3')),
688 fe_name[template_starts + 1] =
'1';
690 const std::unique_ptr<FiniteElement<1>> fe(
697 const unsigned int n_levels = tria.n_global_levels();
698 level_dof_indices.resize(n_levels);
699 parent_child_connect.resize(n_levels - 1);
700 n_owned_level_cells.resize(n_levels - 1);
701 std::vector<std::vector<unsigned int>> coarse_level_indices(n_levels - 1);
702 for (
unsigned int level = 0;
705 coarse_level_indices[
level].resize(tria.n_raw_cells(
level),
707 std::vector<types::global_dof_index> local_dof_indices(
709 dirichlet_indices.resize(n_levels - 1);
712 Assert(external_partitioners.empty() ||
713 external_partitioners.size() == n_levels,
718 unsigned int counter = 0;
719 std::vector<types::global_dof_index> global_level_dof_indices;
720 std::vector<types::global_dof_index> global_level_dof_indices_remote;
721 std::vector<types::global_dof_index> ghosted_level_dofs;
722 std::vector<types::global_dof_index> global_level_dof_indices_l0;
723 std::vector<types::global_dof_index> ghosted_level_dofs_l0;
728 for (cell = dof_handler.
begin(
level - 1); cell != endc; ++cell)
732 if (!cell->has_children())
736 (tria.locally_owned_subdomain() ==
738 cell->level_subdomain_id() == tria.locally_owned_subdomain());
743 const bool cell_is_remote = !consider_cell;
744 for (
unsigned int c = 0;
745 c < GeometryInfo<dim>::max_children_per_cell;
747 if (cell->child(c)->level_subdomain_id() ==
748 tria.locally_owned_subdomain())
750 consider_cell =
true;
765 std::vector<types::global_dof_index> &next_indices =
766 cell_is_remote ? global_level_dof_indices_remote :
767 global_level_dof_indices;
768 const std::size_t start_index = next_indices.size();
771 for (
unsigned int c = 0;
772 c < GeometryInfo<dim>::max_children_per_cell;
775 if (cell_is_remote && cell->child(c)->level_subdomain_id() !=
776 tria.locally_owned_subdomain())
778 cell->child(c)->get_mg_dof_indices(local_dof_indices);
786 for (
const auto local_dof_index : local_dof_indices)
787 if (!owned_level_dofs.
is_element(local_dof_index))
788 ghosted_level_dofs.push_back(local_dof_index);
791 fe->n_dofs_per_cell() -
792 fe->n_dofs_per_vertex(),
796 &next_indices[start_index]);
799 if (cell->child(c)->has_children() &&
800 (tria.locally_owned_subdomain() ==
802 cell->child(c)->level_subdomain_id() ==
803 tria.locally_owned_subdomain()))
805 const unsigned int child_index =
806 coarse_level_indices[
level][cell->child(c)->index()];
808 parent_child_connect[
level].size());
809 unsigned int parent_index = counter;
820 parent_child_connect[
level][child_index] =
821 std::make_pair(parent_index, c);
823 static_cast<unsigned short>(-1));
827 if (mg_constrained_dofs !=
nullptr)
828 for (
unsigned int i = 0;
829 i < dof_handler.
get_fe().n_dofs_per_cell();
835 dirichlet_indices[
level][child_index].push_back(i);
841 coarse_level_indices[
level - 1].size());
842 coarse_level_indices[
level - 1][cell->index()] = counter++;
849 if (
level == 1 && !cell_is_remote)
851 cell->get_mg_dof_indices(local_dof_indices);
857 const IndexSet &owned_level_dofs_l0 =
859 for (
const auto local_dof_index : local_dof_indices)
860 if (!owned_level_dofs_l0.
is_element(local_dof_index))
861 ghosted_level_dofs_l0.push_back(local_dof_index);
863 const std::size_t start_index =
864 global_level_dof_indices_l0.size();
865 global_level_dof_indices_l0.resize(
870 fe->n_dofs_per_cell() - fe->n_dofs_per_vertex(),
874 &global_level_dof_indices_l0[start_index]);
876 dirichlet_indices[0].emplace_back();
877 if (mg_constrained_dofs !=
nullptr)
878 for (
unsigned int i = 0;
879 i < dof_handler.
get_fe().n_dofs_per_cell();
883 local_dof_indices[elem_info
885 dirichlet_indices[0].back().push_back(i);
893 global_level_dof_indices.size());
894 n_owned_level_cells[
level - 1] = counter;
895 dirichlet_indices[
level - 1].resize(counter);
896 parent_child_connect[
level - 1].resize(
904 if (
level < n_levels - 1)
905 for (std::vector<std::pair<unsigned int, unsigned int>>::iterator
906 i = parent_child_connect[
level].begin();
907 i != parent_child_connect[
level].end();
909 if (i->first >= tria.n_cells(
level))
911 i->first -= tria.n_cells(
level);
923 external_partitioners.empty() ?
925 external_partitioners[
level],
926 tria.get_communicator(),
927 target_partitioners[
level],
928 copy_indices_global_mine[
level]);
931 global_level_dof_indices,
932 global_level_dof_indices_remote,
933 level_dof_indices[
level]);
937 for (
unsigned int i = 0; i < parent_child_connect[0].size(); ++i)
938 parent_child_connect[0][i] = std::make_pair(i, 0U);
941 ghosted_level_dofs_l0,
942 external_partitioners.empty() ?
944 external_partitioners[0],
945 tria.get_communicator(),
946 target_partitioners[0],
947 copy_indices_global_mine[0]);
950 *target_partitioners[0],
951 global_level_dof_indices_l0,
952 std::vector<types::global_dof_index>(),
953 level_dof_indices[0]);
959 const unsigned int n_child_dofs_1d =
960 fe->degree + 1 + fe->n_dofs_per_cell() - fe->n_dofs_per_vertex();
964 weights_on_refined.resize(n_levels - 1);
968 target_partitioners[
level]);
969 for (
unsigned int c = 0; c < n_owned_level_cells[
level - 1]; ++c)
977 std::vector<unsigned int> degree_to_3(n_child_dofs_1d);
979 for (
unsigned int i = 1; i < n_child_dofs_1d - 1; ++i)
981 degree_to_3.back() = 2;
985 weights_on_refined[
level - 1].resize(n_owned_level_cells[
level - 1] *
987 for (
unsigned int c = 0; c < n_owned_level_cells[
level - 1]; ++c)
988 for (
unsigned int k = 0, m = 0; k < (dim > 2 ? n_child_dofs_1d : 1);
990 for (
unsigned int j = 0; j < (dim > 1 ? n_child_dofs_1d : 1); ++j)
992 unsigned int shift = 9 * degree_to_3[k] + 3 * degree_to_3[j];
993 for (
unsigned int i = 0; i < n_child_dofs_1d; ++i, ++m)
994 weights_on_refined[
level -
996 shift + degree_to_3[i]] =
999 level_dof_indices[
level]