147 const bool use_vector_data_exchanger_full)
154 const std::size_t n_ghosts =
ghost_dofs.size();
163 std::vector<unsigned int> ghost_numbering(n_ghosts);
167 unsigned int n_unique_ghosts = 0;
171 std::vector<std::pair<types::global_dof_index, unsigned int>>
172 ghost_origin(n_ghosts);
173 for (std::size_t i = 0; i < n_ghosts; ++i)
176 ghost_origin[i].second = i;
178 std::sort(ghost_origin.begin(), ghost_origin.end());
181 ghost_numbering[ghost_origin[0].second] = 0;
182 for (std::size_t i = 1; i < n_ghosts; ++i)
184 if (ghost_origin[i].
first > ghost_origin[i - 1].
first + 1)
186 ghost_indices.
add_range(last_contiguous_start,
187 ghost_origin[i - 1].
first + 1);
188 last_contiguous_start = ghost_origin[i].first;
190 if (ghost_origin[i].
first > ghost_origin[i - 1].
first)
192 ghost_numbering[ghost_origin[i].second] = n_unique_ghosts;
195 ghost_indices.
add_range(last_contiguous_start,
196 ghost_origin.back().first + 1);
203 for (std::size_t i = 0; i < n_ghosts; ++i)
204 Assert(ghost_numbering[i] ==
213 const unsigned int n_boundary_cells = boundary_cells.size();
214 for (
unsigned int i = 0; i < n_boundary_cells; ++i)
216 unsigned int *data_ptr =
219 const unsigned int *row_end =
222 for (; data_ptr != row_end; ++data_ptr)
223 *data_ptr = ((*data_ptr < n_owned ||
226 n_owned + ghost_numbering[*data_ptr - n_owned]);
233 const unsigned int fe_index =
240 unsigned int *data_ptr =
243 const unsigned int *row_end =
245 for (; data_ptr != row_end; ++data_ptr)
247 ((*data_ptr < n_owned) ?
249 n_owned + ghost_numbering[*data_ptr - n_owned]);
254 std::vector<types::global_dof_index> empty;
264 if (use_vector_data_exchanger_full ==
false)
270 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
279 const std::vector<unsigned int> &renumbering,
280 const std::vector<unsigned int> &constraint_pool_row_index,
281 const std::vector<unsigned char> &irregular_cells)
287 std::vector<unsigned int> new_active_fe_index;
289 unsigned int position_cell = 0;
290 for (
unsigned int cell = 0;
294 const unsigned int n_comp =
295 (irregular_cells[cell] > 0 ? irregular_cells[cell] :
300 unsigned int fe_index =
302 for (
unsigned int j = 1; j < n_comp; ++j)
307 new_active_fe_index.push_back(fe_index);
308 position_cell += n_comp;
318 std::vector<std::pair<unsigned int, unsigned int>> new_row_starts(
322 std::vector<unsigned int> new_dof_indices;
323 std::vector<std::pair<unsigned short, unsigned short>>
324 new_constraint_indicator;
325 std::vector<unsigned int> new_plain_indices, new_rowstart_plain;
326 unsigned int position_cell = 0;
330 std::vector<compressed_constraint_kind> new_hanging_node_constraint_masks;
331 new_hanging_node_constraint_masks.reserve(
350 const unsigned int n_lanes_filled =
351 (irregular_cells[i] > 0 ? irregular_cells[i] :
355 this->dofs_per_cell[0];
357 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
359 const unsigned int cell_no = renumbering[position_cell + j];
363 new_hanging_node_constraint_masks.push_back(
366 for (
unsigned int comp = 0; comp <
n_components; ++comp)
370 .
first = new_dof_indices.size();
373 .
second = new_constraint_indicator.size();
376 new_dof_indices.insert(new_dof_indices.end(),
384 new_constraint_indicator.push_back(
392 new_plain_indices.size();
393 new_plain_indices.insert(new_plain_indices.end(),
402 for (
unsigned int comp = 0; comp <
n_components; ++comp)
406 .
first = new_dof_indices.size();
409 .
second = new_constraint_indicator.size();
414 new_hanging_node_constraint_masks.push_back(
417 position_cell += n_lanes_filled;
424 .first = new_dof_indices.size();
427 .second = new_constraint_indicator.size();
430 new_constraint_indicator.size());
443 const unsigned int index_range =
458 const unsigned int row_length_ind =
466 const std::pair<unsigned short, unsigned short>
474 for (; con_it != end_con; ++con_it)
478 constraint_pool_row_index.size() - 1);
483 unsigned int n_active_cells = 0;
484 for (
unsigned int c = 0;
487 if (irregular_cells[c] > 0)
488 n_active_cells += irregular_cells[c];
501 const std::vector<unsigned char> &irregular_cells)
511 irregular_cells.size());
515 irregular_cells.size());
516 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
517 if (irregular_cells[i] > 0)
532 std::vector<unsigned int> index_kinds(
533 static_cast<unsigned int>(
537 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
539 const unsigned int ndofs =
541 const unsigned int n_lanes_filled =
545 bool has_constraints =
false;
546 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
552 has_constraints =
true;
561 bool indices_are_contiguous = (ndofs > 0);
562 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
566 this->dof_indices.data() +
575 indices_are_contiguous =
false;
578 for (
unsigned int i = 1; i < ndofs; ++i)
582 indices_are_contiguous =
false;
587 bool indices_are_interleaved_and_contiguous =
592 this->dof_indices.data() +
594 for (
unsigned int k = 0;
595 k < ndofs && indices_are_interleaved_and_contiguous;
597 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
603 indices_are_interleaved_and_contiguous =
false;
608 if (indices_are_contiguous ||
609 indices_are_interleaved_and_contiguous)
611 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
613 const unsigned int start_index =
626 if (indices_are_interleaved_and_contiguous)
632 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
636 else if (indices_are_contiguous)
640 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
646 int indices_are_interleaved_and_mixed = 2;
651 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
654 for (
unsigned int k = 0;
655 k < ndofs && indices_are_interleaved_and_mixed != 0;
657 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
666 indices_are_interleaved_and_mixed = 0;
669 if (indices_are_interleaved_and_mixed == 2)
671 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
675 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
679 for (
unsigned int j = 0; j < n_lanes_filled; ++j)
682 indices_are_interleaved_and_mixed = 1;
685 if (indices_are_interleaved_and_mixed == 1 ||
708 index_kinds[
static_cast<unsigned int>(
718 auto fix_single_interleaved_indices =
720 if (index_kinds[
static_cast<unsigned int>(
723 index_kinds[
static_cast<unsigned int>(variant)] > 0)
724 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
736 index_kinds[
static_cast<unsigned int>(
739 index_kinds[
static_cast<unsigned int>(variant)]++;
748 unsigned int n_interleaved =
749 index_kinds[
static_cast<unsigned int>(
751 index_kinds[
static_cast<unsigned int>(
753 index_kinds[
static_cast<unsigned int>(
758 if (n_interleaved > 0 && index_kinds[
static_cast<unsigned int>(
760 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
766 index_kinds[
static_cast<unsigned int>(
768 index_kinds[
static_cast<unsigned int>(
774 if (n_interleaved > 0 &&
776 index_kinds[
static_cast<unsigned int>(
779 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
783 index_kinds[
static_cast<unsigned int>(
792 index_kinds[
static_cast<unsigned int>(
797 for (
unsigned int i = 0; i < irregular_cells.size(); ++i)
808 const unsigned int ndofs =
813 unsigned int *interleaved_dof_indices =
817 this->dof_indices_interleaved.size());
827 for (
unsigned int k = 0; k < ndofs; ++k)
829 const unsigned int *my_dof_indices =
dof_indices + k;
830 const unsigned int *
end =
832 for (; interleaved_dof_indices !=
end;
833 ++interleaved_dof_indices, my_dof_indices += ndofs)
834 *interleaved_dof_indices = *my_dof_indices;
844 const unsigned int n_owned_cells,
845 const unsigned int n_lanes,
848 const bool fill_cell_centric,
850 const bool use_vector_data_exchanger_full)
856 std::vector<types::global_dof_index> ghost_indices;
859 for (
unsigned int cell = 0; cell < n_owned_cells; ++cell)
868 const unsigned int fe_index =
877 ghost_indices.push_back(
880 std::sort(ghost_indices.begin(), ghost_indices.end());
882 compressed_set.
add_indices(ghost_indices.begin(), ghost_indices.end());
884 const bool all_ghosts_equal =
889 std::shared_ptr<const Utilities::MPI::Partitioner> temp_0;
891 if (all_ghosts_equal)
895 temp_0 = std::make_shared<Utilities::MPI::Partitioner>(
901 if (use_vector_data_exchanger_full ==
false)
907 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
908 temp_0, communicator_sm);
912 std::vector<FaceToCellTopology<1>> all_faces(inner_faces);
913 all_faces.insert(all_faces.end(),
914 ghosted_faces.begin(),
915 ghosted_faces.end());
918 2 * shape_info(0, 0).n_dimensions);
920 for (
unsigned int f = 0; f < all_faces.size(); ++f)
922 cell_and_face_to_faces(all_faces[f].cells_interior[0],
923 all_faces[f].interior_face_no) = f;
924 Assert(all_faces[f].cells_exterior[0] !=
927 cell_and_face_to_faces(all_faces[f].cells_exterior[0],
928 all_faces[f].exterior_face_no) = f;
932 const auto loop_over_faces =
933 [&](
const std::function<
934 void(
const unsigned int,
const unsigned int,
const bool)> &fu) {
935 for (
const auto &face : inner_faces)
938 fu(face.cells_exterior[0], face.exterior_face_no,
false );
942 const auto loop_over_all_faces =
943 [&](
const std::function<
944 void(
const unsigned int,
const unsigned int,
const bool)> &fu) {
945 for (
unsigned int c = 0; c < cell_and_face_to_faces.size(0); ++c)
946 for (
unsigned int d = 0; d < cell_and_face_to_faces.size(1); ++d)
948 const unsigned int f = cell_and_face_to_faces(c, d);
952 const unsigned int cell_m = all_faces[f].cells_interior[0];
953 const unsigned int cell_p = all_faces[f].cells_exterior[0];
955 const bool ext = c == cell_m;
960 const unsigned int p = ext ? cell_p : cell_m;
961 const unsigned int face_no = ext ?
962 all_faces[f].exterior_face_no :
963 all_faces[f].interior_face_no;
965 fu(p, face_no,
true);
969 const auto process_values =
971 std::shared_ptr<const Utilities::MPI::Partitioner>
972 &vector_partitioner_values,
973 const std::function<void(
974 const std::function<
void(
975 const unsigned int,
const unsigned int,
const bool)> &)> &loop) {
976 bool all_nodal_and_tensorial = shape_info.size(1) == 1;
978 if (all_nodal_and_tensorial)
983 if (!si.nodal_at_cell_boundaries ||
986 all_nodal_and_tensorial =
false;
989 if (all_nodal_and_tensorial ==
false)
993 bool has_noncontiguous_cell =
false;
995 loop([&](
const unsigned int cell_no,
996 const unsigned int face_no,
998 const unsigned int index =
1003 const unsigned int stride =
1004 dof_indices_interleave_strides[dof_access_cell][cell_no];
1006 for (unsigned int e = 0; e < n_base_elements; ++e)
1007 for (unsigned int c = 0; c < n_components[e]; ++c)
1009 const ShapeInfo<double> &shape =
1010 shape_info(global_base_element_offset + e, 0);
1011 for (unsigned int j = 0;
1012 j < shape.dofs_per_component_on_face;
1014 ghost_indices.push_back(part.local_to_global(
1016 shape.face_to_cell_index_nodal(face_no, j) *
1018 i += shape.dofs_per_component_on_cell * stride;
1023 has_noncontiguous_cell =
true;
1025 has_noncontiguous_cell =
1029 std::sort(ghost_indices.begin(), ghost_indices.end());
1032 ghost_indices.end());
1034 const bool all_ghosts_equal =
1038 if (all_ghosts_equal || has_noncontiguous_cell)
1042 vector_partitioner_values =
1043 std::make_shared<Utilities::MPI::Partitioner>(
1046 vector_partitioner_values.get())
1053 const auto process_gradients =
1055 const std::shared_ptr<const Utilities::MPI::Partitioner>
1056 &vector_partitoner_values,
1057 std::shared_ptr<const Utilities::MPI::Partitioner>
1058 &vector_partitioner_gradients,
1059 const std::function<void(
1060 const std::function<
void(
1061 const unsigned int,
const unsigned int,
const bool)> &)> &loop) {
1062 bool all_hermite = shape_info.
size(1) == 1;
1065 for (
unsigned int c = 0; c < n_base_elements; ++c)
1066 if (shape_info(global_base_element_offset + c, 0).element_type !=
1068 all_hermite =
false;
1069 if (all_hermite ==
false ||
1070 vector_partitoner_values.get() == vector_partitioner.get())
1071 vector_partitioner_gradients = vector_partitioner;
1074 loop([&](
const unsigned int cell_no,
1075 const unsigned int face_no,
1077 const unsigned int index =
1078 dof_indices_contiguous[dof_access_cell][cell_no];
1080 index >= part.locally_owned_size()))
1082 const unsigned int stride =
1083 dof_indices_interleave_strides[dof_access_cell][cell_no];
1085 for (unsigned int e = 0; e < n_base_elements; ++e)
1086 for (unsigned int c = 0; c < n_components[e]; ++c)
1088 const ShapeInfo<double> &shape =
1089 shape_info(global_base_element_offset + e, 0);
1090 for (unsigned int j = 0;
1091 j < 2 * shape.dofs_per_component_on_face;
1093 ghost_indices.push_back(part.local_to_global(
1095 shape.face_to_cell_index_hermite(face_no, j) *
1097 i += shape.dofs_per_component_on_cell * stride;
1102 std::sort(ghost_indices.begin(), ghost_indices.end());
1103 IndexSet compressed_set(part.size());
1104 compressed_set.add_indices(ghost_indices.begin(),
1105 ghost_indices.end());
1106 compressed_set.subtract_set(part.locally_owned_range());
1107 const bool all_ghosts_equal =
1109 part.ghost_indices().n_elements(),
1110 part.get_mpi_communicator());
1111 if (all_ghosts_equal)
1112 vector_partitioner_gradients = vector_partitioner;
1115 vector_partitioner_gradients =
1116 std::make_shared<Utilities::MPI::Partitioner>(
1117 part.locally_owned_range(), part.get_mpi_communicator());
1119 vector_partitioner_gradients.get())
1120 ->set_ghost_indices(compressed_set, part.ghost_indices());
1125 std::shared_ptr<const Utilities::MPI::Partitioner> temp_1, temp_2, temp_3,
1129 process_values(temp_1, loop_over_faces);
1132 process_gradients(temp_1, temp_2, loop_over_faces);
1134 if (fill_cell_centric)
1136 ghost_indices.clear();
1138 process_values(temp_3, loop_over_all_faces);
1140 process_gradients(temp_3, temp_4, loop_over_all_faces);
1144 temp_3 = std::make_shared<Utilities::MPI::Partitioner>(
1145 part.locally_owned_range(), part.get_mpi_communicator());
1146 temp_4 = std::make_shared<Utilities::MPI::Partitioner>(
1147 part.locally_owned_range(), part.get_mpi_communicator());
1150 if (use_vector_data_exchanger_full ==
false)
1152 vector_exchanger_face_variants[1] = std::make_shared<
1153 MatrixFreeFunctions::VectorDataExchange::PartitionerWrapper>(
1155 vector_exchanger_face_variants[2] = std::make_shared<
1156 MatrixFreeFunctions::VectorDataExchange::PartitionerWrapper>(
1158 vector_exchanger_face_variants[3] = std::make_shared<
1159 MatrixFreeFunctions::VectorDataExchange::PartitionerWrapper>(
1161 vector_exchanger_face_variants[4] = std::make_shared<
1162 MatrixFreeFunctions::VectorDataExchange::PartitionerWrapper>(
1167 vector_exchanger_face_variants[1] =
1168 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
1169 temp_1, communicator_sm);
1170 vector_exchanger_face_variants[2] =
1171 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
1172 temp_2, communicator_sm);
1173 vector_exchanger_face_variants[3] =
1174 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
1175 temp_3, communicator_sm);
1176 vector_exchanger_face_variants[4] =
1177 std::make_shared<MatrixFreeFunctions::VectorDataExchange::Full>(
1178 temp_4, communicator_sm);
1335 DoFInfo::make_connectivity_graph(
1337 const std::vector<unsigned int> &renumbering,
1340 unsigned int n_rows = (vector_partitioner->local_range().second -
1341 vector_partitioner->local_range().first) +
1342 vector_partitioner->ghost_indices().n_elements();
1349 std::vector<unsigned int> row_lengths(n_rows);
1350 std::vector<std::mutex> mutexes(n_rows / internal::bucket_size_threading +
1355 [
this, &mutexes, &row_lengths](
const unsigned int begin,
1356 const unsigned int end) {
1357 internal::compute_row_lengths(
1358 begin, end, *this, mutexes, row_lengths);
1364 for (
unsigned int row = 0; row < n_rows; ++row)
1365 if (row_lengths[row] <= 1)
1366 row_lengths[row] = 0;
1377 [
this, &row_lengths, &mutexes, &connectivity_dof](
1378 const unsigned int begin,
const unsigned int end) {
1379 internal::fill_connectivity_dofs(
1380 begin, end, *this, row_lengths, mutexes, connectivity_dof);
1387 std::vector<unsigned int> reverse_numbering(task_info.
n_active_cells);
1397 [
this, &reverse_numbering, &connectivity_dof, &connectivity](
1398 const unsigned int begin,
const unsigned int end) {
1399 internal::fill_connectivity(begin,