38 #include <unordered_set>
43 template <
int dim,
int spacedim>
46 template <
int dim,
int spacedim>
49 template <
int dim,
int spacedim>
57 template <
int dim,
int spacedim>
69 template <
int dim,
int spacedim>
72 PolicyBase<dim, spacedim> &policy)
74 std::string policy_name;
75 if (
dynamic_cast<const typename ::internal::DoFHandlerImplementation::
76 Policy::Sequential<::DoFHandler<dim, spacedim>
> *>(
79 const typename ::internal::DoFHandlerImplementation::Policy::
80 Sequential<::hp::DoFHandler<dim, spacedim>
> *>(&policy))
81 policy_name =
"Policy::Sequential<";
82 else if (
dynamic_cast<
83 const typename ::internal::DoFHandlerImplementation::
84 Policy::ParallelDistributed<::DoFHandler<dim, spacedim>
>
88 Policy::ParallelDistributed<
90 policy_name =
"Policy::ParallelDistributed<";
91 else if (
dynamic_cast<
92 const typename ::internal::DoFHandlerImplementation::
93 Policy::ParallelShared<::DoFHandler<dim, spacedim>
> *>(
95 dynamic_cast<const typename ::
internal::
99 policy_name =
"Policy::ParallelShared<";
108 namespace DoFHandlerImplementation
126 template <
int spacedim>
131 3 * dof_handler.
get_fe().dofs_per_vertex +
132 2 * dof_handler.
get_fe().dofs_per_line),
138 template <
int spacedim>
164 switch (dof_handler.
tria->max_adjacent_cells())
167 max_couplings = 19 * dof_handler.
get_fe().dofs_per_vertex +
168 28 * dof_handler.
get_fe().dofs_per_line +
169 8 * dof_handler.
get_fe().dofs_per_quad;
172 max_couplings = 21 * dof_handler.
get_fe().dofs_per_vertex +
173 31 * dof_handler.
get_fe().dofs_per_line +
174 9 * dof_handler.
get_fe().dofs_per_quad;
177 max_couplings = 28 * dof_handler.
get_fe().dofs_per_vertex +
178 42 * dof_handler.
get_fe().dofs_per_line +
179 12 * dof_handler.
get_fe().dofs_per_quad;
182 max_couplings = 30 * dof_handler.
get_fe().dofs_per_vertex +
183 45 * dof_handler.
get_fe().dofs_per_line +
184 13 * dof_handler.
get_fe().dofs_per_quad;
187 max_couplings = 37 * dof_handler.
get_fe().dofs_per_vertex +
188 56 * dof_handler.
get_fe().dofs_per_line +
189 16 * dof_handler.
get_fe().dofs_per_quad;
197 max_couplings = 39 * dof_handler.
get_fe().dofs_per_vertex +
198 59 * dof_handler.
get_fe().dofs_per_line +
199 17 * dof_handler.
get_fe().dofs_per_quad;
202 max_couplings = 46 * dof_handler.
get_fe().dofs_per_vertex +
203 70 * dof_handler.
get_fe().dofs_per_line +
204 20 * dof_handler.
get_fe().dofs_per_quad;
207 max_couplings = 48 * dof_handler.
get_fe().dofs_per_vertex +
208 73 * dof_handler.
get_fe().dofs_per_line +
209 21 * dof_handler.
get_fe().dofs_per_quad;
212 max_couplings = 55 * dof_handler.
get_fe().dofs_per_vertex +
213 84 * dof_handler.
get_fe().dofs_per_line +
214 24 * dof_handler.
get_fe().dofs_per_quad;
217 max_couplings = 57 * dof_handler.
get_fe().dofs_per_vertex +
218 87 * dof_handler.
get_fe().dofs_per_line +
219 25 * dof_handler.
get_fe().dofs_per_quad;
222 max_couplings = 63 * dof_handler.
get_fe().dofs_per_vertex +
223 98 * dof_handler.
get_fe().dofs_per_line +
224 28 * dof_handler.
get_fe().dofs_per_quad;
227 max_couplings = 65 * dof_handler.
get_fe().dofs_per_vertex +
228 103 * dof_handler.
get_fe().dofs_per_line +
229 29 * dof_handler.
get_fe().dofs_per_quad;
232 max_couplings = 72 * dof_handler.
get_fe().dofs_per_vertex +
233 114 * dof_handler.
get_fe().dofs_per_line +
234 32 * dof_handler.
get_fe().dofs_per_quad;
245 template <
int spacedim>
263 const unsigned int max_adjacent_cells =
264 dof_handler.
tria->max_adjacent_cells();
267 if (max_adjacent_cells <= 8)
268 max_couplings = 7 * 7 * 7 * dof_handler.
get_fe().dofs_per_vertex +
269 7 * 6 * 7 * 3 * dof_handler.
get_fe().dofs_per_line +
270 9 * 4 * 7 * 3 * dof_handler.
get_fe().dofs_per_quad +
271 27 * dof_handler.
get_fe().dofs_per_hex;
291 template <
int spacedim>
295 dof_handler.
get_fe().dofs_per_vertex,
298 for (
unsigned int i = 0; i < dof_handler.
tria->n_levels(); ++i)
300 dof_handler.
levels.emplace_back(
303 dof_handler.
levels.back()->dof_object.dofs.resize(
304 dof_handler.
tria->n_raw_cells(i) *
305 dof_handler.
get_fe().dofs_per_line,
308 dof_handler.
levels.back()->cell_dof_indices_cache.resize(
309 dof_handler.
tria->n_raw_cells(i) *
310 dof_handler.
get_fe().dofs_per_cell,
316 template <
int spacedim>
320 dof_handler.
get_fe().dofs_per_vertex,
323 for (
unsigned int i = 0; i < dof_handler.
tria->n_levels(); ++i)
325 dof_handler.
levels.emplace_back(
328 dof_handler.
levels.back()->dof_object.dofs.resize(
329 dof_handler.
tria->n_raw_cells(i) *
330 dof_handler.
get_fe().dofs_per_quad,
333 dof_handler.
levels.back()->cell_dof_indices_cache.resize(
334 dof_handler.
tria->n_raw_cells(i) *
335 dof_handler.
get_fe().dofs_per_cell,
339 dof_handler.
faces = std_cxx14::make_unique<
342 if (dof_handler.
tria->n_cells() > 0)
344 dof_handler.
faces->lines.dofs.resize(
345 dof_handler.
tria->n_raw_lines() *
346 dof_handler.
get_fe().dofs_per_line,
352 template <
int spacedim>
356 dof_handler.
get_fe().dofs_per_vertex,
359 for (
unsigned int i = 0; i < dof_handler.
tria->n_levels(); ++i)
361 dof_handler.
levels.emplace_back(
364 dof_handler.
levels.back()->dof_object.dofs.resize(
365 dof_handler.
tria->n_raw_cells(i) *
366 dof_handler.
get_fe().dofs_per_hex,
369 dof_handler.
levels.back()->cell_dof_indices_cache.resize(
370 dof_handler.
tria->n_raw_cells(i) *
371 dof_handler.
get_fe().dofs_per_cell,
374 dof_handler.
faces = std_cxx14::make_unique<
378 if (dof_handler.
tria->n_cells() > 0)
380 dof_handler.
faces->lines.dofs.resize(
381 dof_handler.
tria->n_raw_lines() *
382 dof_handler.
get_fe().dofs_per_line,
384 dof_handler.
faces->quads.dofs.resize(
385 dof_handler.
tria->n_raw_quads() *
386 dof_handler.
get_fe().dofs_per_quad,
391 template <
int spacedim>
398 const ::Triangulation<1, spacedim> &tria =
400 const unsigned int dofs_per_line = dof_handler.
get_fe().dofs_per_line;
401 const unsigned int n_levels = tria.n_levels();
403 for (
unsigned int i = 0; i < n_levels; ++i)
407 dof_handler.
mg_levels.back()->dof_object.dofs =
408 std::vector<types::global_dof_index>(tria.n_raw_lines(i) *
413 const unsigned int n_vertices = tria.n_vertices();
417 std::vector<unsigned int> max_level(n_vertices, 0);
418 std::vector<unsigned int> min_level(n_vertices, n_levels);
420 for (typename ::Triangulation<1, spacedim>::cell_iterator cell =
425 const unsigned int level = cell->level();
429 const unsigned int vertex_index = cell->vertex_index(vertex);
431 if (min_level[vertex_index] >
level)
432 min_level[vertex_index] =
level;
434 if (max_level[vertex_index] <
level)
435 max_level[vertex_index] =
level;
439 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
440 if (tria.vertex_used(vertex))
443 Assert(max_level[vertex] >= min_level[vertex],
448 dof_handler.
get_fe().dofs_per_vertex);
459 template <
int spacedim>
466 const ::FiniteElement<2, spacedim> &fe = dof_handler.
get_fe();
467 const ::Triangulation<2, spacedim> &tria =
469 const unsigned int n_levels = tria.n_levels();
471 for (
unsigned int i = 0; i < n_levels; ++i)
474 std_cxx14::make_unique<
476 dof_handler.
mg_levels.back()->dof_object.dofs =
477 std::vector<types::global_dof_index>(tria.n_raw_quads(i) *
482 dof_handler.
mg_faces = std_cxx14::make_unique<
484 dof_handler.
mg_faces->lines.dofs = std::vector<types::global_dof_index>(
487 const unsigned int n_vertices = tria.n_vertices();
491 std::vector<unsigned int> max_level(n_vertices, 0);
492 std::vector<unsigned int> min_level(n_vertices, n_levels);
494 for (typename ::Triangulation<2, spacedim>::cell_iterator cell =
499 const unsigned int level = cell->level();
503 const unsigned int vertex_index = cell->vertex_index(vertex);
505 if (min_level[vertex_index] >
level)
506 min_level[vertex_index] =
level;
508 if (max_level[vertex_index] <
level)
509 max_level[vertex_index] =
level;
513 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
514 if (tria.vertex_used(vertex))
517 Assert(max_level[vertex] >= min_level[vertex],
532 template <
int spacedim>
539 const ::FiniteElement<3, spacedim> &fe = dof_handler.
get_fe();
540 const ::Triangulation<3, spacedim> &tria =
542 const unsigned int n_levels = tria.n_levels();
544 for (
unsigned int i = 0; i < n_levels; ++i)
547 std_cxx14::make_unique<
549 dof_handler.
mg_levels.back()->dof_object.dofs =
550 std::vector<types::global_dof_index>(tria.n_raw_hexs(i) *
555 dof_handler.
mg_faces = std_cxx14::make_unique<
557 dof_handler.
mg_faces->lines.dofs = std::vector<types::global_dof_index>(
559 dof_handler.
mg_faces->quads.dofs = std::vector<types::global_dof_index>(
562 const unsigned int n_vertices = tria.n_vertices();
566 std::vector<unsigned int> max_level(n_vertices, 0);
567 std::vector<unsigned int> min_level(n_vertices, n_levels);
569 for (typename ::Triangulation<3, spacedim>::cell_iterator cell =
574 const unsigned int level = cell->level();
578 const unsigned int vertex_index = cell->vertex_index(vertex);
580 if (min_level[vertex_index] >
level)
581 min_level[vertex_index] =
level;
583 if (max_level[vertex_index] <
level)
584 max_level[vertex_index] =
level;
588 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
589 if (tria.vertex_used(vertex))
592 Assert(max_level[vertex] >= min_level[vertex],
609 template <
int spacedim>
617 const unsigned int obj_index,
618 const unsigned int fe_index,
619 const unsigned int local_index,
620 const std::integral_constant<int, 1>)
622 return mg_level->dof_object.get_dof_index(dof_handler,
628 template <
int spacedim>
636 const unsigned int obj_index,
637 const unsigned int fe_index,
638 const unsigned int local_index,
639 const std::integral_constant<int, 1>)
641 return mg_faces->lines.get_dof_index(dof_handler,
647 template <
int spacedim>
655 const unsigned int obj_index,
656 const unsigned int fe_index,
657 const unsigned int local_index,
658 const std::integral_constant<int, 2>)
660 return mg_level->dof_object.get_dof_index(dof_handler,
666 template <
int spacedim>
674 const unsigned int obj_index,
675 const unsigned int fe_index,
676 const unsigned int local_index,
677 const std::integral_constant<int, 1>)
679 return mg_faces->lines.get_dof_index(dof_handler,
685 template <
int spacedim>
693 const unsigned int obj_index,
694 const unsigned int fe_index,
695 const unsigned int local_index,
696 const std::integral_constant<int, 2>)
698 return mg_faces->quads.get_dof_index(dof_handler,
704 template <
int spacedim>
712 const unsigned int obj_index,
713 const unsigned int fe_index,
714 const unsigned int local_index,
715 const std::integral_constant<int, 3>)
717 return mg_level->dof_object.get_dof_index(dof_handler,
723 template <
int spacedim>
731 const unsigned int obj_index,
732 const unsigned int fe_index,
733 const unsigned int local_index,
735 const std::integral_constant<int, 1>)
737 mg_level->dof_object.set_dof_index(
738 dof_handler, obj_index, fe_index, local_index,
global_index);
741 template <
int spacedim>
749 const unsigned int obj_index,
750 const unsigned int fe_index,
751 const unsigned int local_index,
753 const std::integral_constant<int, 1>)
755 mg_faces->lines.set_dof_index(
756 dof_handler, obj_index, fe_index, local_index,
global_index);
759 template <
int spacedim>
767 const unsigned int obj_index,
768 const unsigned int fe_index,
769 const unsigned int local_index,
771 const std::integral_constant<int, 2>)
773 mg_level->dof_object.set_dof_index(
774 dof_handler, obj_index, fe_index, local_index,
global_index);
777 template <
int spacedim>
785 const unsigned int obj_index,
786 const unsigned int fe_index,
787 const unsigned int local_index,
789 const std::integral_constant<int, 1>)
791 mg_faces->lines.set_dof_index(
792 dof_handler, obj_index, fe_index, local_index,
global_index);
795 template <
int spacedim>
803 const unsigned int obj_index,
804 const unsigned int fe_index,
805 const unsigned int local_index,
807 const std::integral_constant<int, 2>)
809 mg_faces->quads.set_dof_index(
810 dof_handler, obj_index, fe_index, local_index,
global_index);
813 template <
int spacedim>
821 const unsigned int obj_index,
822 const unsigned int fe_index,
823 const unsigned int local_index,
825 const std::integral_constant<int, 3>)
827 mg_level->dof_object.set_dof_index(
828 dof_handler, obj_index, fe_index, local_index,
global_index);
836 template <
int dim,
int spacedim>
838 : tria(&tria, typeid(*this).name())
846 std_cxx14::make_unique<internal::DoFHandlerImplementation::Policy::
847 ParallelShared<DoFHandler<dim, spacedim>>>(
849 else if (
dynamic_cast<
857 std_cxx14::make_unique<internal::DoFHandlerImplementation::Policy::
858 ParallelDistributed<DoFHandler<dim, spacedim>>>(
863 template <
int dim,
int spacedim>
865 : tria(nullptr, typeid(*this).name())
869 template <
int dim,
int spacedim>
885 template <
int dim,
int spacedim>
892 number_cache.n_global_dofs = 0;
898 std_cxx14::make_unique<internal::DoFHandlerImplementation::Policy::
899 ParallelShared<DoFHandler<dim, spacedim>>>(
901 else if (
dynamic_cast<
910 std_cxx14::make_unique<internal::DoFHandlerImplementation::Policy::
911 Sequential<DoFHandler<dim, spacedim>>>(*this);
920 template <
int dim,
int spacedim>
925 this->get_triangulation().begin(
level);
926 if (cell == this->get_triangulation().
end(
level))
933 template <
int dim,
int spacedim>
941 while (i->has_children())
949 template <
int dim,
int spacedim>
953 return cell_iterator(&this->get_triangulation(), -1, -1,
this);
957 template <
int dim,
int spacedim>
962 this->get_triangulation().end(
level);
969 template <
int dim,
int spacedim>
974 this->get_triangulation().end_active(
level);
982 template <
int dim,
int spacedim>
989 this->get_triangulation().begin(
level);
990 if (cell == this->get_triangulation().
end(
level))
991 return end_mg(
level);
996 template <
int dim,
int spacedim>
1003 this->get_triangulation().end(
level);
1010 template <
int dim,
int spacedim>
1019 template <
int dim,
int spacedim>
1028 template <
int dim,
int spacedim>
1039 template <
int dim,
int spacedim>
1044 begin_mg(), end_mg());
1049 template <
int dim,
int spacedim>
1052 const unsigned int level)
const
1060 template <
int dim,
int spacedim>
1063 const unsigned int level)
const
1072 template <
int dim,
int spacedim>
1075 const unsigned int level)
const
1087 template <
int dim,
int spacedim>
1093 std::vector<::types::global_dof_index> dofs_on_face(dofs_per_face);
1095 const IndexSet &owned_dofs = locally_owned_dofs();
1097 std::unordered_set<unsigned int> boundary_dof_indices;
1104 for (
const auto &cell : this->active_cell_iterators())
1106 if (cell->is_locally_owned() && cell->at_boundary())
1108 for (
const unsigned int iface :
1111 const auto face = cell->face(iface);
1112 if (face->at_boundary())
1114 cell->face(iface)->get_dof_indices(dofs_on_face);
1115 for (
unsigned int idof_face = 0; idof_face < dofs_per_face;
1118 const unsigned int global_idof_index =
1119 dofs_on_face[idof_face];
1125 if (owned_dofs.
is_element(global_idof_index))
1127 boundary_dof_indices.insert(global_idof_index);
1134 return boundary_dof_indices.size();
1139 template <
int dim,
int spacedim>
1142 const std::set<types::boundary_id> &boundary_ids)
const
1150 std::vector<::types::global_dof_index> dofs_on_face(dofs_per_face);
1152 const IndexSet &owned_dofs = locally_owned_dofs();
1154 std::unordered_set<unsigned int> boundary_dof_indices;
1161 for (
const auto &cell : this->active_cell_iterators())
1163 if (cell->is_locally_owned() && cell->at_boundary())
1165 for (
const unsigned int iface :
1168 const auto face = cell->face(iface);
1169 const unsigned int boundary_id = face->boundary_id();
1171 if (face->at_boundary() &&
1172 std::find(boundary_ids.begin(),
1176 cell->face(iface)->get_dof_indices(dofs_on_face);
1177 for (
unsigned int idof_face = 0; idof_face < dofs_per_face;
1180 const unsigned int global_idof_index =
1181 dofs_on_face[idof_face];
1187 if (owned_dofs.
is_element(global_idof_index))
1189 boundary_dof_indices.insert(global_idof_index);
1196 return boundary_dof_indices.size();
1201 template <
int dim,
int spacedim>
1214 for (
unsigned int i = 0; i < levels.size(); ++i)
1220 if (mg_faces !=
nullptr)
1223 for (
unsigned int i = 0; i < mg_vertex_dofs.size(); ++i)
1224 mem +=
sizeof(MGVertexDoFs) + (1 + mg_vertex_dofs[i].get_finest_level() -
1225 mg_vertex_dofs[i].get_coarsest_level()) *
1233 template <
int dim,
int spacedim>
1239 if (fe_collection.size() == 0 || fe_collection[0] != ff)
1245 template <
int dim,
int spacedim>
1253 "You need to set the Triangulation in the DoFHandler using initialize() or "
1254 "in the constructor before you can distribute DoFs."));
1255 Assert(tria->n_levels() > 0,
1256 ExcMessage(
"The Triangulation you are using is empty!"));
1281 number_cache = policy->distribute_dofs();
1288 *
>(&*tria) ==
nullptr)
1289 block_info_object.initialize(*
this,
false,
true);
1294 template <
int dim,
int spacedim>
1301 "Distribute active DoFs using distribute_dofs() before calling distribute_mg_dofs()."));
1304 ((tria->get_mesh_smoothing() &
1308 "The mesh smoothing requirement 'limit_level_difference_at_vertices' has to be set for using multigrid!"));
1313 mg_number_cache = policy->distribute_mg_dofs();
1321 block_info_object.initialize(*
this,
true,
false);
1326 template <
int dim,
int spacedim>
1333 std::vector<MGVertexDoFs> tmp;
1337 mg_number_cache.clear();
1341 template <
int dim,
int spacedim>
1345 block_info_object.initialize_local(*
this);
1350 template <
int dim,
int spacedim>
1361 template <
int dim,
int spacedim>
1364 const std::vector<types::global_dof_index> &new_numbers)
1366 Assert(levels.size() > 0,
1368 "You need to distribute DoFs before you can renumber them."));
1374 Assert(new_numbers.size() == n_dofs() ||
1375 new_numbers.size() == n_locally_owned_dofs(),
1376 ExcMessage(
"Incorrect size of the input array."));
1378 else if (
dynamic_cast<
1398 if (n_locally_owned_dofs() == n_dofs())
1400 std::vector<types::global_dof_index> tmp(new_numbers);
1401 std::sort(tmp.begin(), tmp.end());
1402 std::vector<types::global_dof_index>::const_iterator p = tmp.begin();
1404 for (; p != tmp.end(); ++p, ++i)
1405 Assert(*p == i, ExcNewNumbersNotConsecutive(i));
1408 for (
const auto new_number : new_numbers)
1409 Assert(new_number < n_dofs(),
1411 "New DoF index is not less than the total number of dofs."));
1414 number_cache = policy->renumber_dofs(new_numbers);
1418 template <
int dim,
int spacedim>
1421 const unsigned int level,
1422 const std::vector<types::global_dof_index> &new_numbers)
1425 mg_levels.size() > 0 && levels.size() > 0,
1427 "You need to distribute active and level DoFs before you can renumber level DoFs."));
1430 locally_owned_mg_dofs(
level).n_elements());
1437 if (n_locally_owned_dofs() == n_dofs())
1439 std::vector<types::global_dof_index> tmp(new_numbers);
1440 std::sort(tmp.begin(), tmp.end());
1441 std::vector<types::global_dof_index>::const_iterator p = tmp.begin();
1443 for (; p != tmp.end(); ++p, ++i)
1444 Assert(*p == i, ExcNewNumbersNotConsecutive(i));
1447 for (
const auto new_number : new_numbers)
1450 "New DoF index is not less than the total number of dofs."));
1453 mg_number_cache[
level] = policy->renumber_mg_dofs(
level, new_numbers);
1458 template <
int dim,
int spacedim>
1468 template <
int dim,
int spacedim>
1475 return get_fe().dofs_per_vertex;
1477 return (3 * get_fe().dofs_per_vertex + 2 * get_fe().dofs_per_line);
1495 return (19 * get_fe().dofs_per_vertex + 28 * get_fe().dofs_per_line +
1496 8 * get_fe().dofs_per_quad);
1505 template <
int dim,
int spacedim>
1512 std::vector<types::global_dof_index> tmp;
1515 number_cache.clear();
1520 template <
int dim,
int spacedim>
1521 template <
int structdim>
1524 const unsigned int obj_index,
1525 const unsigned int fe_index,
1526 const unsigned int local_index)
const
1530 this->mg_levels[obj_level],
1535 std::integral_constant<int, structdim>());
1540 template <
int dim,
int spacedim>
1541 template <
int structdim>
1544 const unsigned int obj_level,
1545 const unsigned int obj_index,
1546 const unsigned int fe_index,
1547 const unsigned int local_index,
1552 this->mg_levels[obj_level],
1558 std::integral_constant<int, structdim>());
1563 template <
int dim,
int spacedim>
1571 template <
int dim,
int spacedim>
1574 const unsigned int cl,
1575 const unsigned int fl,
1576 const unsigned int dofs_per_vertex)
1578 coarsest_level = cl;
1581 if (coarsest_level <= finest_level)
1583 const unsigned int n_levels = finest_level - coarsest_level + 1;
1584 const unsigned int n_indices = n_levels * dofs_per_vertex;
1586 indices = std_cxx14::make_unique<types::global_dof_index[]>(n_indices);
1587 std::fill(indices.get(),
1588 indices.get() + n_indices,
1597 template <
int dim,
int spacedim>
1601 return coarsest_level;
1606 template <
int dim,
int spacedim>
1610 return finest_level;
1615 #include "dof_handler.inst"