59 template <
typename DoFHandlerType,
60 typename SparsityPatternType,
64 SparsityPatternType & sparsity,
66 const bool keep_constrained_dofs,
72 Assert(sparsity.n_rows() == n_dofs,
74 Assert(sparsity.n_cols() == n_dofs,
80 Assert((dof.get_triangulation().locally_owned_subdomain() ==
84 dof.get_triangulation().locally_owned_subdomain()),
86 "For parallel::distributed::Triangulation objects and "
87 "associated DoF handler objects, asking for any subdomain other "
88 "than the locally owned one does not make sense."));
90 std::vector<types::global_dof_index> dofs_on_this_cell;
92 typename DoFHandlerType::active_cell_iterator cell = dof.begin_active(),
98 for (; cell != endc; ++cell)
101 cell->is_locally_owned())
103 const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
104 dofs_on_this_cell.resize(dofs_per_cell);
105 cell->get_dof_indices(dofs_on_this_cell);
112 keep_constrained_dofs);
118 template <
typename DoFHandlerType,
119 typename SparsityPatternType,
124 SparsityPatternType & sparsity,
126 const bool keep_constrained_dofs,
132 Assert(sparsity.n_rows() == n_dofs,
134 Assert(sparsity.n_cols() == n_dofs,
136 Assert(couplings.n_rows() == dof.get_fe(0).n_components(),
138 dof.get_fe(0).n_components()));
139 Assert(couplings.n_cols() == dof.get_fe(0).n_components(),
141 dof.get_fe(0).n_components()));
146 Assert((dof.get_triangulation().locally_owned_subdomain() ==
150 dof.get_triangulation().locally_owned_subdomain()),
152 "For parallel::distributed::Triangulation objects and "
153 "associated DoF handler objects, asking for any subdomain other "
154 "than the locally owned one does not make sense."));
157 DoFHandlerType::space_dimension> &fe_collection =
158 dof.get_fe_collection();
160 const std::vector<Table<2, Coupling>> dof_mask
165 std::vector<Table<2, bool>> bool_dof_mask(fe_collection.size());
166 for (
unsigned int f = 0; f < fe_collection.size(); ++f)
168 bool_dof_mask[f].reinit(
170 fe_collection[f].dofs_per_cell));
171 bool_dof_mask[f].fill(
false);
172 for (
unsigned int i = 0; i < fe_collection[f].dofs_per_cell; ++i)
173 for (
unsigned int j = 0; j < fe_collection[f].dofs_per_cell; ++j)
174 if (dof_mask[f](i, j) !=
none)
175 bool_dof_mask[f](i, j) =
true;
178 std::vector<types::global_dof_index> dofs_on_this_cell(
179 fe_collection.max_dofs_per_cell());
180 typename DoFHandlerType::active_cell_iterator cell = dof.begin_active(),
186 for (; cell != endc; ++cell)
189 cell->is_locally_owned())
191 const unsigned int fe_index = cell->active_fe_index();
192 const unsigned int dofs_per_cell =
193 fe_collection[fe_index].dofs_per_cell;
195 dofs_on_this_cell.resize(dofs_per_cell);
196 cell->get_dof_indices(dofs_on_this_cell);
204 keep_constrained_dofs,
205 bool_dof_mask[fe_index]);
211 template <
typename DoFHandlerType,
typename SparsityPatternType>
214 const DoFHandlerType &dof_col,
215 SparsityPatternType & sparsity)
222 Assert(sparsity.n_rows() == n_dofs_row,
224 Assert(sparsity.n_cols() == n_dofs_col,
232 constexpr
int dim = DoFHandlerType::dimension;
233 constexpr
int spacedim = DoFHandlerType::space_dimension;
235 &dof_row.get_triangulation()) !=
nullptr ||
237 &dof_col.get_triangulation()) !=
nullptr)
239 Assert(&dof_row.get_triangulation() == &dof_col.get_triangulation(),
240 ExcMessage(
"This function can only be used with with parallel "
241 "Triangulations when the Triangulations are equal."));
246 using cell_iterator =
typename DoFHandlerType::cell_iterator;
247 std::list<std::pair<cell_iterator, cell_iterator>> cell_list =
250 #ifdef DEAL_II_WITH_MPI
255 &dof_row.get_triangulation()) !=
nullptr ||
257 &dof_col.get_triangulation()) !=
nullptr)
260 dof_row.get_triangulation().locally_owned_subdomain();
261 Assert(this_subdomain_id ==
262 dof_col.get_triangulation().locally_owned_subdomain(),
268 [=](
const std::pair<cell_iterator, cell_iterator> &pair) {
269 return pair.first->subdomain_id() != this_subdomain_id ||
270 pair.second->subdomain_id() != this_subdomain_id;
276 for (
const auto &cell_pair : cell_list)
278 const cell_iterator cell_row = cell_pair.first;
279 const cell_iterator cell_col = cell_pair.second;
281 if (cell_row->is_active() && cell_col->is_active())
283 const unsigned int dofs_per_cell_row =
284 cell_row->get_fe().dofs_per_cell;
285 const unsigned int dofs_per_cell_col =
286 cell_col->get_fe().dofs_per_cell;
287 std::vector<types::global_dof_index> local_dof_indices_row(
289 std::vector<types::global_dof_index> local_dof_indices_col(
291 cell_row->get_dof_indices(local_dof_indices_row);
292 cell_col->get_dof_indices(local_dof_indices_col);
293 for (
unsigned int i = 0; i < dofs_per_cell_row; ++i)
294 sparsity.add_entries(local_dof_indices_row[i],
295 local_dof_indices_col.begin(),
296 local_dof_indices_col.end());
298 else if (cell_row->has_children())
300 const std::vector<typename DoFHandlerType::active_cell_iterator>
302 GridTools::get_active_child_cells<DoFHandlerType>(cell_row);
303 for (
unsigned int i = 0; i < child_cells.size(); i++)
305 const typename DoFHandlerType::cell_iterator cell_row_child =
307 const unsigned int dofs_per_cell_row =
308 cell_row_child->get_fe().dofs_per_cell;
309 const unsigned int dofs_per_cell_col =
310 cell_col->get_fe().dofs_per_cell;
311 std::vector<types::global_dof_index> local_dof_indices_row(
313 std::vector<types::global_dof_index> local_dof_indices_col(
315 cell_row_child->get_dof_indices(local_dof_indices_row);
316 cell_col->get_dof_indices(local_dof_indices_col);
317 for (
unsigned int r = 0; r < dofs_per_cell_row; ++r)
318 sparsity.add_entries(local_dof_indices_row[r],
319 local_dof_indices_col.begin(),
320 local_dof_indices_col.end());
325 std::vector<typename DoFHandlerType::active_cell_iterator>
327 GridTools::get_active_child_cells<DoFHandlerType>(cell_col);
328 for (
unsigned int i = 0; i < child_cells.size(); i++)
330 const typename DoFHandlerType::active_cell_iterator
331 cell_col_child = child_cells[i];
332 const unsigned int dofs_per_cell_row =
333 cell_row->get_fe().dofs_per_cell;
334 const unsigned int dofs_per_cell_col =
335 cell_col_child->get_fe().dofs_per_cell;
336 std::vector<types::global_dof_index> local_dof_indices_row(
338 std::vector<types::global_dof_index> local_dof_indices_col(
340 cell_row->get_dof_indices(local_dof_indices_row);
341 cell_col_child->get_dof_indices(local_dof_indices_col);
342 for (
unsigned int r = 0; r < dofs_per_cell_row; ++r)
343 sparsity.add_entries(local_dof_indices_row[r],
344 local_dof_indices_col.begin(),
345 local_dof_indices_col.end());
353 template <
typename DoFHandlerType,
typename SparsityPatternType>
356 const DoFHandlerType & dof,
357 const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
358 SparsityPatternType & sparsity)
360 if (DoFHandlerType::dimension == 1)
367 boundary_ids[0] =
nullptr;
368 boundary_ids[1] =
nullptr;
369 make_boundary_sparsity_pattern<DoFHandlerType, SparsityPatternType>(
370 dof, boundary_ids, dof_to_boundary_mapping, sparsity);
381 if (sparsity.n_rows() != 0)
391 std::vector<types::global_dof_index> dofs_on_this_face;
399 typename DoFHandlerType::active_cell_iterator cell = dof.begin_active(),
401 for (; cell != endc; ++cell)
402 for (
const unsigned int f :
404 if (cell->at_boundary(f))
406 const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
407 dofs_on_this_face.resize(dofs_per_face);
408 cell->face(f)->get_dof_indices(dofs_on_this_face,
409 cell->active_fe_index());
412 for (
unsigned int i = 0; i < dofs_per_face; ++i)
413 for (
unsigned int j = 0; j < dofs_per_face; ++j)
414 sparsity.add(dof_to_boundary_mapping[dofs_on_this_face[i]],
415 dof_to_boundary_mapping[dofs_on_this_face[j]]);
421 template <
typename DoFHandlerType,
422 typename SparsityPatternType,
426 const DoFHandlerType &dof,
430 const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
431 SparsityPatternType & sparsity)
433 if (DoFHandlerType::dimension == 1)
436 for (
unsigned int direction = 0; direction < 2; ++direction)
439 if (boundary_ids.find(direction) == boundary_ids.end())
444 typename DoFHandlerType::level_cell_iterator cell = dof.begin(0);
445 while (!cell->at_boundary(direction))
446 cell = cell->neighbor(direction);
447 while (!cell->is_active())
448 cell = cell->child(direction);
450 const unsigned int dofs_per_vertex = cell->get_fe().dofs_per_vertex;
451 std::vector<types::global_dof_index> boundary_dof_boundary_indices(
455 for (
unsigned int i = 0; i < dofs_per_vertex; ++i)
456 boundary_dof_boundary_indices[i] =
457 dof_to_boundary_mapping[cell->vertex_dof_index(direction, i)];
459 for (
unsigned int i = 0; i < dofs_per_vertex; ++i)
460 sparsity.add_entries(boundary_dof_boundary_indices[i],
461 boundary_dof_boundary_indices.begin(),
462 boundary_dof_boundary_indices.end());
474 Assert(sparsity.n_rows() == dof.n_boundary_dofs(boundary_ids),
476 dof.n_boundary_dofs(boundary_ids)));
477 Assert(sparsity.n_cols() == dof.n_boundary_dofs(boundary_ids),
479 dof.n_boundary_dofs(boundary_ids)));
481 if (sparsity.n_rows() != 0)
491 std::vector<types::global_dof_index> dofs_on_this_face;
493 typename DoFHandlerType::active_cell_iterator cell = dof.begin_active(),
495 for (; cell != endc; ++cell)
496 for (
const unsigned int f :
498 if (boundary_ids.find(cell->face(f)->boundary_id()) !=
501 const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
502 dofs_on_this_face.resize(dofs_per_face);
503 cell->face(f)->get_dof_indices(dofs_on_this_face,
504 cell->active_fe_index());
507 for (
unsigned int i = 0; i < dofs_per_face; ++i)
508 for (
unsigned int j = 0; j < dofs_per_face; ++j)
509 sparsity.add(dof_to_boundary_mapping[dofs_on_this_face[i]],
510 dof_to_boundary_mapping[dofs_on_this_face[j]]);
516 template <
typename DoFHandlerType,
517 typename SparsityPatternType,
521 SparsityPatternType & sparsity,
523 const bool keep_constrained_dofs,
538 Assert((dof.get_triangulation().locally_owned_subdomain() ==
542 dof.get_triangulation().locally_owned_subdomain()),
544 "For parallel::distributed::Triangulation objects and "
545 "associated DoF handler objects, asking for any subdomain other "
546 "than the locally owned one does not make sense."));
548 std::vector<types::global_dof_index> dofs_on_this_cell;
549 std::vector<types::global_dof_index> dofs_on_other_cell;
552 typename DoFHandlerType::active_cell_iterator cell = dof.begin_active(),
563 for (; cell != endc; ++cell)
566 cell->is_locally_owned())
568 const unsigned int n_dofs_on_this_cell = cell->get_fe().dofs_per_cell;
569 dofs_on_this_cell.resize(n_dofs_on_this_cell);
570 cell->get_dof_indices(dofs_on_this_cell);
577 keep_constrained_dofs);
579 for (
const unsigned int face :
582 typename DoFHandlerType::face_iterator cell_face =
584 const bool periodic_neighbor = cell->has_periodic_neighbor(face);
585 if (!cell->at_boundary(face) || periodic_neighbor)
587 typename DoFHandlerType::level_cell_iterator neighbor =
588 cell->neighbor_or_periodic_neighbor(face);
594 if (DoFHandlerType::dimension == 1)
595 while (neighbor->has_children())
596 neighbor = neighbor->child(face == 0 ? 1 : 0);
598 if (neighbor->has_children())
600 for (
unsigned int sub_nr = 0;
601 sub_nr != cell_face->number_of_children();
604 const typename DoFHandlerType::level_cell_iterator
607 cell->periodic_neighbor_child_on_subface(
609 cell->neighbor_child_on_subface(face, sub_nr);
611 const unsigned int n_dofs_on_neighbor =
612 sub_neighbor->get_fe().dofs_per_cell;
613 dofs_on_other_cell.resize(n_dofs_on_neighbor);
614 sub_neighbor->get_dof_indices(dofs_on_other_cell);
620 keep_constrained_dofs);
625 keep_constrained_dofs);
629 if (sub_neighbor->subdomain_id() !=
630 cell->subdomain_id())
634 keep_constrained_dofs);
641 if ((!periodic_neighbor &&
642 cell->neighbor_is_coarser(face)) ||
643 (periodic_neighbor &&
644 cell->periodic_neighbor_is_coarser(face)))
645 if (neighbor->subdomain_id() == cell->subdomain_id())
648 const unsigned int n_dofs_on_neighbor =
649 neighbor->get_fe().dofs_per_cell;
650 dofs_on_other_cell.resize(n_dofs_on_neighbor);
652 neighbor->get_dof_indices(dofs_on_other_cell);
658 keep_constrained_dofs);
664 if (!cell->neighbor_or_periodic_neighbor(face)
666 (neighbor->subdomain_id() != cell->subdomain_id()))
672 keep_constrained_dofs);
673 if (neighbor->subdomain_id() != cell->subdomain_id())
677 keep_constrained_dofs);
687 template <
typename DoFHandlerType,
typename SparsityPatternType>
690 SparsityPatternType & sparsity)
696 template <
int dim,
int spacedim>
713 for (
unsigned int i = 0; i < n_dofs; ++i)
715 const unsigned int ii =
721 for (
unsigned int j = 0; j < n_dofs; ++j)
723 const unsigned int jj =
729 dof_couplings(i, j) = component_couplings(ii, jj);
732 return dof_couplings;
737 template <
int dim,
int spacedim>
738 std::vector<Table<2, Coupling>>
743 std::vector<Table<2, Coupling>> return_value(fe.
size());
744 for (
unsigned int i = 0; i < fe.
size(); ++i)
761 typename SparsityPatternType,
766 SparsityPatternType & sparsity,
768 const bool keep_constrained_dofs,
774 const unsigned int)> &face_has_flux_coupling)
778 std::vector<types::global_dof_index> dofs_on_this_cell(
780 std::vector<types::global_dof_index> dofs_on_other_cell(
796 bool_int_dof_mask.fill(
false);
799 if (int_dof_mask(i, j) != none)
800 bool_int_dof_mask(i, j) =
true;
805 for (; cell != endc; ++cell)
808 cell->is_locally_owned())
810 cell->get_dof_indices(dofs_on_this_cell);
814 keep_constrained_dofs,
817 for (
const unsigned int face_n :
821 cell_face = cell->face(face_n);
823 const bool periodic_neighbor =
824 cell->has_periodic_neighbor(face_n);
826 if (cell->at_boundary(face_n) && (!periodic_neighbor))
830 const bool i_non_zero_i = support_on_face(i, face_n);
833 const bool j_non_zero_i =
834 support_on_face(j, face_n);
836 if (flux_dof_mask(i, j) ==
always ||
837 (flux_dof_mask(i, j) ==
nonzero &&
838 i_non_zero_i && j_non_zero_i))
839 sparsity.add(dofs_on_this_cell[i],
840 dofs_on_this_cell[j]);
846 if (!face_has_flux_coupling(cell, face_n))
850 neighbor = cell->neighbor_or_periodic_neighbor(face_n);
855 if (neighbor->level() == cell->level() &&
856 neighbor->index() > cell->index() &&
857 neighbor->is_active() && neighbor->is_locally_owned())
870 if (neighbor->level() != cell->level() &&
871 ((!periodic_neighbor &&
872 !cell->neighbor_is_coarser(face_n)) ||
873 (periodic_neighbor &&
874 !cell->periodic_neighbor_is_coarser(face_n))) &&
875 neighbor->is_locally_owned())
878 const unsigned int neighbor_face_n =
880 cell->periodic_neighbor_face_no(face_n) :
881 cell->neighbor_face_no(face_n);
890 while (neighbor->has_children())
891 neighbor = neighbor->child(face_n == 0 ? 1 : 0);
893 if (neighbor->has_children())
895 for (
unsigned int sub_nr = 0;
896 sub_nr != cell_face->n_children();
900 level_cell_iterator sub_neighbor =
902 cell->periodic_neighbor_child_on_subface(
904 cell->neighbor_child_on_subface(face_n,
907 sub_neighbor->get_dof_indices(dofs_on_other_cell);
911 const bool i_non_zero_i =
912 support_on_face(i, face_n);
913 const bool i_non_zero_e =
914 support_on_face(i, neighbor_face_n);
918 const bool j_non_zero_i =
919 support_on_face(j, face_n);
920 const bool j_non_zero_e =
921 support_on_face(j, neighbor_face_n);
923 if (flux_dof_mask(i, j) ==
always)
925 sparsity.add(dofs_on_this_cell[i],
926 dofs_on_other_cell[j]);
927 sparsity.add(dofs_on_other_cell[i],
928 dofs_on_this_cell[j]);
929 sparsity.add(dofs_on_this_cell[i],
930 dofs_on_this_cell[j]);
931 sparsity.add(dofs_on_other_cell[i],
932 dofs_on_other_cell[j]);
934 else if (flux_dof_mask(i, j) ==
nonzero)
936 if (i_non_zero_i && j_non_zero_e)
937 sparsity.add(dofs_on_this_cell[i],
938 dofs_on_other_cell[j]);
939 if (i_non_zero_e && j_non_zero_i)
940 sparsity.add(dofs_on_other_cell[i],
941 dofs_on_this_cell[j]);
942 if (i_non_zero_i && j_non_zero_i)
943 sparsity.add(dofs_on_this_cell[i],
944 dofs_on_this_cell[j]);
945 if (i_non_zero_e && j_non_zero_e)
946 sparsity.add(dofs_on_other_cell[i],
947 dofs_on_other_cell[j]);
950 if (flux_dof_mask(j, i) ==
always)
952 sparsity.add(dofs_on_this_cell[j],
953 dofs_on_other_cell[i]);
954 sparsity.add(dofs_on_other_cell[j],
955 dofs_on_this_cell[i]);
956 sparsity.add(dofs_on_this_cell[j],
957 dofs_on_this_cell[i]);
958 sparsity.add(dofs_on_other_cell[j],
959 dofs_on_other_cell[i]);
961 else if (flux_dof_mask(j, i) ==
nonzero)
963 if (j_non_zero_i && i_non_zero_e)
964 sparsity.add(dofs_on_this_cell[j],
965 dofs_on_other_cell[i]);
966 if (j_non_zero_e && i_non_zero_i)
967 sparsity.add(dofs_on_other_cell[j],
968 dofs_on_this_cell[i]);
969 if (j_non_zero_i && i_non_zero_i)
970 sparsity.add(dofs_on_this_cell[j],
971 dofs_on_this_cell[i]);
972 if (j_non_zero_e && i_non_zero_e)
973 sparsity.add(dofs_on_other_cell[j],
974 dofs_on_other_cell[i]);
982 neighbor->get_dof_indices(dofs_on_other_cell);
985 const bool i_non_zero_i =
986 support_on_face(i, face_n);
987 const bool i_non_zero_e =
988 support_on_face(i, neighbor_face_n);
992 const bool j_non_zero_i =
993 support_on_face(j, face_n);
994 const bool j_non_zero_e =
995 support_on_face(j, neighbor_face_n);
996 if (flux_dof_mask(i, j) ==
always)
998 sparsity.add(dofs_on_this_cell[i],
999 dofs_on_other_cell[j]);
1000 sparsity.add(dofs_on_other_cell[i],
1001 dofs_on_this_cell[j]);
1002 sparsity.add(dofs_on_this_cell[i],
1003 dofs_on_this_cell[j]);
1004 sparsity.add(dofs_on_other_cell[i],
1005 dofs_on_other_cell[j]);
1007 if (flux_dof_mask(i, j) ==
nonzero)
1009 if (i_non_zero_i && j_non_zero_e)
1010 sparsity.add(dofs_on_this_cell[i],
1011 dofs_on_other_cell[j]);
1012 if (i_non_zero_e && j_non_zero_i)
1013 sparsity.add(dofs_on_other_cell[i],
1014 dofs_on_this_cell[j]);
1015 if (i_non_zero_i && j_non_zero_i)
1016 sparsity.add(dofs_on_this_cell[i],
1017 dofs_on_this_cell[j]);
1018 if (i_non_zero_e && j_non_zero_e)
1019 sparsity.add(dofs_on_other_cell[i],
1020 dofs_on_other_cell[j]);
1023 if (flux_dof_mask(j, i) ==
always)
1025 sparsity.add(dofs_on_this_cell[j],
1026 dofs_on_other_cell[i]);
1027 sparsity.add(dofs_on_other_cell[j],
1028 dofs_on_this_cell[i]);
1029 sparsity.add(dofs_on_this_cell[j],
1030 dofs_on_this_cell[i]);
1031 sparsity.add(dofs_on_other_cell[j],
1032 dofs_on_other_cell[i]);
1034 if (flux_dof_mask(j, i) ==
nonzero)
1036 if (j_non_zero_i && i_non_zero_e)
1037 sparsity.add(dofs_on_this_cell[j],
1038 dofs_on_other_cell[i]);
1039 if (j_non_zero_e && i_non_zero_i)
1040 sparsity.add(dofs_on_other_cell[j],
1041 dofs_on_this_cell[i]);
1042 if (j_non_zero_i && i_non_zero_i)
1043 sparsity.add(dofs_on_this_cell[j],
1044 dofs_on_this_cell[i]);
1045 if (j_non_zero_e && i_non_zero_e)
1046 sparsity.add(dofs_on_other_cell[j],
1047 dofs_on_other_cell[i]);
1062 typename SparsityPatternType,
1066 const ::hp::DoFHandler<dim, spacedim> &dof,
1067 SparsityPatternType & sparsity,
1069 const bool keep_constrained_dofs,
1073 const std::function<
1074 bool(
const typename ::hp::DoFHandler<dim, spacedim>::
1075 active_cell_iterator &,
1076 const unsigned int)> &face_has_flux_coupling)
1085 const ::hp::FECollection<dim, spacedim> &fe =
1086 dof.get_fe_collection();
1088 std::vector<types::global_dof_index> dofs_on_this_cell(
1090 std::vector<types::global_dof_index> dofs_on_other_cell(
1105 if (int_mask(c1, c2) != none || flux_mask(c1, c2) != none)
1106 int_and_flux_mask(c1, c2) =
always;
1108 std::vector<Table<2, Coupling>> int_and_flux_dof_mask =
1113 std::vector<Table<2, bool>> bool_int_and_flux_dof_mask(fe.size());
1114 for (
unsigned int f = 0; f < fe.size(); ++f)
1116 bool_int_and_flux_dof_mask[f].reinit(
1118 bool_int_and_flux_dof_mask[f].fill(
false);
1119 for (
unsigned int i = 0; i < fe[f].dofs_per_cell; ++i)
1120 for (
unsigned int j = 0; j < fe[f].dofs_per_cell; ++j)
1121 if (int_and_flux_dof_mask[f](i, j) != none)
1122 bool_int_and_flux_dof_mask[f](i, j) =
true;
1126 typename ::hp::DoFHandler<dim, spacedim>::active_cell_iterator
1129 for (; cell != endc; ++cell)
1132 cell->is_locally_owned())
1134 dofs_on_this_cell.resize(cell->get_fe().dofs_per_cell);
1135 cell->get_dof_indices(dofs_on_this_cell);
1142 keep_constrained_dofs,
1143 bool_int_and_flux_dof_mask[cell->active_fe_index()]);
1148 const typename ::hp::DoFHandler<dim,
1149 spacedim>::face_iterator
1150 cell_face = cell->face(face);
1152 const bool periodic_neighbor =
1153 cell->has_periodic_neighbor(face);
1155 if ((!cell->at_boundary(face)) || periodic_neighbor)
1157 typename ::hp::DoFHandler<dim, spacedim>::
1158 level_cell_iterator neighbor =
1159 cell->neighbor_or_periodic_neighbor(face);
1161 if (!face_has_flux_coupling(cell, face))
1168 if (neighbor->level() == cell->level() &&
1169 neighbor->index() > cell->index() &&
1170 neighbor->is_active() && neighbor->is_locally_owned())
1184 if (neighbor->level() != cell->level() &&
1185 ((!periodic_neighbor &&
1186 !cell->neighbor_is_coarser(face)) ||
1187 (periodic_neighbor &&
1188 !cell->periodic_neighbor_is_coarser(face))) &&
1189 neighbor->is_locally_owned())
1198 while (neighbor->has_children())
1199 neighbor = neighbor->child(face == 0 ? 1 : 0);
1201 if (neighbor->has_children())
1203 for (
unsigned int sub_nr = 0;
1204 sub_nr != cell_face->n_children();
1207 const typename ::hp::DoFHandler<
1209 spacedim>::level_cell_iterator sub_neighbor =
1211 cell->periodic_neighbor_child_on_subface(
1213 cell->neighbor_child_on_subface(face, sub_nr);
1215 dofs_on_other_cell.resize(
1216 sub_neighbor->get_fe().dofs_per_cell);
1217 sub_neighbor->get_dof_indices(dofs_on_other_cell);
1218 for (
unsigned int i = 0;
1219 i < cell->get_fe().dofs_per_cell;
1222 const unsigned int ii =
1223 (cell->get_fe().is_primitive(i) ?
1225 .system_to_component_index(i)
1228 .get_nonzero_components(i)
1229 .first_selected_component());
1234 for (
unsigned int j = 0;
1235 j < sub_neighbor->get_fe().dofs_per_cell;
1238 const unsigned int jj =
1239 (sub_neighbor->get_fe().is_primitive(
1241 sub_neighbor->get_fe()
1242 .system_to_component_index(j)
1244 sub_neighbor->get_fe()
1245 .get_nonzero_components(j)
1246 .first_selected_component());
1248 Assert(jj < sub_neighbor->get_fe()
1252 if ((flux_mask(ii, jj) ==
always) ||
1253 (flux_mask(ii, jj) ==
nonzero))
1255 sparsity.add(dofs_on_this_cell[i],
1256 dofs_on_other_cell[j]);
1259 if ((flux_mask(jj, ii) ==
always) ||
1260 (flux_mask(jj, ii) ==
nonzero))
1262 sparsity.add(dofs_on_other_cell[j],
1263 dofs_on_this_cell[i]);
1271 dofs_on_other_cell.resize(
1272 neighbor->get_fe().dofs_per_cell);
1273 neighbor->get_dof_indices(dofs_on_other_cell);
1274 for (
unsigned int i = 0;
1275 i < cell->get_fe().dofs_per_cell;
1278 const unsigned int ii =
1279 (cell->get_fe().is_primitive(i) ?
1281 .system_to_component_index(i)
1284 .get_nonzero_components(i)
1285 .first_selected_component());
1290 for (
unsigned int j = 0;
1291 j < neighbor->get_fe().dofs_per_cell;
1294 const unsigned int jj =
1295 (neighbor->get_fe().is_primitive(j) ?
1297 .system_to_component_index(j)
1300 .get_nonzero_components(j)
1301 .first_selected_component());
1306 if ((flux_mask(ii, jj) ==
always) ||
1307 (flux_mask(ii, jj) ==
nonzero))
1309 sparsity.add(dofs_on_this_cell[i],
1310 dofs_on_other_cell[j]);
1313 if ((flux_mask(jj, ii) ==
always) ||
1314 (flux_mask(jj, ii) ==
nonzero))
1316 sparsity.add(dofs_on_other_cell[j],
1317 dofs_on_this_cell[i]);
1332 template <
typename DoFHandlerType,
typename SparsityPatternType>
1335 SparsityPatternType & sparsity,
1342 const bool keep_constrained_dofs =
true;
1348 keep_constrained_dofs,
1352 internal::always_couple_on_faces<DoFHandlerType>);
1357 template <
typename DoFHandlerType,
1358 typename SparsityPatternType,
1362 const DoFHandlerType & dof,
1363 SparsityPatternType & sparsity,
1365 const bool keep_constrained_dofs,
1369 const std::function<
1370 bool(
const typename DoFHandlerType::active_cell_iterator &,
1371 const unsigned int)> &face_has_flux_coupling)
1377 const unsigned int n_comp = dof.get_fe(0).n_components();
1380 Assert(sparsity.n_rows() == n_dofs,
1382 Assert(sparsity.n_cols() == n_dofs,
1384 Assert(int_mask.n_rows() == n_comp,
1386 Assert(int_mask.n_cols() == n_comp,
1388 Assert(flux_mask.n_rows() == n_comp,
1390 Assert(flux_mask.n_cols() == n_comp,
1396 Assert((dof.get_triangulation().locally_owned_subdomain() ==
1400 dof.get_triangulation().locally_owned_subdomain()),
1402 "For parallel::distributed::Triangulation objects and "
1403 "associated DoF handler objects, asking for any subdomain other "
1404 "than the locally owned one does not make sense."));
1407 face_has_flux_coupling,
1409 "The function which specifies if a flux coupling occurs over a given "
1415 keep_constrained_dofs,
1419 face_has_flux_coupling);
1427 #include "dof_tools_sparsity.inst"