40 #ifdef DEAL_II_WITH_MPI
62 check_master_dof_list(
64 const std::vector<types::global_dof_index> &master_dof_list)
66 const unsigned int N = master_dof_list.size();
69 for (
unsigned int i = 0; i <
N; ++i)
70 for (
unsigned int j = 0; j <
N; ++j)
71 tmp(i, j) = face_interpolation_matrix(master_dof_list[i], j);
82 double diagonal_sum = 0;
83 for (
unsigned int i = 0; i <
N; ++i)
85 const double typical_diagonal_element = diagonal_sum /
N;
89 std::vector<unsigned int> p(
N);
90 for (
unsigned int i = 0; i <
N; ++i)
93 for (
unsigned int j = 0; j <
N; ++j)
99 for (
unsigned int i = j + 1; i <
N; ++i)
110 if (
max < 1.
e-12 * typical_diagonal_element)
116 for (
unsigned int k = 0; k <
N; ++k)
123 const double hr = 1. / tmp(j, j);
125 for (
unsigned int k = 0; k <
N; ++k)
129 for (
unsigned int i = 0; i <
N; ++i)
133 tmp(i, k) -= tmp(i, j) * tmp(j, k) * hr;
136 for (
unsigned int i = 0; i <
N; ++i)
172 template <
int dim,
int spacedim>
174 select_master_dofs_for_face_restriction(
178 std::vector<bool> & master_dof_mask)
208 std::vector<types::global_dof_index> master_dof_list;
209 unsigned int index = 0;
214 unsigned int dofs_added = 0;
223 master_dof_list.push_back(index + i);
226 if (check_master_dof_list(face_interpolation_matrix,
227 master_dof_list) ==
true)
232 master_dof_list.pop_back();
245 unsigned int dofs_added = 0;
251 master_dof_list.push_back(index + i);
252 if (check_master_dof_list(face_interpolation_matrix,
253 master_dof_list) ==
true)
256 master_dof_list.pop_back();
268 unsigned int dofs_added = 0;
274 master_dof_list.push_back(index + i);
275 if (check_master_dof_list(face_interpolation_matrix,
276 master_dof_list) ==
true)
279 master_dof_list.pop_back();
290 std::fill(master_dof_mask.begin(), master_dof_mask.end(),
false);
291 for (
const auto dof : master_dof_list)
292 master_dof_mask[dof] =
true;
301 template <
int dim,
int spacedim>
303 ensure_existence_of_master_dof_mask(
307 std::unique_ptr<std::vector<bool>> &master_dof_mask)
309 if (master_dof_mask ==
nullptr)
312 std_cxx14::make_unique<std::vector<bool>>(fe1.
dofs_per_face);
313 select_master_dofs_for_face_restriction(fe1,
315 face_interpolation_matrix,
327 template <
int dim,
int spacedim>
329 ensure_existence_of_face_matrix(
337 std_cxx14::make_unique<FullMatrix<double>>(fe2.
dofs_per_face,
348 template <
int dim,
int spacedim>
350 ensure_existence_of_subface_matrix(
353 const unsigned int subface,
359 std_cxx14::make_unique<FullMatrix<double>>(fe2.
dofs_per_face,
373 ensure_existence_of_split_face_matrix(
375 const std::vector<bool> & master_dof_mask,
380 Assert(std::count(master_dof_mask.begin(),
381 master_dof_mask.end(),
383 static_cast<signed int>(face_interpolation_matrix.
n()),
386 if (split_matrix ==
nullptr)
388 split_matrix = std_cxx14::make_unique<
391 const unsigned int n_master_dofs = face_interpolation_matrix.
n();
392 const unsigned int n_dofs = face_interpolation_matrix.
m();
397 split_matrix->first.reinit(n_master_dofs, n_master_dofs);
398 split_matrix->second.reinit(n_dofs - n_master_dofs, n_master_dofs);
400 unsigned int nth_master_dof = 0, nth_slave_dof = 0;
402 for (
unsigned int i = 0; i < n_dofs; ++i)
403 if (master_dof_mask[i] ==
true)
405 for (
unsigned int j = 0; j < n_master_dofs; ++j)
406 split_matrix->first(nth_master_dof, j) =
407 face_interpolation_matrix(i, j);
412 for (
unsigned int j = 0; j < n_master_dofs; ++j)
413 split_matrix->second(nth_slave_dof, j) =
414 face_interpolation_matrix(i, j);
423 split_matrix->first.gauss_jordan();
431 struct DoFHandlerSupportsDifferentFEs
437 template <
int dim,
int spacedim>
438 struct DoFHandlerSupportsDifferentFEs<::
DoFHandler<dim, spacedim>>
440 static const bool value =
false;
449 template <
int dim,
int spacedim>
452 const ::hp::DoFHandler<dim, spacedim> &dof_handler)
454 return dof_handler.get_fe_collection().size();
458 template <
typename DoFHandlerType>
460 n_finite_elements(
const DoFHandlerType &)
477 template <
typename number1,
typename number2>
480 const std::vector<types::global_dof_index> &master_dofs,
481 const std::vector<types::global_dof_index> &slave_dofs,
485 Assert(face_constraints.
n() == master_dofs.size(),
487 Assert(face_constraints.
m() == slave_dofs.size(),
490 const unsigned int n_master_dofs = master_dofs.size();
491 const unsigned int n_slave_dofs = slave_dofs.size();
495 for (
unsigned int row = 0; row != n_slave_dofs; ++row)
498 for (
unsigned int col = 0; col != n_master_dofs; ++col)
503 for (
unsigned int row = 0; row != n_slave_dofs; ++row)
506 bool constraint_already_satisfied =
false;
511 for (
unsigned int i = 0; i < n_master_dofs; ++i)
512 if (face_constraints(row, i) == 1.0)
513 if (master_dofs[i] == slave_dofs[row])
515 constraint_already_satisfied =
true;
519 if (constraint_already_satisfied ==
false)
524 for (
unsigned int i = 0; i < n_master_dofs; ++i)
525 abs_sum += std::abs(face_constraints(row, i));
533 constraints.
add_line(slave_dofs[row]);
534 for (
unsigned int i = 0; i < n_master_dofs; ++i)
535 if ((face_constraints(row, i) != 0) &&
540 face_constraints(row, i));
550 template <
typename number,
int spacedim>
553 const ::hp::DoFHandler<1, spacedim> & ,
560 template <
typename number,
int spacedim>
563 const ::hp::DoFHandler<1, spacedim> & ,
565 std::integral_constant<int, 1>)
571 template <
typename number,
int spacedim>
574 const ::DoFHandler<1, spacedim> & ,
581 template <
typename number,
int spacedim>
584 const ::DoFHandler<1, spacedim> & ,
586 std::integral_constant<int, 1>)
591 template <
typename DoFHandlerType,
typename number>
594 const DoFHandlerType & dof_handler,
596 std::integral_constant<int, 2>)
598 const unsigned int dim = 2;
600 const unsigned int spacedim = DoFHandlerType::space_dimension;
602 std::vector<types::global_dof_index> dofs_on_mother;
603 std::vector<types::global_dof_index> dofs_on_children;
613 typename DoFHandlerType::active_cell_iterator cell = dof_handler
615 endc = dof_handler.end();
616 for (; cell != endc; ++cell)
620 if (cell->is_artificial())
624 if (cell->face(face)->has_children())
630 Assert(cell->face(face)->n_active_fe_indices() == 1,
632 Assert(cell->face(face)->fe_index_is_active(
633 cell->active_fe_index()) ==
true,
635 for (
unsigned int c = 0; c < cell->face(face)->n_children();
637 if (!cell->neighbor_child_on_subface(face, c)
639 Assert(cell->face(face)->child(c)->n_active_fe_indices() ==
645 for (
unsigned int c = 0; c < cell->face(face)->n_children();
647 if (!cell->neighbor_child_on_subface(face, c)
649 Assert(cell->face(face)->child(c)->fe_index_is_active(
650 cell->active_fe_index()) ==
true,
655 const unsigned int fe_index = cell->active_fe_index();
657 const unsigned int n_dofs_on_mother =
662 dofs_on_mother.resize(n_dofs_on_mother);
665 dofs_on_children.clear();
666 dofs_on_children.reserve(n_dofs_on_children);
675 const typename DoFHandlerType::line_iterator this_face =
680 unsigned int next_index = 0;
681 for (
unsigned int vertex = 0; vertex < 2; ++vertex)
683 dofs_on_mother[next_index++] =
684 this_face->vertex_dof_index(vertex, dof, fe_index);
686 dofs_on_mother[next_index++] =
687 this_face->dof_index(dof, fe_index);
691 dofs_on_children.push_back(
692 this_face->child(0)->vertex_dof_index(1, dof, fe_index));
693 for (
unsigned int child = 0; child < 2; ++child)
696 if (cell->neighbor_child_on_subface(face, child)
700 dofs_on_children.push_back(
701 this_face->child(child)->dof_index(dof, fe_index));
704 Assert(dofs_on_children.size() <= n_dofs_on_children,
708 for (
unsigned int row = 0; row != dofs_on_children.size();
711 constraints.
add_line(dofs_on_children[row]);
712 for (
unsigned int i = 0; i != dofs_on_mother.size(); ++i)
713 constraints.
add_entry(dofs_on_children[row],
726 if (!cell->at_boundary(face) &&
727 !cell->neighbor(face)->is_artificial())
729 Assert(cell->face(face)->n_active_fe_indices() == 1,
731 Assert(cell->face(face)->fe_index_is_active(
732 cell->active_fe_index()) ==
true,
741 template <
typename DoFHandlerType,
typename number>
744 const DoFHandlerType & dof_handler,
746 std::integral_constant<int, 3>)
748 const unsigned int dim = 3;
750 std::vector<types::global_dof_index> dofs_on_mother;
751 std::vector<types::global_dof_index> dofs_on_children;
761 typename DoFHandlerType::active_cell_iterator cell = dof_handler
763 endc = dof_handler.end();
764 for (; cell != endc; ++cell)
768 if (cell->is_artificial())
772 if (cell->face(face)->has_children())
777 if (cell->get_fe().dofs_per_face == 0)
780 Assert(cell->face(face)->refinement_case() ==
789 Assert(cell->face(face)->fe_index_is_active(
790 cell->active_fe_index()) ==
true,
792 for (
unsigned int c = 0; c < cell->face(face)->n_children();
794 if (!cell->neighbor_child_on_subface(face, c)
797 cell->face(face)->child(c)->n_active_fe_indices(), 1);
802 for (
unsigned int c = 0; c < cell->face(face)->n_children();
804 if (!cell->neighbor_child_on_subface(face, c)
807 Assert(cell->face(face)->child(c)->fe_index_is_active(
808 cell->active_fe_index()) ==
true,
810 for (
unsigned int e = 0;
e < 4; ++
e)
815 ->n_active_fe_indices() == 1,
820 ->fe_index_is_active(
821 cell->active_fe_index()) ==
true,
825 for (
unsigned int e = 0;
e < 4; ++
e)
827 Assert(cell->face(face)->line(
e)->n_active_fe_indices() ==
830 Assert(cell->face(face)->line(
e)->fe_index_is_active(
831 cell->active_fe_index()) ==
true,
837 const unsigned int fe_index = cell->active_fe_index();
840 const unsigned int n_dofs_on_children =
847 dofs_on_mother.resize(n_dofs_on_mother);
850 dofs_on_children.clear();
851 dofs_on_children.reserve(n_dofs_on_children);
860 const typename DoFHandlerType::face_iterator this_face =
865 unsigned int next_index = 0;
866 for (
unsigned int vertex = 0; vertex < 4; ++vertex)
868 dofs_on_mother[next_index++] =
869 this_face->vertex_dof_index(vertex, dof, fe_index);
870 for (
unsigned int line = 0; line < 4; ++line)
872 dofs_on_mother[next_index++] =
873 this_face->line(line)->dof_index(dof, fe_index);
875 dofs_on_mother[next_index++] =
876 this_face->dof_index(dof, fe_index);
883 Assert(dof_handler.get_triangulation()
884 .get_anisotropic_refinement_flag() ||
885 ((this_face->child(0)->vertex_index(3) ==
886 this_face->child(1)->vertex_index(2)) &&
887 (this_face->child(0)->vertex_index(3) ==
888 this_face->child(2)->vertex_index(1)) &&
889 (this_face->child(0)->vertex_index(3) ==
890 this_face->child(3)->vertex_index(0))),
894 dofs_on_children.push_back(
895 this_face->child(0)->vertex_dof_index(3, dof));
898 for (
unsigned int line = 0; line < 4; ++line)
900 dofs_on_children.push_back(
901 this_face->line(line)->child(0)->vertex_dof_index(
908 dofs_on_children.push_back(
909 this_face->child(0)->line(1)->dof_index(dof, fe_index));
911 dofs_on_children.push_back(
912 this_face->child(2)->line(1)->dof_index(dof, fe_index));
914 dofs_on_children.push_back(
915 this_face->child(0)->line(3)->dof_index(dof, fe_index));
917 dofs_on_children.push_back(
918 this_face->child(1)->line(3)->dof_index(dof, fe_index));
921 for (
unsigned int line = 0; line < 4; ++line)
922 for (
unsigned int child = 0; child < 2; ++child)
925 dofs_on_children.push_back(
926 this_face->line(line)->child(child)->dof_index(
931 for (
unsigned int child = 0; child < 4; ++child)
934 if (cell->neighbor_child_on_subface(face, child)
938 dofs_on_children.push_back(
939 this_face->child(child)->dof_index(dof, fe_index));
943 Assert(dofs_on_children.size() <= n_dofs_on_children,
947 for (
unsigned int row = 0; row != dofs_on_children.size();
950 constraints.
add_line(dofs_on_children[row]);
951 for (
unsigned int i = 0; i != dofs_on_mother.size(); ++i)
952 constraints.
add_entry(dofs_on_children[row],
965 if (!cell->at_boundary(face) &&
966 !cell->neighbor(face)->is_artificial())
968 Assert(cell->face(face)->n_active_fe_indices() == 1,
970 Assert(cell->face(face)->fe_index_is_active(
971 cell->active_fe_index()) ==
true,
980 template <
typename DoFHandlerType,
typename number>
990 const unsigned int dim = DoFHandlerType::dimension;
992 const unsigned int spacedim = DoFHandlerType::space_dimension;
1001 std::vector<types::global_dof_index> master_dofs;
1002 std::vector<types::global_dof_index> slave_dofs;
1003 std::vector<types::global_dof_index> scratch_dofs;
1009 n_finite_elements(dof_handler), n_finite_elements(dof_handler));
1011 subface_interpolation_matrices(
1012 n_finite_elements(dof_handler),
1013 n_finite_elements(dof_handler),
1022 split_face_interpolation_matrices(n_finite_elements(dof_handler),
1023 n_finite_elements(dof_handler));
1029 n_finite_elements(dof_handler), n_finite_elements(dof_handler));
1036 for (
const auto &cell : dof_handler.active_cell_iterators())
1040 if (cell->is_artificial())
1044 if (cell->face(face)->has_children())
1049 if (cell->get_fe().dofs_per_face == 0)
1052 Assert(cell->face(face)->refinement_case() ==
1063 Assert(cell->face(face)->n_active_fe_indices() == 1,
1065 Assert(cell->face(face)->fe_index_is_active(
1066 cell->active_fe_index()) ==
true,
1068 for (
unsigned int c = 0; c < cell->face(face)->n_children();
1070 if (!cell->neighbor_child_on_subface(face, c)
1072 Assert(cell->face(face)->child(c)->n_active_fe_indices() ==
1088 std::set<unsigned int> fe_ind_face_subface;
1089 fe_ind_face_subface.insert(cell->active_fe_index());
1093 for (
unsigned int c = 0;
1094 c < cell->face(face)->number_of_children();
1097 const auto subcell =
1098 cell->neighbor_child_on_subface(face, c);
1099 if (!subcell->is_artificial())
1101 mother_face_dominates =
1102 mother_face_dominates &
1103 (cell->get_fe().compare_for_domination(
1104 subcell->get_fe(), 1));
1105 fe_ind_face_subface.insert(
1106 subcell->active_fe_index());
1110 switch (mother_face_dominates)
1122 master_dofs.resize(cell->get_fe().dofs_per_face);
1124 cell->face(face)->get_dof_indices(
1125 master_dofs, cell->active_fe_index());
1131 for (
unsigned int c = 0;
1132 c < cell->face(face)->n_children();
1135 if (cell->neighbor_child_on_subface(face, c)
1139 const typename DoFHandlerType::active_face_iterator
1140 subface = cell->face(face)->child(c);
1142 Assert(subface->n_active_fe_indices() == 1,
1145 const unsigned int subface_fe_index =
1146 subface->nth_active_fe_index(0);
1157 if (cell->get_fe().compare_for_domination(
1158 subface->get_fe(subface_fe_index),
1166 subface->get_fe(subface_fe_index).dofs_per_face);
1167 subface->get_dof_indices(slave_dofs,
1200 ensure_existence_of_subface_matrix(
1202 subface->get_fe(subface_fe_index),
1204 subface_interpolation_matrices
1205 [cell->active_fe_index()][subface_fe_index][c]);
1209 filter_constraints(master_dofs,
1211 *(subface_interpolation_matrices
1212 [cell->active_fe_index()]
1213 [subface_fe_index][c]),
1230 Assert(DoFHandlerSupportsDifferentFEs<
1231 DoFHandlerType>::
value ==
true,
1234 const ::hp::FECollection<dim, spacedim>
1235 &fe_collection = dof_handler.get_fe_collection();
1261 const unsigned int dominating_fe_index =
1262 fe_collection.find_dominating_fe_extended(
1263 fe_ind_face_subface, 1);
1268 "Could not find a least face dominating FE."));
1271 dof_handler.get_fe(dominating_fe_index);
1276 cell->get_fe().dofs_per_face,
1279 ensure_existence_of_face_matrix(
1282 face_interpolation_matrices[dominating_fe_index]
1283 [cell->active_fe_index()]);
1287 ensure_existence_of_master_dof_mask(
1290 (*face_interpolation_matrices
1291 [dominating_fe_index][cell->active_fe_index()]),
1292 master_dof_masks[dominating_fe_index]
1293 [cell->active_fe_index()]);
1295 ensure_existence_of_split_face_matrix(
1296 *face_interpolation_matrices[dominating_fe_index]
1297 [cell->active_fe_index()],
1298 (*master_dof_masks[dominating_fe_index]
1299 [cell->active_fe_index()]),
1300 split_face_interpolation_matrices
1301 [dominating_fe_index][cell->active_fe_index()]);
1304 &restrict_mother_to_virtual_master_inv =
1305 (split_face_interpolation_matrices
1306 [dominating_fe_index][cell->active_fe_index()]
1310 &restrict_mother_to_virtual_slave =
1311 (split_face_interpolation_matrices
1312 [dominating_fe_index][cell->active_fe_index()]
1317 constraint_matrix.
reinit(cell->get_fe().dofs_per_face -
1320 restrict_mother_to_virtual_slave.
mmult(
1322 restrict_mother_to_virtual_master_inv);
1326 scratch_dofs.resize(cell->get_fe().dofs_per_face);
1327 cell->face(face)->get_dof_indices(
1328 scratch_dofs, cell->active_fe_index());
1331 master_dofs.clear();
1333 for (
unsigned int i = 0;
1334 i < cell->get_fe().dofs_per_face;
1336 if ((*master_dof_masks[dominating_fe_index]
1337 [cell->active_fe_index()])[i] ==
1339 master_dofs.push_back(scratch_dofs[i]);
1341 slave_dofs.push_back(scratch_dofs[i]);
1346 cell->get_fe().dofs_per_face -
1349 filter_constraints(master_dofs,
1358 for (
unsigned int sf = 0;
1359 sf < cell->face(face)->n_children();
1364 if (cell->neighbor_child_on_subface(face, sf)
1365 ->is_artificial() ||
1366 (dim == 2 && cell->is_ghost() &&
1367 cell->neighbor_child_on_subface(face, sf)
1373 ->n_active_fe_indices() == 1,
1376 const unsigned int subface_fe_index =
1377 cell->face(face)->child(sf)->nth_active_fe_index(
1380 dof_handler.get_fe(subface_fe_index);
1387 ensure_existence_of_subface_matrix(
1391 subface_interpolation_matrices
1392 [dominating_fe_index][subface_fe_index][sf]);
1395 &restrict_subface_to_virtual = *(
1396 subface_interpolation_matrices
1397 [dominating_fe_index][subface_fe_index][sf]);
1399 constraint_matrix.
reinit(
1403 restrict_subface_to_virtual.
mmult(
1405 restrict_mother_to_virtual_master_inv);
1408 cell->face(face)->child(sf)->get_dof_indices(
1409 slave_dofs, subface_fe_index);
1411 filter_constraints(master_dofs,
1434 Assert(cell->face(face)->fe_index_is_active(
1435 cell->active_fe_index()) ==
true,
1442 if (!cell->at_boundary(face) &&
1443 cell->neighbor(face)->is_artificial())
1450 !cell->face(face)->at_boundary() &&
1451 (cell->neighbor(face)->active_fe_index() !=
1452 cell->active_fe_index()) &&
1453 (!cell->face(face)->has_children() &&
1454 !cell->neighbor_is_coarser(face)))
1456 const typename DoFHandlerType::level_cell_iterator
1457 neighbor = cell->neighbor(face);
1461 cell->get_fe().compare_for_domination(neighbor->get_fe(),
1468 master_dofs.resize(cell->get_fe().dofs_per_face);
1469 cell->face(face)->get_dof_indices(
1470 master_dofs, cell->active_fe_index());
1475 if (master_dofs.size() == 0)
1478 slave_dofs.resize(neighbor->get_fe().dofs_per_face);
1479 cell->face(face)->get_dof_indices(
1480 slave_dofs, neighbor->active_fe_index());
1484 ensure_existence_of_face_matrix(
1487 face_interpolation_matrices
1488 [cell->active_fe_index()]
1489 [neighbor->active_fe_index()]);
1495 *(face_interpolation_matrices
1496 [cell->active_fe_index()]
1497 [neighbor->active_fe_index()]),
1540 if (cell < neighbor)
1553 const unsigned int this_fe_index =
1554 cell->active_fe_index();
1555 const unsigned int neighbor_fe_index =
1556 neighbor->active_fe_index();
1557 std::set<unsigned int> fes;
1558 fes.insert(this_fe_index);
1559 fes.insert(neighbor_fe_index);
1560 const ::hp::FECollection<dim, spacedim>
1561 &fe_collection = dof_handler.get_fe_collection();
1563 const unsigned int dominating_fe_index =
1564 fe_collection.find_dominating_fe_extended(
1568 dominating_fe_index !=
1571 "Could not find the dominating FE for " +
1572 cell->get_fe().get_name() +
" and " +
1573 neighbor->get_fe().get_name() +
1574 " inside FECollection."));
1577 fe_collection[dominating_fe_index];
1585 cell->get_fe().dofs_per_face,
1588 ensure_existence_of_face_matrix(
1591 face_interpolation_matrices
1592 [dominating_fe_index][cell->active_fe_index()]);
1596 ensure_existence_of_master_dof_mask(
1599 (*face_interpolation_matrices
1600 [dominating_fe_index]
1601 [cell->active_fe_index()]),
1602 master_dof_masks[dominating_fe_index]
1603 [cell->active_fe_index()]);
1605 ensure_existence_of_split_face_matrix(
1606 *face_interpolation_matrices
1607 [dominating_fe_index][cell->active_fe_index()],
1608 (*master_dof_masks[dominating_fe_index]
1609 [cell->active_fe_index()]),
1610 split_face_interpolation_matrices
1611 [dominating_fe_index][cell->active_fe_index()]);
1614 double> &restrict_mother_to_virtual_master_inv =
1615 (split_face_interpolation_matrices
1616 [dominating_fe_index][cell->active_fe_index()]
1620 double> &restrict_mother_to_virtual_slave =
1621 (split_face_interpolation_matrices
1622 [dominating_fe_index][cell->active_fe_index()]
1627 constraint_matrix.
reinit(
1628 cell->get_fe().dofs_per_face -
1631 restrict_mother_to_virtual_slave.mmult(
1633 restrict_mother_to_virtual_master_inv);
1637 scratch_dofs.resize(cell->get_fe().dofs_per_face);
1638 cell->face(face)->get_dof_indices(
1639 scratch_dofs, cell->active_fe_index());
1642 master_dofs.clear();
1644 for (
unsigned int i = 0;
1645 i < cell->get_fe().dofs_per_face;
1647 if ((*master_dof_masks[dominating_fe_index]
1648 [cell->active_fe_index()])
1650 master_dofs.push_back(scratch_dofs[i]);
1652 slave_dofs.push_back(scratch_dofs[i]);
1657 cell->get_fe().dofs_per_face -
1660 filter_constraints(master_dofs,
1669 neighbor->get_fe().dofs_per_face,
1672 ensure_existence_of_face_matrix(
1675 face_interpolation_matrices
1676 [dominating_fe_index]
1677 [neighbor->active_fe_index()]);
1680 &restrict_secondface_to_virtual =
1681 *(face_interpolation_matrices
1682 [dominating_fe_index]
1683 [neighbor->active_fe_index()]);
1685 constraint_matrix.
reinit(
1686 neighbor->get_fe().dofs_per_face,
1689 restrict_secondface_to_virtual.
mmult(
1691 restrict_mother_to_virtual_master_inv);
1693 slave_dofs.resize(neighbor->get_fe().dofs_per_face);
1694 cell->face(face)->get_dof_indices(
1695 slave_dofs, neighbor->active_fe_index());
1697 filter_constraints(master_dofs,
1723 template <
typename DoFHandlerType,
typename number>
1732 if (dof_handler.get_fe_collection().hp_constraints_are_implemented())
1738 std::integral_constant<int, DoFHandlerType::dimension>());
1770 template <
typename FaceIterator,
typename number>
1772 set_periodicity_constraints(
1773 const FaceIterator & face_1,
1778 const bool face_orientation,
1779 const bool face_flip,
1780 const bool face_rotation,
1781 const number periodicity_factor)
1783 static const int dim = FaceIterator::AccessorType::dimension;
1784 static const int spacedim = FaceIterator::AccessorType::space_dimension;
1794 if (face_2->has_children())
1796 Assert(face_2->n_children() ==
1800 const unsigned int dofs_per_face =
1801 face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
1806 for (
unsigned int c = 0; c < face_2->n_children(); ++c)
1811 const auto &fe = face_1->get_fe(face_1->nth_active_fe_index(0));
1812 fe.get_subface_interpolation_matrix(fe, c, subface_interpolation);
1813 subface_interpolation.mmult(child_transformation, transformation);
1815 set_periodicity_constraints(face_1,
1817 child_transformation,
1823 periodicity_factor);
1833 const unsigned int face_1_index = face_1->nth_active_fe_index(0);
1834 const unsigned int face_2_index = face_2->nth_active_fe_index(0);
1835 Assert(face_1->get_fe(face_1_index) == face_2->get_fe(face_2_index),
1837 "Matching periodic cells need to use the same finite element"));
1843 "The number of components in the mask has to be either "
1844 "zero or equal to the number of components in the finite "
1849 std::vector<types::global_dof_index> dofs_1(dofs_per_face);
1850 std::vector<types::global_dof_index> dofs_2(dofs_per_face);
1852 face_1->get_dof_indices(dofs_1, face_1_index);
1853 face_2->get_dof_indices(dofs_2, face_2_index);
1871 for (
unsigned int i = 0; i < dofs_per_face; i++)
1893 std::map<unsigned int, unsigned int> cell_to_rotated_face_index;
1896 for (
unsigned int i = 0; i < dofs_per_face; ++i)
1898 const unsigned int cell_index =
1907 cell_to_rotated_face_index[cell_index] = i;
1915 for (
unsigned int i = 0; i < dofs_per_face; ++i)
1935 bool is_identity_constrained =
false;
1937 number constraint_factor = periodicity_factor;
1939 constexpr
double eps = 1.e-13;
1940 for (
unsigned int jj = 0; jj < dofs_per_face; ++jj)
1942 const auto entry = transformation(i, jj);
1943 if (std::abs(entry) >
eps)
1945 if (is_identity_constrained)
1950 is_identity_constrained =
false;
1953 is_identity_constrained =
true;
1955 constraint_factor = entry * periodicity_factor;
1964 if (!is_identity_constrained)
1972 affine_constraints.
add_line(dofs_2[i]);
1974 for (
unsigned int jj = 0; jj < dofs_per_face; ++jj)
1978 const unsigned int j =
1980 jj, 0, face_orientation, face_flip, face_rotation)];
1982 if (std::abs(transformation(i, jj)) >
eps)
1985 transformation(i, jj));
1996 const unsigned int j =
1998 target, 0, face_orientation, face_flip, face_rotation)];
2000 auto dof_left = dofs_1[j];
2001 auto dof_right = dofs_2[i];
2007 (dof_left < dof_right &&
2011 constraint_factor = 1. / constraint_factor;
2027 bool constraints_are_cyclic =
true;
2028 number cycle_constraint_factor = constraint_factor;
2030 for (
auto test_dof = dof_right; test_dof != dof_left;)
2034 constraints_are_cyclic =
false;
2038 const auto &constraint_entries =
2040 if (constraint_entries.size() == 1)
2042 test_dof = constraint_entries[0].first;
2043 cycle_constraint_factor *= constraint_entries[0].second;
2047 constraints_are_cyclic =
false;
2062 if (constraints_are_cyclic)
2064 if (std::abs(cycle_constraint_factor - 1.) >
eps)
2065 affine_constraints.
add_line(dof_left);
2069 affine_constraints.
add_line(dof_left);
2094 std::abs(constraint_factor) < 1e10,
2096 "The periodicity constraint is too large. The parameter periodicity_factor might be too large or too small."));
2108 template <
int dim,
int spacedim>
2110 compute_transformation(
2113 const std::vector<unsigned int> & first_vector_components)
2119 if (
matrix.m() == n_dofs_per_face)
2126 if (first_vector_components.empty() &&
matrix.m() == 0)
2139 quadrature(fe.get_unit_face_support_points());
2143 using DoFTuple = std::array<
unsigned int, spacedim>;
2148 for (
unsigned int i = 0; i < n_dofs_per_face; ++i)
2150 std::vector<unsigned int>::const_iterator comp_it =
2151 std::find(first_vector_components.begin(),
2152 first_vector_components.end(),
2154 if (comp_it != first_vector_components.end())
2156 const unsigned int first_vector_component = *comp_it;
2159 DoFTuple vector_dofs;
2161 unsigned int n_found = 1;
2166 "Error: the finite element does not have enough components "
2167 "to define rotated periodic boundaries."));
2169 for (
unsigned int k = 0; k < n_dofs_per_face; ++k)
2170 if ((k != i) && (quadrature.point(k) == quadrature.point(i)) &&
2172 first_vector_component) &&
2174 first_vector_component + spacedim))
2177 first_vector_component] = k;
2185 for (
int i = 0; i < spacedim; ++i)
2187 transformation[vector_dofs[i]][vector_dofs[i]] = 0.;
2188 for (
int j = 0; j < spacedim; ++j)
2189 transformation[vector_dofs[i]][vector_dofs[j]] =
2194 return transformation;
2202 template <
typename FaceIterator,
typename number>
2205 const FaceIterator & face_1,
2209 const bool face_orientation,
2210 const bool face_flip,
2211 const bool face_rotation,
2213 const std::vector<unsigned int> & first_vector_components,
2214 const number periodicity_factor)
2216 static const int dim = FaceIterator::AccessorType::dimension;
2217 static const int spacedim = FaceIterator::AccessorType::space_dimension;
2219 Assert((dim != 1) || (face_orientation ==
true && face_flip ==
false &&
2220 face_rotation ==
false),
2222 "(face_orientation, face_flip, face_rotation) "
2223 "is invalid for 1D"));
2225 Assert((dim != 2) || (face_orientation ==
true && face_rotation ==
false),
2227 "(face_orientation, face_flip, face_rotation) "
2228 "is invalid for 2D"));
2231 ExcMessage(
"face_1 and face_2 are equal! Cannot constrain DoFs "
2232 "on the very same face"));
2234 Assert(face_1->at_boundary() && face_2->at_boundary(),
2235 ExcMessage(
"Faces for periodicity constraints must be on the "
2239 ExcMessage(
"The supplied (rotation or interpolation) matrix must "
2240 "be a square matrix"));
2242 Assert(first_vector_components.empty() ||
matrix.m() == spacedim,
2243 ExcMessage(
"first_vector_components is nonempty, so matrix must "
2244 "be a rotation matrix exactly of size spacedim"));
2247 if (!face_1->has_children())
2250 const unsigned int n_dofs_per_face =
2251 face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
2254 (first_vector_components.empty() &&
2255 matrix.m() == n_dofs_per_face) ||
2256 (!first_vector_components.empty() &&
matrix.m() == spacedim),
2258 "The matrix must have either size 0 or spacedim "
2259 "(if first_vector_components is nonempty) "
2260 "or the size must be equal to the # of DoFs on the face "
2261 "(if first_vector_components is empty)."));
2264 if (!face_2->has_children())
2267 const unsigned int n_dofs_per_face =
2268 face_2->get_fe(face_2->nth_active_fe_index(0)).dofs_per_face;
2271 (first_vector_components.empty() &&
2272 matrix.m() == n_dofs_per_face) ||
2273 (!first_vector_components.empty() &&
matrix.m() == spacedim),
2275 "The matrix must have either size 0 or spacedim "
2276 "(if first_vector_components is nonempty) "
2277 "or the size must be equal to the # of DoFs on the face "
2278 "(if first_vector_components is empty)."));
2285 static const int lookup_table_2d[2][2] = {
2291 static const int lookup_table_3d[2][2][2][4] = {
2315 if (face_1->has_children() && face_2->has_children())
2320 Assert(face_1->n_children() ==
2322 face_2->n_children() ==
2326 for (
unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face;
2334 j = lookup_table_2d[face_flip][i];
2337 j = lookup_table_3d[face_orientation][face_flip]
2352 first_vector_components,
2353 periodicity_factor);
2363 face_1->has_children() ?
2364 face_2->get_fe(face_2->nth_active_fe_index(0)) :
2365 face_1->get_fe(face_1->nth_active_fe_index(0));
2371 if (n_dofs_per_face == 0)
2375 compute_transformation(fe,
matrix, first_vector_components);
2377 if (!face_2->has_children())
2381 if (first_vector_components.empty() &&
matrix.m() == 0)
2383 set_periodicity_constraints(face_2,
2391 periodicity_factor);
2396 inverse.
invert(transformation);
2398 set_periodicity_constraints(face_2,
2406 periodicity_factor);
2419 set_periodicity_constraints(face_1,
2426 face_rotation ^ face_flip :
2429 periodicity_factor);
2436 template <
typename DoFHandlerType,
typename number>
2444 const std::vector<unsigned int> &first_vector_components,
2445 const number periodicity_factor)
2448 for (
auto &pair : periodic_faces)
2450 using FaceIterator =
typename DoFHandlerType::face_iterator;
2451 const FaceIterator face_1 = pair.cell[0]->face(pair.face_idx[0]);
2452 const FaceIterator face_2 = pair.cell[1]->face(pair.face_idx[1]);
2454 Assert(face_1->at_boundary() && face_2->at_boundary(),
2465 pair.orientation[0],
2466 pair.orientation[1],
2467 pair.orientation[2],
2469 first_vector_components,
2470 periodicity_factor);
2478 template <
typename DoFHandlerType,
typename number>
2483 const unsigned int direction,
2486 const number periodicity_factor)
2488 static const int space_dim = DoFHandlerType::space_dimension;
2493 ExcMessage(
"The boundary indicators b_id1 and b_id2 must be "
2494 "different to denote different boundaries."));
2502 dof_handler, b_id1, b_id2, direction, matched_faces);
2504 make_periodicity_constraints<DoFHandlerType>(matched_faces,
2507 std::vector<unsigned int>(),
2508 periodicity_factor);
2513 template <
typename DoFHandlerType,
typename number>
2517 const unsigned int direction,
2520 const number periodicity_factor)
2522 static const int dim = DoFHandlerType::dimension;
2523 static const int space_dim = DoFHandlerType::space_dimension;
2541 make_periodicity_constraints<DoFHandlerType>(matched_faces,
2544 std::vector<unsigned int>(),
2545 periodicity_factor);
2558 template <
int dim,
int spacedim>
2563 #ifdef DEAL_II_WITH_MPI
2564 std::vector<::LinearAlgebra::distributed::Vector<double>>
2579 template <
int dim,
int spacedim>
2581 compute_intergrid_weights_3(
2582 const typename ::DoFHandler<dim, spacedim>::active_cell_iterator
2586 const unsigned int coarse_component,
2589 & coarse_to_fine_grid_map,
2646 for (
unsigned int local_dof = 0; local_dof < copy_data.
dofs_per_cell;
2652 const unsigned int local_parameter_dof =
2661 coarse_to_fine_grid_map[cell]->set_dof_values_by_interpolation(
2662 parameter_dofs[local_parameter_dof],
2674 template <
int dim,
int spacedim>
2676 copy_intergrid_weights_3(
2677 const Assembler::CopyData<dim, spacedim> & copy_data,
2678 const unsigned int coarse_component,
2680 const std::vector<types::global_dof_index> &weight_mapping,
2681 const bool is_called_in_parallel,
2682 std::vector<std::map<types::global_dof_index, float>> &weights)
2684 unsigned int pos = 0;
2685 for (
unsigned int local_dof = 0; local_dof < copy_data.dofs_per_cell;
2712 i < copy_data.global_parameter_representation[pos].size();
2718 if (copy_data.global_parameter_representation[pos](i) != 0)
2721 wi = copy_data.parameter_dof_indices[local_dof],
2722 wj = weight_mapping[i];
2724 copy_data.global_parameter_representation[pos](i);
2727 else if (!is_called_in_parallel)
2732 Assert(copy_data.global_parameter_representation[pos](i) ==
2748 template <
int dim,
int spacedim>
2750 compute_intergrid_weights_2(
2751 const ::DoFHandler<dim, spacedim> &coarse_grid,
2752 const unsigned int coarse_component,
2754 & coarse_to_fine_grid_map,
2756 const std::vector<types::global_dof_index> &weight_mapping,
2757 std::vector<std::map<types::global_dof_index, float>> &weights)
2759 Assembler::Scratch scratch;
2760 Assembler::CopyData<dim, spacedim> copy_data;
2762 unsigned int n_interesting_dofs = 0;
2763 for (
unsigned int local_dof = 0;
2764 local_dof < coarse_grid.get_fe().dofs_per_cell;
2766 if (coarse_grid.get_fe().system_to_component_index(local_dof).first ==
2768 ++n_interesting_dofs;
2770 copy_data.global_parameter_representation.resize(n_interesting_dofs);
2772 bool is_called_in_parallel =
false;
2773 for (std::size_t i = 0;
2774 i < copy_data.global_parameter_representation.size();
2777 #ifdef DEAL_II_WITH_MPI
2778 MPI_Comm communicator = MPI_COMM_SELF;
2781 const typename ::parallel::TriangulationBase<dim,
2783 &tria =
dynamic_cast<const typename ::parallel::
2784 TriangulationBase<dim, spacedim> &
>(
2785 coarse_to_fine_grid_map.get_destination_grid()
2786 .get_triangulation());
2787 communicator = tria.get_communicator();
2788 is_called_in_parallel =
true;
2790 catch (std::bad_cast &)
2798 coarse_to_fine_grid_map.get_destination_grid(),
2799 locally_relevant_dofs);
2801 copy_data.global_parameter_representation[i].reinit(
2802 coarse_to_fine_grid_map.get_destination_grid()
2803 .locally_owned_dofs(),
2804 locally_relevant_dofs,
2808 copy_data.global_parameter_representation[i].reinit(n_fine_dofs);
2815 &coarse_to_fine_grid_map,
2816 ¶meter_dofs](
const typename ::DoFHandler<dim, spacedim>::
2817 active_cell_iterator & cell,
2818 const Assembler::Scratch & scratch_data,
2819 Assembler::CopyData<dim, spacedim> ©_data) {
2820 compute_intergrid_weights_3<dim, spacedim>(cell,
2824 coarse_grid.get_fe(),
2825 coarse_to_fine_grid_map,
2833 is_called_in_parallel,
2834 &weights](
const Assembler::CopyData<dim, spacedim> ©_data) {
2835 copy_intergrid_weights_3<dim, spacedim>(copy_data,
2837 coarse_grid.get_fe(),
2839 is_called_in_parallel,
2850 #ifdef DEAL_II_WITH_MPI
2851 for (std::size_t i = 0;
2852 i < copy_data.global_parameter_representation.size();
2854 copy_data.global_parameter_representation[i].update_ghost_values();
2865 template <
int dim,
int spacedim>
2867 compute_intergrid_weights_1(
2868 const ::DoFHandler<dim, spacedim> &coarse_grid,
2869 const unsigned int coarse_component,
2870 const ::DoFHandler<dim, spacedim> &fine_grid,
2871 const unsigned int fine_component,
2873 &coarse_to_fine_grid_map,
2874 std::vector<std::map<types::global_dof_index, float>> &weights,
2875 std::vector<types::global_dof_index> & weight_mapping)
2879 &fine_fe = fine_grid.get_fe();
2883 n_fine_dofs = fine_grid.n_dofs();
2886 const unsigned int fine_dofs_per_cell = fine_fe.dofs_per_cell;
2890 const unsigned int coarse_dofs_per_cell_component =
2899 Assert(coarse_grid.get_triangulation().n_cells(0) ==
2900 fine_grid.get_triangulation().n_cells(0),
2904 Assert(&coarse_to_fine_grid_map.get_source_grid() == &coarse_grid,
2906 Assert(&coarse_to_fine_grid_map.get_destination_grid() == &fine_grid,
2917 fine_fe.base_element(
2918 fine_fe.component_to_base_index(fine_component).first),
2924 for (
const auto &cell : coarse_grid.active_cell_iterators())
2925 Assert(cell->level() <= coarse_to_fine_grid_map[cell]->level(),
2950 std::vector<::Vector<double>> parameter_dofs(
2951 coarse_dofs_per_cell_component,
2956 for (
unsigned int local_coarse_dof = 0;
2957 local_coarse_dof < coarse_dofs_per_cell_component;
2959 for (
unsigned int fine_dof = 0; fine_dof < fine_fe.dofs_per_cell;
2961 if (fine_fe.system_to_component_index(fine_dof) ==
2962 std::make_pair(fine_component, local_coarse_dof))
2964 parameter_dofs[local_coarse_dof](fine_dof) = 1.;
2971 unsigned int n_parameters_on_fine_grid = 0;
2975 std::vector<bool> dof_is_interesting(fine_grid.n_dofs(),
false);
2976 std::vector<types::global_dof_index> local_dof_indices(
2977 fine_fe.dofs_per_cell);
2979 for (
const auto &cell : fine_grid.active_cell_iterators())
2980 if (cell->is_locally_owned())
2982 cell->get_dof_indices(local_dof_indices);
2983 for (
unsigned int i = 0; i < fine_fe.dofs_per_cell; ++i)
2984 if (fine_fe.system_to_component_index(i).first ==
2986 dof_is_interesting[local_dof_indices[i]] =
true;
2989 n_parameters_on_fine_grid = std::count(dof_is_interesting.begin(),
2990 dof_is_interesting.end(),
2997 weights.resize(n_coarse_dofs);
2999 weight_mapping.clear();
3003 std::vector<types::global_dof_index> local_dof_indices(
3004 fine_fe.dofs_per_cell);
3005 unsigned int next_free_index = 0;
3006 for (
const auto &cell : fine_grid.active_cell_iterators())
3007 if (cell->is_locally_owned())
3009 cell->get_dof_indices(local_dof_indices);
3010 for (
unsigned int i = 0; i < fine_fe.dofs_per_cell; ++i)
3013 if ((fine_fe.system_to_component_index(i).first ==
3015 (weight_mapping[local_dof_indices[i]] ==
3018 weight_mapping[local_dof_indices[i]] = next_free_index;
3023 Assert(next_free_index == n_parameters_on_fine_grid,
3035 compute_intergrid_weights_2(coarse_grid,
3037 coarse_to_fine_grid_map,
3057 for (
unsigned int col = 0; col < n_parameters_on_fine_grid; ++col)
3061 if (weights[row].find(col) != weights[row].
end())
3062 sum += weights[row][col];
3070 return n_parameters_on_fine_grid;
3079 template <
int dim,
int spacedim>
3083 const unsigned int coarse_component,
3085 const unsigned int fine_component,
3109 std::vector<std::map<types::global_dof_index, float>> weights;
3115 std::vector<types::global_dof_index> weight_mapping;
3117 const unsigned int n_parameters_on_fine_grid =
3118 internal::compute_intergrid_weights_1(coarse_grid,
3122 coarse_to_fine_grid_map,
3125 (void)n_parameters_on_fine_grid;
3129 n_fine_dofs = fine_grid.
n_dofs();
3136 std::vector<bool> mask(coarse_grid.
get_fe(0).n_components(),
false);
3137 mask[coarse_component] =
true;
3139 coarse_dof_is_parameter =
3140 extract_dofs<DoFHandler<dim, spacedim>>(coarse_grid,
3153 std::vector<types::global_dof_index> representants(
3156 parameter_dof < n_coarse_dofs;
3158 if (coarse_dof_is_parameter.
is_element(parameter_dof))
3165 std::map<types::global_dof_index, float>::const_iterator i =
3166 weights[parameter_dof].begin();
3167 for (; i != weights[parameter_dof].end(); ++i)
3177 for (; global_dof < weight_mapping.size(); ++global_dof)
3178 if (weight_mapping[global_dof] ==
3184 representants[parameter_dof] = global_dof;
3200 std::vector<std::pair<types::global_dof_index, double>> constraint_line;
3219 std::map<types::global_dof_index, float>::const_iterator col_entry =
3221 for (; first_used_row < n_coarse_dofs; ++first_used_row)
3223 col_entry = weights[first_used_row].find(col);
3224 if (col_entry != weights[first_used_row].
end())
3228 Assert(col_entry != weights[first_used_row].
end(),
3231 if ((col_entry->second == 1) &&
3232 (representants[first_used_row] == global_dof))
3242 constraint_line.clear();
3244 row < n_coarse_dofs;
3247 const std::map<types::global_dof_index, float>::const_iterator j =
3248 weights[row].find(col);
3249 if ((j != weights[row].
end()) && (j->second != 0))
3250 constraint_line.emplace_back(representants[row], j->second);
3253 constraints.
add_entries(global_dof, constraint_line);
3259 template <
int dim,
int spacedim>
3263 const unsigned int coarse_component,
3265 const unsigned int fine_component,
3267 std::vector<std::map<types::global_dof_index, float>>
3268 &transfer_representation)
3290 std::vector<std::map<types::global_dof_index, float>> weights;
3296 std::vector<types::global_dof_index> weight_mapping;
3298 internal::compute_intergrid_weights_1(coarse_grid,
3302 coarse_to_fine_grid_map,
3308 std::count_if(weight_mapping.begin(),
3309 weight_mapping.end(),
3311 return dof != numbers::invalid_dof_index;
3315 std::vector<types::global_dof_index> inverse_weight_mapping(
3324 Assert((inverse_weight_mapping[parameter_dof] ==
3328 inverse_weight_mapping[parameter_dof] = i;
3335 transfer_representation.clear();
3336 transfer_representation.resize(n_rows);
3341 std::map<types::global_dof_index, float>::const_iterator j =
3343 for (; j != weights[i].end(); ++j)
3348 transfer_representation[p][i] = j->second;
3357 template <
int,
int>
class DoFHandlerType,
3361 const DoFHandlerType<dim, spacedim> &dof,
3367 ExcMessage(
"The number of components in the mask has to be either "
3368 "zero or equal to the number of components in the finite "
3377 std::vector<types::global_dof_index> face_dofs;
3380 std::vector<types::global_dof_index> cell_dofs;
3383 typename DoFHandlerType<dim, spacedim>::active_cell_iterator
3384 cell = dof.begin_active(),
3386 for (; cell != endc; ++cell)
3387 if (!cell->is_artificial() && cell->at_boundary())
3393 cell->get_dof_indices(cell_dofs);
3397 const typename DoFHandlerType<dim, spacedim>::face_iterator face =
3398 cell->face(face_no);
3402 if (face->at_boundary() &&
3408 face->get_dof_indices(face_dofs, cell->active_fe_index());
3416 const std::vector<types::global_dof_index>::iterator
3417 it_index_on_cell = std::find(cell_dofs.begin(),
3420 Assert(it_index_on_cell != cell_dofs.end(),
3422 const unsigned int index_on_cell =
3423 std::distance(cell_dofs.begin(), it_index_on_cell);
3425 cell->get_fe().get_nonzero_components(index_on_cell);
3428 if (nonzero_component_array[c] && component_mask[c])
3435 zero_boundary_constraints.
add_line(face_dof);
3446 template <
int,
int>
class DoFHandlerType,
3450 const DoFHandlerType<dim, spacedim> &dof,
3456 zero_boundary_constraints,
3467 #include "dof_tools_constraints.inst"