8#include <deal.II/base/partitioner.h>
9#include <deal.II/dofs/dof_handler.h>
10#include <deal.II/dofs/dof_renumbering.h>
11#include <deal.II/dofs/dof_tools.h>
12#include <deal.II/lac/affine_constraints.h>
13#include <deal.II/lac/dynamic_sparsity_pattern.h>
14#include <deal.II/lac/sparsity_tools.h>
26 template <
typename Number>
28 const dealii::Utilities::MPI::Partitioner &partitioner,
29 dealii::AffineConstraints<Number> &affine_constraints)
31 affine_constraints.close();
33 dealii::AffineConstraints<Number> temporary;
35 for (
auto line : affine_constraints.get_lines()) {
37 line.index = partitioner.global_to_local(line.index);
38 std::transform(line.entries.begin(),
42 return std::make_pair(
43 partitioner.global_to_local(entry.first),
47 temporary.add_line(line.index);
48 temporary.add_entries(line.index, line.entries);
49 temporary.set_inhomogeneity(line.index, line.inhomogeneity);
54 affine_constraints = std::move(temporary);
66 template <
typename VECTOR>
68 const dealii::Utilities::MPI::Partitioner &partitioner, VECTOR &vector)
71 vector.begin(), vector.end(), vector.begin(), [&](
auto index) {
72 return partitioner.global_to_local(index);
83 namespace DoFRenumbering
89 using dealii::DoFRenumbering::Cuthill_McKee;
102 const MPI_Comm &mpi_communicator,
103 const unsigned int n_locally_internal,
104 const std::size_t group_size)
106 using namespace dealii;
108 const IndexSet &locally_owned = dof_handler.locally_owned_dofs();
109 const auto n_locally_owned = locally_owned.n_elements();
112 Assert(locally_owned.is_contiguous() ==
true,
114 "Need a contiguous set of locally owned indices."));
117 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
119 IndexSet locally_relevant;
120 DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant);
124 Utilities::MPI::Partitioner partitioner(
125 locally_owned, locally_relevant, mpi_communicator);
127 IndexSet export_indices(n_locally_owned);
128 for (
const auto &it : partitioner.import_indices()) {
129 export_indices.add_range(it.first, it.second);
132 std::vector<dealii::types::global_dof_index> new_order(n_locally_owned);
139 unsigned int n_export_indices = 0;
141 Assert(n_locally_internal <= n_locally_owned, dealii::ExcInternalError());
143 for (
unsigned int i = 0; i < n_locally_internal; i += group_size) {
144 bool export_index_present =
false;
145 for (
unsigned int j = 0; j < group_size; ++j) {
146 if (export_indices.is_element(i + j)) {
147 export_index_present =
true;
152 if (export_index_present) {
153 Assert(n_export_indices % group_size == 0,
154 dealii::ExcInternalError());
155 for (
unsigned int j = 0; j < group_size; ++j) {
156 new_order[i + j] = offset + n_export_indices++;
159 for (
unsigned int j = 0; j < group_size; ++j)
160 new_order[i + j] = dealii::numbers::invalid_dof_index;
165 unsigned int n_other = 0;
166 for (
unsigned int i = n_locally_internal; i < n_locally_owned; ++i)
167 if (export_indices.is_element(i))
170 Assert(n_other + n_export_indices >= export_indices.n_elements(),
171 dealii::ExcInternalError());
174 unsigned int running_index = n_export_indices;
180 for (
unsigned int i = 0; i < n_locally_internal; i += group_size) {
181 if (new_order[i] == dealii::numbers::invalid_dof_index) {
182 for (
unsigned int j = 0; j < group_size; ++j) {
183 Assert(new_order[i + j] == dealii::numbers::invalid_dof_index,
184 dealii::ExcInternalError());
185 new_order[i + j] = offset + running_index++;
190 Assert(running_index == n_locally_internal, dealii::ExcInternalError());
192 for (
unsigned int i = n_locally_internal; i < n_locally_owned; i++) {
193 new_order[i] = offset + running_index++;
196 Assert(running_index == n_locally_owned, dealii::ExcInternalError());
198 dof_handler.renumber_dofs(new_order);
200 Assert(n_export_indices % group_size == 0, dealii::ExcInternalError());
201 Assert(n_export_indices <= n_locally_internal,
202 dealii::ExcInternalError());
203 return n_export_indices;
216 const dealii::DynamicSparsityPattern &sparsity,
217 const unsigned int n_locally_internal,
218 const std::size_t group_size)
220 using namespace dealii;
222 const IndexSet &locally_owned = dof_handler.locally_owned_dofs();
223 const auto n_locally_owned = locally_owned.n_elements();
226 Assert(locally_owned.is_contiguous() ==
true,
228 "Need a contiguous set of locally owned indices."));
231 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
233 std::vector<dealii::types::global_dof_index> new_order(n_locally_owned);
241 unsigned int n_consistent_range = 0;
243 Assert(n_locally_internal <= n_locally_owned, dealii::ExcInternalError());
245 for (
unsigned int i = 0; i < n_locally_internal; i += group_size) {
247 bool stride_is_consistent =
true;
248 const auto group_row_length = sparsity.row_length(offset + i);
249 for (
unsigned int j = 0; j < group_size; ++j) {
250 if (group_row_length != sparsity.row_length(offset + i + j)) {
251 stride_is_consistent =
false;
256 if (stride_is_consistent) {
257 for (
unsigned int j = 0; j < group_size; ++j) {
258 new_order[i + j] = offset + n_consistent_range++;
261 for (
unsigned int j = 0; j < group_size; ++j)
262 new_order[i + j] = dealii::numbers::invalid_dof_index;
270 unsigned int running_index = n_consistent_range;
272 for (
unsigned int i = 0; i < n_locally_internal; i += group_size) {
273 if (new_order[i] == dealii::numbers::invalid_dof_index) {
274 for (
unsigned int j = 0; j < group_size; ++j) {
275 Assert(new_order[i + j] == dealii::numbers::invalid_dof_index,
276 dealii::ExcInternalError());
277 new_order[i + j] = offset + running_index++;
282 Assert(running_index == n_locally_internal, dealii::ExcInternalError());
284 for (
unsigned int i = n_locally_internal; i < n_locally_owned; i++) {
285 new_order[i] = offset + running_index++;
288 Assert(running_index == n_locally_owned, dealii::ExcInternalError());
290 dof_handler.renumber_dofs(new_order);
292 Assert(n_consistent_range % group_size == 0, dealii::ExcInternalError());
293 Assert(n_consistent_range <= n_locally_internal,
294 dealii::ExcInternalError());
295 return n_consistent_range;
315 const dealii::DynamicSparsityPattern &sparsity,
316 const std::size_t group_size)
318 using namespace dealii;
320 const auto &locally_owned = dof_handler.locally_owned_dofs();
321 const auto n_locally_owned = locally_owned.n_elements();
325 Assert(locally_owned.is_contiguous() ==
true,
327 "Need a contiguous set of locally owned indices."));
330 const auto offset = n_locally_owned != 0 ? *locally_owned.begin() : 0;
332 using dof_type = dealii::types::global_dof_index;
333 std::vector<dof_type> new_order(n_locally_owned);
334 dof_type current_index = offset;
342 std::map<unsigned int, std::set<dof_type>> bins;
344 for (
unsigned int i = 0; i < n_locally_owned; ++i) {
345 const dof_type index = i;
346 const unsigned int row_length = sparsity.row_length(offset + index);
347 bins[row_length].insert(index);
349 if (bins[row_length].size() == group_size) {
350 for (
const auto &index : bins[row_length])
351 new_order[index] = current_index++;
352 bins.erase(row_length);
356 unsigned int n_locally_internal = current_index - offset;
360 for (
const auto &entries : bins) {
361 Assert(entries.second.size() > 0, ExcInternalError());
362 for (
const auto &index : entries.second)
363 new_order[index] = current_index++;
365 Assert(current_index == offset + n_locally_owned, ExcInternalError());
367 dof_handler.renumber_dofs(new_order);
369 Assert(n_locally_internal % group_size == 0, ExcInternalError());
370 return n_locally_internal;
384 using dealii::DoFTools::extract_locally_relevant_dofs;
387 using dealii::DoFTools::make_hanging_node_constraints;
390 using dealii::DoFTools::make_periodicity_constraints;
393 using dealii::DoFTools::make_sparsity_pattern;
403 template <
int dim,
typename Number,
typename SPARSITY>
405 const dealii::DoFHandler<dim> &dof_handler,
407 const dealii::AffineConstraints<Number> &affine_constraints,
408 bool keep_constrained)
410 const unsigned int dofs_per_cell = dof_handler.get_fe().dofs_per_cell;
411 std::vector<dealii::types::global_dof_index> dof_indices(dofs_per_cell);
413 for (
auto cell : dof_handler.active_cell_iterators()) {
415 if (cell->is_artificial())
418 cell->get_dof_indices(dof_indices);
419 affine_constraints.add_entries_local_to_global(
420 dof_indices, dsp, keep_constrained);
433 template <
int dim,
typename Number,
typename SPARSITY>
435 const dealii::DoFHandler<dim> &dof_handler,
437 const dealii::AffineConstraints<Number> &affine_constraints,
438 bool keep_constrained)
440 Assert(affine_constraints.n_constraints() == 0,
441 dealii::ExcMessage(
"I don't think constraints make sense for dG"));
443 const auto &fe = dof_handler.get_fe();
444 const unsigned int dofs_per_cell = fe.dofs_per_cell;
445 std::vector<dealii::types::global_dof_index> dof_indices(dofs_per_cell);
446 std::vector<dealii::types::global_dof_index> neighbor_dof_indices(
453 std::vector<dealii::types::global_dof_index> coupling_indices;
454 std::vector<dealii::types::global_dof_index> neighbor_coupling_indices;
457 for (
auto cell : dof_handler.active_cell_iterators()) {
458 if (cell->is_artificial())
461 cell->get_dof_indices(dof_indices);
463 affine_constraints.add_entries_local_to_global(
464 dof_indices, dsp, keep_constrained);
466 for (
const auto f_index : cell->face_indices()) {
467 const auto &face = cell->face(f_index);
470 const bool has_neighbor =
471 !face->at_boundary() || cell->has_periodic_neighbor(f_index);
476 const auto neighbor_cell =
477 cell->neighbor_or_periodic_neighbor(f_index);
478 if (neighbor_cell->is_artificial())
481 const unsigned int f_index_neighbor =
482 cell->has_periodic_neighbor(f_index)
483 ? cell->periodic_neighbor_of_periodic_neighbor(f_index)
484 : cell->neighbor_of_neighbor(f_index);
486 neighbor_cell->get_dof_indices(neighbor_dof_indices);
493 coupling_indices.resize(0);
494 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
495 if (fe.has_support_on_face(i, f_index))
496 coupling_indices.push_back(dof_indices[i]);
498 neighbor_coupling_indices.resize(0);
499 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
500 if (fe.has_support_on_face(j, f_index_neighbor))
501 neighbor_coupling_indices.push_back(neighbor_dof_indices[j]);
503 affine_constraints.add_entries_local_to_global(
505 neighbor_coupling_indices,
void make_extended_sparsity_pattern(const dealii::DoFHandler< dim > &dof_handler, SPARSITY &dsp, const dealii::AffineConstraints< Number > &affine_constraints, bool keep_constrained)
void transform_to_local_range(const dealii::Utilities::MPI::Partitioner &partitioner, dealii::AffineConstraints< Number > &affine_constraints)
unsigned int internal_range(dealii::DoFHandler< dim > &dof_handler, const dealii::DynamicSparsityPattern &sparsity, const std::size_t group_size)
unsigned int export_indices_first(dealii::DoFHandler< dim > &dof_handler, const MPI_Comm &mpi_communicator, const unsigned int n_locally_internal, const std::size_t group_size)
unsigned int inconsistent_strides_last(dealii::DoFHandler< dim > &dof_handler, const dealii::DynamicSparsityPattern &sparsity, const unsigned int n_locally_internal, const std::size_t group_size)
void make_extended_sparsity_pattern_dg(const dealii::DoFHandler< dim > &dof_handler, SPARSITY &dsp, const dealii::AffineConstraints< Number > &affine_constraints, bool keep_constrained)