39 template <
int dim,
typename Number,
bool is_face_>
52 std::function<std::vector<std::unique_ptr<FEEvalType>>(
53 const std::pair<unsigned int, unsigned int> &)>
55 std::function<void(std::vector<std::unique_ptr<FEEvalType>> &,
58 std::function<void(std::vector<std::unique_ptr<FEEvalType>> &)>
68 template <
int dim,
typename AdditionalData>
71 AdditionalData &additional_data);
91 typename VectorizedArrayType,
96 VectorType &diagonal_global,
102 VectorizedArrayType> &)>
104 const unsigned int dof_handler_index = 0,
105 const unsigned int quadrature_index = 0,
106 const unsigned int first_selected_component = 0,
107 const unsigned int first_vector_component = 0);
118 typename QuadOperation>
123 const QuadOperation &quad_operation,
126 const unsigned int dof_handler_index = 0,
127 const unsigned int quadrature_index = 0,
128 const unsigned int first_selected_component = 0,
129 const unsigned int first_vector_component = 0);
134 template <
typename CLASS,
140 typename VectorizedArrayType,
145 VectorType &diagonal_global,
151 VectorizedArrayType> &) const,
152 const CLASS *owning_class,
153 const unsigned
int dof_handler_index = 0,
154 const unsigned
int quadrature_index = 0,
155 const unsigned
int first_selected_component = 0,
156 const unsigned
int first_vector_component = 0);
175 typename VectorizedArrayType,
180 VectorType &diagonal_global,
186 VectorizedArrayType> &)>
193 VectorizedArrayType> &,
199 VectorizedArrayType> &)>
206 VectorizedArrayType> &)>
208 const unsigned int dof_handler_index = 0,
209 const unsigned int quadrature_index = 0,
210 const unsigned int first_selected_component = 0,
211 const unsigned int first_vector_component = 0);
218 template <
typename CLASS,
224 typename VectorizedArrayType,
229 VectorType &diagonal_global,
235 VectorizedArrayType> &) const,
241 VectorizedArrayType> &,
247 VectorizedArrayType> &)
254 VectorizedArrayType> &)
256 const CLASS *owning_class,
257 const unsigned
int dof_handler_index = 0,
258 const unsigned
int quadrature_index = 0,
259 const unsigned
int first_selected_component = 0,
260 const unsigned
int first_vector_component = 0);
277 typename VectorizedArrayType,
289 VectorizedArrayType> &)>
291 const unsigned int dof_handler_index = 0,
292 const unsigned int quadrature_index = 0,
293 const unsigned int first_selected_component = 0);
300 template <
typename CLASS,
306 typename VectorizedArrayType,
318 VectorizedArrayType> &) const,
319 const CLASS *owning_class,
320 const unsigned
int dof_handler_index = 0,
321 const unsigned
int quadrature_index = 0,
322 const unsigned
int first_selected_component = 0);
333 typename VectorizedArrayType,
335 typename VectorType2>
345 VectorType &diagonal_global,
346 std::vector<VectorType2 *> &diagonal_global_components);
354 typename VectorizedArrayType,
385 typename VectorizedArrayType,
397 VectorizedArrayType> &)>
404 VectorizedArrayType> &,
410 VectorizedArrayType> &)>
417 VectorizedArrayType> &)>
419 const unsigned int dof_handler_index = 0,
420 const unsigned int quadrature_index = 0,
421 const unsigned int first_selected_component = 0);
428 template <
typename CLASS,
434 typename VectorizedArrayType,
446 VectorizedArrayType> &) const,
452 VectorizedArrayType> &,
458 VectorizedArrayType> &)
465 VectorizedArrayType> &)
467 const CLASS *owning_class,
468 const unsigned
int dof_handler_index = 0,
469 const unsigned
int quadrature_index = 0,
470 const unsigned
int first_selected_component = 0);
522 std::vector<unsigned int> valid_fe_indices;
524 const auto &fe_collection =
526 .get_fe_collection();
528 for (
unsigned int i = 0; i < fe_collection.size(); ++i)
529 if (fe_collection[i].n_dofs_per_cell() > 0)
530 valid_fe_indices.push_back(i);
544 template <
typename VectorTypeOut,
typename VectorTypeIn>
549 const VectorTypeIn &,
550 const std::pair<unsigned int, unsigned int> &)> &cell_operation,
552 const VectorTypeIn &src,
553 const bool zero_dst_vector =
false)
const
555 const auto ebd_cell_operation = [&](
const auto &
matrix_free,
559 const auto category =
matrix_free.get_cell_range_category(range);
567 matrix_free->template cell_loop<VectorTypeOut, VectorTypeIn>(
568 ebd_cell_operation, dst, src, zero_dst_vector);
578 template <
typename VectorTypeOut,
typename VectorTypeIn>
583 const VectorTypeIn &,
584 const std::pair<unsigned int, unsigned int> &)> &cell_operation,
588 const VectorTypeIn &,
589 const std::pair<unsigned int, unsigned int> &)> &face_operation,
593 const VectorTypeIn &,
594 const std::pair<unsigned int, unsigned int> &,
595 const bool)> &boundary_operation,
597 const VectorTypeIn &src,
598 const bool zero_dst_vector =
false)
const
600 const auto ebd_cell_operation = [&](
const auto &
matrix_free,
604 const auto category =
matrix_free.get_cell_range_category(range);
612 const auto ebd_internal_or_boundary_face_operation =
617 const auto category =
matrix_free.get_face_range_category(range);
619 const unsigned int type =
633 matrix_free->template loop<VectorTypeOut, VectorTypeIn>(
635 ebd_internal_or_boundary_face_operation,
636 ebd_internal_or_boundary_face_operation,
659 template <
int dim,
typename AdditionalData>
662 AdditionalData &additional_data)
665 const unsigned int level = additional_data.mg_level;
670 additional_data.cell_vectorization_category.assign(
673 additional_data.cell_vectorization_category.assign(tria.
n_active_cells(),
680 std::sort(bids.begin(), bids.end());
683 unsigned int n_bids = bids.size() + 1;
685 for (
unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell;
686 i++, offset = offset * n_bids)
690 const auto to_category = [&](
const auto &cell) {
691 unsigned int c_num = 0;
692 for (
unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell; ++i)
694 const auto face = cell->face(i);
695 if (face->at_boundary() && !cell->has_periodic_neighbor(i))
697 factors[i] * (1 + std::distance(bids.begin(),
698 std::find(bids.begin(),
700 face->boundary_id())));
709 if (cell->is_locally_owned())
711 .cell_vectorization_category[cell->active_cell_index()] =
719 if (cell->is_locally_owned_on_level())
720 additional_data.cell_vectorization_category[cell->index()] =
726 additional_data.hold_all_faces_to_owned_cells =
true;
727 additional_data.cell_vectorization_categories_strict =
true;
728 additional_data.mapping_update_flags_faces_by_cells =
729 additional_data.mapping_update_flags_inner_faces |
730 additional_data.mapping_update_flags_boundary_faces;
735 template <
typename Number>
738 std::vector<unsigned int> row_lid_to_gid;
739 std::vector<unsigned int> row;
740 std::vector<unsigned int> col;
741 std::vector<Number> val;
743 std::vector<unsigned int> inverse_lookup_rows;
744 std::vector<std::pair<unsigned int, unsigned int>> inverse_lookup_origins;
747 template <
int dim,
typename VectorizedArrayType,
bool is_face>
748 class ComputeDiagonalHelper
751 using FEEvaluationType =
754 using Number =
typename VectorizedArrayType::value_type;
755 static const unsigned int n_lanes = VectorizedArrayType::size();
757 ComputeDiagonalHelper()
759 , matrix_free(nullptr)
760 , dofs_per_component(0)
764 ComputeDiagonalHelper(
const ComputeDiagonalHelper &)
766 , matrix_free(nullptr)
767 , dofs_per_component(0)
773 FEEvaluationType &phi,
775 const unsigned int n_components)
779 if (dofs_per_component !=
780 phi.get_shape_info().dofs_per_component_on_cell)
782 locally_relevant_constraints_hn_map.
clear();
784 phi.get_shape_info().dofs_per_component_on_cell;
786 this->n_components = n_components;
787 this->dofs_per_cell = n_components * dofs_per_component;
789 this->matrix_free = &matrix_free;
793 reinit(
const unsigned int cell)
796 const auto &matrix_free = *this->matrix_free;
804 const unsigned int first_selected_component =
805 n_fe_components == 1 ? 0 : phi->get_first_selected_component();
807 this->n_lanes_filled =
814 const std::array<unsigned int, n_lanes> &cells =
815 this->phi->get_cell_ids();
817 inverse_lookup_count.resize(dofs_per_cell);
818 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
823 const unsigned int *dof_indices;
824 unsigned int index_indicators, next_index_indicators;
826 const unsigned int start =
827 cells[v] * n_fe_components + first_selected_component;
829 dof_info.dof_indices.data() + dof_info.row_starts[start].first;
830 index_indicators = dof_info.row_starts[start].second;
831 next_index_indicators = dof_info.row_starts[start + 1].second;
835 locally_relevant_constraints.clear();
837 if (n_components == 1 || n_fe_components == 1)
839 unsigned int ind_local = 0;
840 for (; index_indicators != next_index_indicators;
841 ++index_indicators, ++ind_local)
843 const std::pair<unsigned short, unsigned short> indicator =
844 dof_info.constraint_indicator[index_indicators];
846 for (
unsigned int j = 0; j < indicator.first;
848 locally_relevant_constraints.emplace_back(ind_local,
852 dof_indices += indicator.first;
859 for (; data_val != end_pool; ++data_val, ++dof_indices)
860 locally_relevant_constraints.emplace_back(ind_local,
867 for (; ind_local < dofs_per_component;
868 ++dof_indices, ++ind_local)
869 locally_relevant_constraints.emplace_back(ind_local,
880 for (
unsigned int comp = 0; comp < n_components; ++comp)
882 unsigned int ind_local = 0;
886 for (; index_indicators != next_index_indicators;
887 ++index_indicators, ++ind_local)
889 const std::pair<unsigned short, unsigned short>
891 dof_info.constraint_indicator[index_indicators];
894 for (
unsigned int j = 0; j < indicator.first;
896 locally_relevant_constraints.emplace_back(
897 comp * dofs_per_component + ind_local,
900 dof_indices += indicator.first;
907 for (; data_val != end_pool; ++data_val, ++dof_indices)
908 locally_relevant_constraints.emplace_back(
909 comp * dofs_per_component + ind_local,
917 for (; ind_local < dofs_per_component;
918 ++dof_indices, ++ind_local)
919 locally_relevant_constraints.emplace_back(
920 comp * dofs_per_component + ind_local,
924 if (comp + 1 < n_components)
925 next_index_indicators =
926 dof_info.row_starts[start + comp + 2].second;
933 for (
unsigned int i = 1; i < locally_relevant_constraints.size();
935 Assert(std::get<0>(locally_relevant_constraints[i]) >=
936 std::get<0>(locally_relevant_constraints[i - 1]),
940 if (dof_info.hanging_node_constraint_masks.size() > 0 &&
941 dof_info.hanging_node_constraint_masks_comp.size() > 0 &&
942 dof_info.hanging_node_constraint_masks_comp
943 [phi->get_active_fe_index()][first_selected_component])
946 dof_info.hanging_node_constraint_masks[cells[v]];
949 if (mask != ::internal::MatrixFreeFunctions::
954 if (locally_relevant_constraints_hn_map.find(mask) ==
955 locally_relevant_constraints_hn_map.end())
956 fill_constraint_type_into_map(mask);
958 const auto &locally_relevant_constraints_hn =
959 locally_relevant_constraints_hn_map[
mask];
961 locally_relevant_constraints_tmp.clear();
962 if (locally_relevant_constraints_tmp.capacity() <
963 locally_relevant_constraints.size())
964 locally_relevant_constraints_tmp.reserve(
965 locally_relevant_constraints.size() +
966 locally_relevant_constraints_hn.size());
971 constraint_position.assign(dofs_per_cell,
973 for (
auto &a : locally_relevant_constraints)
974 if (constraint_position[
std::get<0>(a)] ==
976 constraint_position[
std::get<0>(a)] =
977 std::distance(locally_relevant_constraints.
data(),
979 is_constrained_hn.assign(dofs_per_cell,
false);
980 for (
auto &hn : locally_relevant_constraints_hn)
981 is_constrained_hn[
std::get<0>(hn)] = 1;
984 for (
const auto &a : locally_relevant_constraints)
985 if (is_constrained_hn[
std::get<0>(a)] == 0)
986 locally_relevant_constraints_tmp.
push_back(a);
990 for (
const auto &hn : locally_relevant_constraints_hn)
991 if (constraint_position[
std::get<1>(hn)] !=
995 locally_relevant_constraints.size());
996 auto other = locally_relevant_constraints.begin() +
997 constraint_position[std::get<1>(hn)];
1000 for (; other != locally_relevant_constraints.end() &&
1001 std::get<0>(*other) == std::get<1>(hn);
1003 locally_relevant_constraints_tmp.emplace_back(
1005 std::get<1>(*other),
1006 std::get<2>(hn) * std::get<2>(*other));
1009 std::swap(locally_relevant_constraints,
1010 locally_relevant_constraints_tmp);
1015 std::sort(locally_relevant_constraints.begin(),
1016 locally_relevant_constraints.end(),
1017 [](
const auto &a,
const auto &b) {
1018 if (std::get<1>(a) < std::get<1>(b))
1020 return (std::get<1>(a) == std::get<1>(b)) &&
1021 (std::get<0>(a) < std::get<0>(b));
1025 auto &c_pool = c_pools[v];
1027 c_pool.row_lid_to_gid.clear();
1029 c_pool.row.push_back(0);
1033 if (locally_relevant_constraints.size() > 0)
1034 c_pool.row_lid_to_gid.emplace_back(
1035 std::get<1>(locally_relevant_constraints.front()));
1036 for (
const auto &j : locally_relevant_constraints)
1038 if (c_pool.row_lid_to_gid.back() != std::get<1>(j))
1040 c_pool.row_lid_to_gid.push_back(std::get<1>(j));
1041 c_pool.row.push_back(c_pool.val.size());
1044 c_pool.col.emplace_back(std::get<0>(j));
1045 c_pool.val.emplace_back(std::get<2>(j));
1048 if (c_pool.val.size() > 0)
1049 c_pool.row.push_back(c_pool.val.size());
1051 c_pool.inverse_lookup_rows.clear();
1052 c_pool.inverse_lookup_rows.resize(1 + dofs_per_cell);
1053 for (
const unsigned int i : c_pool.col)
1054 c_pool.inverse_lookup_rows[1 + i]++;
1056 std::partial_sum(c_pool.inverse_lookup_rows.begin(),
1057 c_pool.inverse_lookup_rows.end(),
1058 c_pool.inverse_lookup_rows.begin());
1062 c_pool.inverse_lookup_origins.resize(c_pool.col.size());
1063 std::fill(inverse_lookup_count.begin(),
1064 inverse_lookup_count.end(),
1066 for (
unsigned int row = 0; row < c_pool.row.size() - 1; ++row)
1067 for (
unsigned int col = c_pool.row[row];
1068 col < c_pool.row[row + 1];
1071 const unsigned int index = c_pool.col[col];
1072 c_pool.inverse_lookup_origins
1073 [c_pool.inverse_lookup_rows[
index] +
1074 inverse_lookup_count[
index]] = std::make_pair(row, col);
1075 ++inverse_lookup_count[
index];
1104 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
1105 diagonals_local_constrained[v].assign(
1106 c_pools[v].row_lid_to_gid.size() *
1107 (n_fe_components == 1 ? n_components : 1),
1111 bool use_fast_path =
true;
1113 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
1115 auto &c_pool = c_pools[v];
1117 for (
unsigned int i = 0; i < c_pool.row.size() - 1; ++i)
1119 if ((c_pool.row[i + 1] - c_pool.row[i]) > 1)
1121 use_fast_path =
false;
1124 else if (((c_pool.row[i + 1] - c_pool.row[i]) == 1) &&
1125 (c_pool.val[c_pool.row[i]] != 1.0))
1127 use_fast_path =
false;
1132 if (use_fast_path ==
false)
1136 this->has_simple_constraints_ = use_fast_path;
1140 fill_constraint_type_into_map(
1141 const ::internal::MatrixFreeFunctions::compressed_constraint_kind
1144 auto &constraints_hn = locally_relevant_constraints_hn_map[
mask];
1149 const unsigned int degree =
1150 phi->get_shape_info().data.front().fe_degree;
1155 values_dofs.resize(dofs_per_component);
1158 VectorizedArrayType::size()>
1160 constraint_mask.fill(::internal::MatrixFreeFunctions::
1162 constraint_mask[0] =
mask;
1164 for (
unsigned int i = 0; i < dofs_per_component; ++i)
1166 for (
unsigned int j = 0; j < dofs_per_component; ++j)
1167 values_dofs[j] = VectorizedArrayType();
1168 values_dofs[i] =
Number(1);
1173 VectorizedArrayType>::apply(1,
1175 phi->get_shape_info(),
1178 values_dofs.data());
1182 std::numeric_limits<Number>::epsilon() * 16);
1183 for (
unsigned int j = 0; j < dofs_per_component; ++j)
1184 if (
std::abs(values_dofs[j][0]) > tolerance &&
1187 constraints_hn.emplace_back(j, i, values_dofs[j][0]);
1191 const unsigned int n_hn_constraints = constraints_hn.size();
1192 constraints_hn.resize(n_hn_constraints * n_components);
1194 for (
unsigned int c = 1; c < n_components; ++c)
1195 for (
unsigned int i = 0; i < n_hn_constraints; ++i)
1196 constraints_hn[c * n_hn_constraints + i] = std::make_tuple(
1197 std::get<0>(constraints_hn[i]) + c * dofs_per_component,
1198 std::get<1>(constraints_hn[i]) + c * dofs_per_component,
1199 std::get<2>(constraints_hn[i]));
1203 prepare_basis_vector(
const unsigned int i)
1210 VectorizedArrayType *dof_values = phi->begin_dof_values();
1211 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
1212 dof_values[j] = VectorizedArrayType();
1213 dof_values[i] =
Number(1);
1219 VectorizedArrayType *dof_values = phi->begin_dof_values();
1220 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
1221 dof_values[j] = VectorizedArrayType();
1230 const unsigned int n_fe_components =
1231 phi->get_dof_info().start_components.back();
1232 const unsigned int comp =
1233 n_fe_components == 1 ? i / dofs_per_component : 0;
1234 const unsigned int i_comp =
1235 n_fe_components == 1 ? (i % dofs_per_component) : i;
1239 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
1241 const auto &c_pool = c_pools[v];
1243 for (
unsigned int jj = c_pool.inverse_lookup_rows[i_comp];
1244 jj < c_pool.inverse_lookup_rows[i_comp + 1];
1247 const unsigned int j = c_pool.inverse_lookup_origins[jj].first;
1250 for (
unsigned int k = c_pool.row[j]; k < c_pool.row[j + 1]; ++k)
1251 temp += c_pool.val[k] *
1252 phi->begin_dof_values()[comp * dofs_per_component +
1256 diagonals_local_constrained
1257 [v][j + comp * c_pools[v].row_lid_to_gid.size()] +=
1258 temp * c_pool.val[c_pool.inverse_lookup_origins[jj].second];
1263 template <
typename VectorType>
1265 distribute_local_to_global(std::vector<VectorType *> &diagonal_global)
1268 const unsigned int n_fe_components =
1269 phi->get_dof_info().start_components.back();
1271 if (n_fe_components == 1)
1274 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
1278 for (
unsigned int j = 0; j < c_pools[v].row.size() - 1; ++j)
1279 for (
unsigned int comp = 0;
1280 comp < (n_fe_components == 1 ?
1281 static_cast<unsigned int>(n_components) :
1286 *diagonal_global[n_fe_components == 1 ? comp : 0],
1287 c_pools[v].row_lid_to_gid[j],
1288 diagonals_local_constrained
1289 [v][j + comp * c_pools[v].row_lid_to_gid.
size()]);
1293 has_simple_constraints()
const
1295 return has_simple_constraints_;
1299 FEEvaluationType *phi;
1302 unsigned int dofs_per_component;
1303 unsigned int dofs_per_cell;
1304 unsigned int n_components;
1308 unsigned int n_lanes_filled;
1310 std::array<internal::LocalCSR<Number>, n_lanes> c_pools;
1315 std::array<std::vector<Number>, n_lanes> diagonals_local_constrained;
1319 std::vector<std::tuple<unsigned int, unsigned int, Number>>>
1320 locally_relevant_constraints_hn_map;
1325 std::vector<std::tuple<unsigned int, unsigned int, Number>>
1326 locally_relevant_constraints;
1327 std::vector<std::tuple<unsigned int, unsigned int, Number>>
1328 locally_relevant_constraints_tmp;
1329 std::vector<unsigned int> constraint_position;
1330 std::vector<unsigned char> is_constrained_hn;
1331 std::vector<unsigned int> inverse_lookup_count;
1333 bool has_simple_constraints_;
1336 template <
bool is_face,
1339 typename VectorizedArrayType>
1343 const std::pair<unsigned int, unsigned int> &range,
1344 const unsigned int dof_handler_index,
1345 const unsigned int quadrature_index,
1346 const unsigned int first_selected_component,
1347 const unsigned int fe_degree,
1348 const unsigned int n_q_points_1d,
1349 const bool is_interior_face =
true)
1351 const unsigned int static_n_q_points =
1355 unsigned int active_fe_index = 0;
1359 else if (is_interior_face)
1366 const auto init_data = ::internal::
1367 extract_initialization_data<is_face, dim, Number, VectorizedArrayType>(
1370 first_selected_component,
1378 return init_data.shape_info->dofs_per_component_on_cell == 0;
1391 typename QuadOperation>
1392 class ComputeDiagonalCellAction
1395 ComputeDiagonalCellAction(
1396 const unsigned int dof_handler_index,
1397 const QuadOperation &quad_operation,
1400 : m_dof_handler_index(dof_handler_index)
1401 , m_quad_operation(quad_operation)
1402 , m_evaluation_flags(evaluation_flags)
1403 , m_integration_flags(integration_flags)
1406 KOKKOS_FUNCTION
void
1412 FEEvaluation<dim, fe_degree, n_q_points_1d, n_components, Number>
1413 fe_eval(
data, m_dof_handler_index);
1415 *gpu_data = &
data->precomputed_data[m_dof_handler_index];
1416 const int cell =
data->cell_index;
1418 constexpr int dofs_per_cell =
decltype(fe_eval)::tensor_dofs_per_cell;
1420 diagonal[dofs_per_cell / n_components] = {};
1421 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
1423 const auto c = i % n_components;
1425 Kokkos::parallel_for(
1426 Kokkos::TeamThreadRange(
data->team_member,
1427 dofs_per_cell / n_components),
1428 [&](
unsigned int j) {
1429 typename decltype(fe_eval)::value_type val = {};
1431 if constexpr (n_components == 1)
1433 val = (i == j) ? 1 : 0;
1437 val[c] = (i / n_components == j) ? 1 : 0;
1440 fe_eval.submit_dof_value(val, j);
1443 data->team_member.team_barrier();
1445 Portable::internal::
1446 resolve_hanging_nodes<dim, fe_degree, false, Number>(
1450 Kokkos::subview(
data->shared_data[m_dof_handler_index].values,
1454 fe_eval.evaluate(m_evaluation_flags);
1455 data->for_each_quad_point(
1456 [&](
const int &q_point) { m_quad_operation(&fe_eval, q_point); });
1457 fe_eval.integrate(m_integration_flags);
1459 Portable::internal::
1460 resolve_hanging_nodes<dim, fe_degree, true, Number>(
1464 Kokkos::subview(
data->shared_data[m_dof_handler_index].values,
1468 Kokkos::single(Kokkos::PerTeam(
data->team_member), [&] {
1469 if constexpr (n_components == 1)
1470 diagonal[i] = fe_eval.get_dof_value(i);
1472 diagonal[i / n_components][i % n_components] =
1473 fe_eval.get_dof_value(i / n_components)[i % n_components];
1476 data->team_member.team_barrier();
1479 Kokkos::single(Kokkos::PerTeam(
data->team_member), [&] {
1480 for (unsigned int i = 0; i < dofs_per_cell / n_components; ++i)
1481 fe_eval.submit_dof_value(diagonal[i], i);
1484 data->team_member.team_barrier();
1490 Kokkos::parallel_for(
1491 Kokkos::TeamThreadRange(
data->team_member, dofs_per_cell),
1493 dst[gpu_data->local_to_global(i, cell)] +=
1494 data->shared_data[m_dof_handler_index].values(
1495 i % (dofs_per_cell / n_components),
1496 i / (dofs_per_cell / n_components));
1501 Kokkos::parallel_for(
1502 Kokkos::TeamThreadRange(
data->team_member, dofs_per_cell),
1504 Kokkos::atomic_add(&dst[gpu_data->local_to_global(i, cell)],
1505 data->shared_data[m_dof_handler_index]
1506 .values(i % (dofs_per_cell / n_components),
1508 (dofs_per_cell / n_components)));
1513 static constexpr unsigned int n_q_points =
1517 const unsigned int m_dof_handler_index;
1518 const QuadOperation m_quad_operation;
1533 typename QuadOperation>
1538 const QuadOperation &quad_operation,
1541 const unsigned int dof_handler_index,
1542 const unsigned int quadrature_index,
1543 const unsigned int first_selected_component,
1544 const unsigned int first_vector_component)
1553 internal::ComputeDiagonalCellAction<dim,
1564 matrix_free.
cell_loop(cell_action, dummy, diagonal_global);
1576 typename VectorizedArrayType,
1581 VectorType &diagonal_global,
1587 VectorizedArrayType> &)>
1589 const unsigned int dof_handler_index,
1590 const unsigned int quadrature_index,
1591 const unsigned int first_selected_component,
1592 const unsigned int first_vector_component)
1599 VectorizedArrayType,
1607 first_selected_component,
1608 first_vector_component);
1611 template <
typename CLASS,
1617 typename VectorizedArrayType,
1622 VectorType &diagonal_global,
1628 VectorizedArrayType> &)
const,
1629 const CLASS *owning_class,
1630 const unsigned
int dof_handler_index,
1631 const unsigned
int quadrature_index,
1632 const unsigned
int first_selected_component,
1633 const unsigned
int first_vector_component)
1640 VectorizedArrayType,
1644 [&](
auto &phi) { (owning_class->*cell_operation)(phi); },
1647 first_selected_component,
1648 first_vector_component);
1656 typename VectorizedArrayType,
1661 VectorType &diagonal_global,
1667 VectorizedArrayType> &)>
1674 VectorizedArrayType> &,
1680 VectorizedArrayType> &)>
1687 VectorizedArrayType> &)>
1688 &boundary_operation,
1689 const unsigned int dof_handler_index,
1690 const unsigned int quadrature_index,
1691 const unsigned int first_selected_component,
1692 const unsigned int first_vector_component)
1694 std::vector<typename ::internal::BlockVectorSelector<
1697 diagonal_global_components(n_components);
1699 for (
unsigned int d = 0;
d < n_components; ++
d)
1700 diagonal_global_components[d] = ::internal::
1702 get_vector_component(diagonal_global,
d + first_vector_component);
1704 const auto &dof_info = matrix_free.
get_dof_info(dof_handler_index);
1706 if (dof_info.start_components.back() == 1)
1707 for (
unsigned int comp = 0; comp < n_components; ++comp)
1709 Assert(diagonal_global_components[comp] !=
nullptr,
1710 ExcMessage(
"The finite element underlying this FEEvaluation "
1711 "object is scalar, but you requested " +
1712 std::to_string(n_components) +
1713 " components via the template argument in "
1714 "FEEvaluation. In that case, you must pass an "
1715 "std::vector<VectorType> or a BlockVector to " +
1716 "read_dof_values and distribute_local_to_global."));
1718 *diagonal_global_components[comp], matrix_free, dof_info);
1723 *diagonal_global_components[0], matrix_free, dof_info);
1731 VectorizedArrayType>;
1738 VectorizedArrayType>;
1740 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, false>
1743 data_cell.dof_numbers = {dof_handler_index};
1744 data_cell.quad_numbers = {quadrature_index};
1745 data_cell.n_components = {n_components};
1746 data_cell.first_selected_components = {first_selected_component};
1747 data_cell.batch_type = {0};
1749 data_cell.op_create =
1750 [&](
const std::pair<unsigned int, unsigned int> &range) {
1752 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, false>>>
1755 if (!internal::is_fe_nothing<false>(matrix_free,
1759 first_selected_component,
1763 std::make_unique<FEEvalType>(matrix_free,
1767 first_selected_component));
1772 data_cell.op_reinit = [](
auto &phi,
const unsigned batch) {
1773 if (phi.size() == 1)
1774 static_cast<FEEvalType &
>(*phi[0]).reinit(batch);
1778 data_cell.op_compute = [&](
auto &phi) {
1779 cell_operation(
static_cast<FEEvalType &
>(*phi[0]));
1782 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
1785 data_face.dof_numbers = {dof_handler_index, dof_handler_index};
1786 data_face.quad_numbers = {quadrature_index, quadrature_index};
1787 data_face.n_components = {n_components, n_components};
1788 data_face.first_selected_components = {first_selected_component,
1789 first_selected_component};
1790 data_face.batch_type = {1, 2};
1792 data_face.op_create =
1793 [&](
const std::pair<unsigned int, unsigned int> &range) {
1795 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, true>>>
1798 if (!internal::is_fe_nothing<true>(matrix_free,
1802 first_selected_component,
1806 !internal::is_fe_nothing<true>(matrix_free,
1810 first_selected_component,
1816 std::make_unique<FEFaceEvalType>(matrix_free,
1821 first_selected_component));
1823 std::make_unique<FEFaceEvalType>(matrix_free,
1828 first_selected_component));
1834 data_face.op_reinit = [](
auto &phi,
const unsigned batch) {
1835 if (phi.size() == 2)
1837 static_cast<FEFaceEvalType &
>(*phi[0]).
reinit(batch);
1838 static_cast<FEFaceEvalType &
>(*phi[1]).
reinit(batch);
1843 data_face.op_compute = [&](
auto &phi) {
1844 face_operation(
static_cast<FEFaceEvalType &
>(*phi[0]),
1845 static_cast<FEFaceEvalType &
>(*phi[1]));
1848 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
1851 data_boundary.dof_numbers = {dof_handler_index};
1852 data_boundary.quad_numbers = {quadrature_index};
1853 data_boundary.n_components = {n_components};
1854 data_boundary.first_selected_components = {first_selected_component};
1855 data_boundary.batch_type = {1};
1857 data_boundary.op_create =
1858 [&](
const std::pair<unsigned int, unsigned int> &range) {
1860 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, true>>>
1863 if (!internal::is_fe_nothing<true>(matrix_free,
1867 first_selected_component,
1872 std::make_unique<FEFaceEvalType>(matrix_free,
1877 first_selected_component));
1882 data_boundary.op_reinit = [](
auto &phi,
const unsigned batch) {
1883 if (phi.size() == 1)
1884 static_cast<FEFaceEvalType &
>(*phi[0]).reinit(batch);
1887 if (boundary_operation)
1888 data_boundary.op_compute = [&](
auto &phi) {
1889 boundary_operation(
static_cast<FEFaceEvalType &
>(*phi[0]));
1892 internal::compute_diagonal(matrix_free,
1897 diagonal_global_components);
1904 typename VectorizedArrayType,
1906 typename VectorType2>
1910 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, false>
1912 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
1914 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
1916 VectorType &diagonal_global,
1917 std::vector<VectorType2 *> &diagonal_global_components)
1924 internal::ComputeDiagonalHelper<dim, VectorizedArrayType, false>;
1927 internal::ComputeDiagonalHelper<dim, VectorizedArrayType, true>;
1931 scratch_data_internal;
1934 const auto batch_operation =
1937 const std::pair<unsigned int, unsigned int> &range) {
1938 if (!
data.op_compute)
1941 auto phi =
data.op_create(range);
1943 const unsigned int n_blocks = phi.size();
1945 auto &helpers = scratch_data.
get();
1946 helpers.resize(n_blocks);
1949 helpers[b].initialize(*phi[b], matrix_free,
data.n_components[b]);
1951 for (
unsigned int batch = range.first; batch < range.second; ++batch)
1953 data.op_reinit(phi, batch);
1956 helpers[b].
reinit(batch);
1960 Assert(std::all_of(helpers.begin(),
1962 [](
const auto &helper) {
1963 return helper.has_simple_constraints();
1970 for (
unsigned int i = 0;
1971 i < phi[
b]->get_shape_info().dofs_per_component_on_cell *
1972 data.n_components[b];
1975 for (
unsigned int bb = 0; bb <
n_blocks; ++bb)
1977 helpers[bb].prepare_basis_vector(i);
1979 helpers[bb].zero_basis_vector();
1981 data.op_compute(phi);
1982 helpers[
b].submit();
1985 helpers[
b].distribute_local_to_global(
1986 diagonal_global_components);
1991 const auto cell_operation_wrapped =
1992 [&](
const auto &,
auto &,
const auto &,
const auto range) {
1993 batch_operation(data_cell, scratch_data, range);
1996 const auto face_operation_wrapped =
1997 [&](
const auto &,
auto &,
const auto &,
const auto range) {
1998 batch_operation(data_face, scratch_data_internal, range);
2001 const auto boundary_operation_wrapped =
2002 [&](
const auto &,
auto &,
const auto &,
const auto range) {
2003 batch_operation(data_boundary, scratch_data_bc, range);
2006 if (data_face.op_compute || data_boundary.op_compute)
2007 matrix_free.template loop<VectorType, int>(cell_operation_wrapped,
2008 face_operation_wrapped,
2009 boundary_operation_wrapped,
2014 matrix_free.template cell_loop<VectorType, int>(cell_operation_wrapped,
2021 template <
typename CLASS,
2027 typename VectorizedArrayType,
2032 VectorType &diagonal_global,
2038 VectorizedArrayType> &)
const,
2044 VectorizedArrayType> &,
2050 VectorizedArrayType> &)
2057 VectorizedArrayType> &)
2059 const CLASS *owning_class,
2060 const unsigned
int dof_handler_index,
2061 const unsigned
int quadrature_index,
2062 const unsigned
int first_selected_component,
2063 const unsigned
int first_vector_component)
2070 VectorizedArrayType,
2074 [&](
auto &phi) { (owning_class->*cell_operation)(phi); },
2075 [&](
auto &phi_m,
auto &phi_p) {
2076 (owning_class->*face_operation)(phi_m, phi_p);
2078 [&](
auto &phi) { (owning_class->*boundary_operation)(phi); },
2081 first_selected_component,
2082 first_vector_component);
2094 std::enable_if_t<std::is_same_v<
2095 std::remove_const_t<
2096 std::remove_reference_t<typename MatrixType::value_type>>,
2097 std::remove_const_t<std::remove_reference_t<Number>>>> * =
nullptr>
2099 create_new_affine_constraints_if_needed(
2115 std::enable_if_t<!std::is_same_v<
2116 std::remove_const_t<
2117 std::remove_reference_t<typename MatrixType::value_type>>,
2118 std::remove_const_t<std::remove_reference_t<Number>>>> * =
nullptr>
2120 create_new_affine_constraints_if_needed(
2127 std::make_unique<AffineConstraints<typename MatrixType::value_type>>();
2128 new_constraints->
copy_from(constraints);
2130 return *new_constraints;
2139 typename VectorizedArrayType,
2151 VectorizedArrayType> &)>
2153 const unsigned int dof_handler_index,
2154 const unsigned int quadrature_index,
2155 const unsigned int first_selected_component)
2162 VectorizedArrayType,
2171 first_selected_component);
2174 template <
typename CLASS,
2180 typename VectorizedArrayType,
2192 VectorizedArrayType> &)
const,
2193 const CLASS *owning_class,
2194 const unsigned
int dof_handler_index,
2195 const unsigned
int quadrature_index,
2196 const unsigned
int first_selected_component)
2203 VectorizedArrayType,
2208 [&](
auto &phi) { (owning_class->*cell_operation)(phi); },
2211 first_selected_component);
2219 typename VectorizedArrayType,
2231 VectorizedArrayType> &)>
2238 VectorizedArrayType> &,
2244 VectorizedArrayType> &)>
2251 VectorizedArrayType> &)>
2252 &boundary_operation,
2253 const unsigned int dof_handler_index,
2254 const unsigned int quadrature_index,
2255 const unsigned int first_selected_component)
2262 VectorizedArrayType>;
2269 VectorizedArrayType>;
2271 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, false>
2274 data_cell.dof_numbers = {dof_handler_index};
2275 data_cell.quad_numbers = {quadrature_index};
2276 data_cell.n_components = {n_components};
2277 data_cell.first_selected_components = {first_selected_component};
2278 data_cell.batch_type = {0};
2280 data_cell.op_create =
2281 [&](
const std::pair<unsigned int, unsigned int> &range) {
2283 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, false>>>
2286 if (!internal::is_fe_nothing<false>(matrix_free,
2290 first_selected_component,
2294 std::make_unique<FEEvalType>(matrix_free,
2298 first_selected_component));
2303 data_cell.op_reinit = [](
auto &phi,
const unsigned batch) {
2304 if (phi.size() == 1)
2305 static_cast<FEEvalType &
>(*phi[0]).reinit(batch);
2309 data_cell.op_compute = [&](
auto &phi) {
2310 cell_operation(
static_cast<FEEvalType &
>(*phi[0]));
2313 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
2316 data_face.dof_numbers = {dof_handler_index, dof_handler_index};
2317 data_face.quad_numbers = {quadrature_index, quadrature_index};
2318 data_face.n_components = {n_components, n_components};
2319 data_face.first_selected_components = {first_selected_component,
2320 first_selected_component};
2321 data_face.batch_type = {1, 2};
2323 data_face.op_create =
2324 [&](
const std::pair<unsigned int, unsigned int> &range) {
2326 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, true>>>
2329 if (!internal::is_fe_nothing<true>(matrix_free,
2333 first_selected_component,
2337 !internal::is_fe_nothing<true>(matrix_free,
2341 first_selected_component,
2347 std::make_unique<FEFaceEvalType>(matrix_free,
2352 first_selected_component));
2354 std::make_unique<FEFaceEvalType>(matrix_free,
2359 first_selected_component));
2365 data_face.op_reinit = [](
auto &phi,
const unsigned batch) {
2366 if (phi.size() == 2)
2368 static_cast<FEFaceEvalType &
>(*phi[0]).
reinit(batch);
2369 static_cast<FEFaceEvalType &
>(*phi[1]).
reinit(batch);
2374 data_face.op_compute = [&](
auto &phi) {
2375 face_operation(
static_cast<FEFaceEvalType &
>(*phi[0]),
2376 static_cast<FEFaceEvalType &
>(*phi[1]));
2379 internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
2382 data_boundary.dof_numbers = {dof_handler_index};
2383 data_boundary.quad_numbers = {quadrature_index};
2384 data_boundary.n_components = {n_components};
2385 data_boundary.first_selected_components = {first_selected_component};
2386 data_boundary.batch_type = {1};
2388 data_boundary.op_create =
2389 [&](
const std::pair<unsigned int, unsigned int> &range) {
2391 std::unique_ptr<FEEvaluationData<dim, VectorizedArrayType, true>>>
2394 if (!internal::is_fe_nothing<true>(matrix_free,
2398 first_selected_component,
2403 std::make_unique<FEFaceEvalType>(matrix_free,
2408 first_selected_component));
2413 data_boundary.op_reinit = [](
auto &phi,
const unsigned batch) {
2414 if (phi.size() == 1)
2415 static_cast<FEFaceEvalType &
>(*phi[0]).reinit(batch);
2418 if (boundary_operation)
2419 data_boundary.op_compute = [&](
auto &phi) {
2420 boundary_operation(
static_cast<FEFaceEvalType &
>(*phi[0]));
2423 internal::compute_matrix(
2424 matrix_free, constraints_in, data_cell, data_face, data_boundary, matrix);
2431 typename VectorizedArrayType,
2437 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, false>
2439 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
2441 const internal::ComputeMatrixScratchData<dim, VectorizedArrayType, true>
2445 std::unique_ptr<AffineConstraints<typename MatrixType::value_type>>
2446 constraints_for_matrix;
2448 internal::create_new_affine_constraints_if_needed(
2449 matrix, constraints_in, constraints_for_matrix);
2451 const auto batch_operation =
2452 [&matrix_free, &constraints, &
matrix](
2453 auto &
data,
const std::pair<unsigned int, unsigned int> &range) {
2454 if (!
data.op_compute)
2457 auto phi =
data.op_create(range);
2459 const unsigned int n_blocks = phi.size();
2468 n_blocks, VectorizedArrayType::size());
2471 std::array<FullMatrix<typename MatrixType::value_type>,
2472 VectorizedArrayType::size()>>
2473 matrices(n_blocks, n_blocks);
2478 .get_fe(phi[b]->get_active_fe_index());
2480 const auto component_base =
2483 const auto component_in_base =
2484 data.first_selected_components[
b] -
2489 data.dof_numbers[b],
2490 data.quad_numbers[b],
2492 phi[b]->get_active_fe_index(),
2493 phi[b]->get_active_quadrature_index());
2496 shape_info.dofs_per_component_on_cell *
data.n_components[
b];
2498 dof_indices[
b].resize(fe.n_dofs_per_cell());
2500 for (
unsigned int v = 0; v < VectorizedArrayType::size(); ++v)
2501 dof_indices_mf[b][v].resize(dofs_per_cell[b]);
2503 lexicographic_numbering[
b].insert(
2504 lexicographic_numbering[b].
begin(),
2505 shape_info.lexicographic_numbering.begin() +
2506 component_in_base * shape_info.dofs_per_component_on_cell,
2507 shape_info.lexicographic_numbering.begin() +
2508 (component_in_base +
data.n_components[
b]) *
2509 shape_info.dofs_per_component_on_cell);
2512 for (
unsigned int bj = 0; bj <
n_blocks; ++bj)
2513 for (
unsigned int bi = 0; bi <
n_blocks; ++bi)
2514 std::fill_n(matrices[bi][bj].
begin(),
2515 VectorizedArrayType::size(),
2517 dofs_per_cell[bi], dofs_per_cell[bj]));
2519 for (
auto batch = range.first; batch < range.second; ++batch)
2521 data.op_reinit(phi, batch);
2523 const unsigned int n_filled_lanes =
2528 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2532 (
data.batch_type[
b] == 0) ?
2533 (batch * VectorizedArrayType::size() + v) :
2534 ((
data.batch_type[
b] == 1) ?
2535 matrix_free.get_face_info(batch).cells_interior[v] :
2536 matrix_free.get_face_info(batch).cells_exterior[v]);
2541 data.dof_numbers[b]);
2545 cell_iterator->get_mg_dof_indices(dof_indices[b]);
2547 cell_iterator->get_dof_indices(dof_indices[b]);
2549 for (
unsigned int j = 0; j < dofs_per_cell[
b]; ++j)
2550 dof_indices_mf[b][v][j] =
2551 dof_indices[b][lexicographic_numbering[b][j]];
2554 for (
unsigned int bj = 0; bj <
n_blocks; ++bj)
2556 for (
unsigned int j = 0; j < dofs_per_cell[bj]; ++j)
2558 for (
unsigned int bi = 0; bi <
n_blocks; ++bi)
2559 for (
unsigned int i = 0; i < dofs_per_cell[bi]; ++i)
2560 phi[bi]->begin_dof_values()[i] =
2561 (bj == bi) ?
static_cast<Number>(i == j) : 0.0;
2563 data.op_compute(phi);
2565 for (
unsigned int bi = 0; bi <
n_blocks; ++bi)
2566 for (
unsigned int i = 0; i < dofs_per_cell[bi]; ++i)
2567 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2568 matrices[bi][bj][v](i, j) =
2569 phi[bi]->begin_dof_values()[i][v];
2572 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
2573 for (
unsigned int bi = 0; bi <
n_blocks; ++bi)
2581 matrices[bi][bi][v], dof_indices_mf[bi][v], matrix);
2584 matrices[bi][bj][v],
2585 dof_indices_mf[bi][v],
2586 dof_indices_mf[bj][v],
2592 const auto cell_operation_wrapped =
2593 [&](
const auto &,
auto &,
const auto &,
const auto range) {
2594 batch_operation(data_cell, range);
2597 const auto face_operation_wrapped =
2598 [&](
const auto &,
auto &,
const auto &,
const auto range) {
2599 batch_operation(data_face, range);
2602 const auto boundary_operation_wrapped =
2603 [&](
const auto &,
auto &,
const auto &,
const auto range) {
2604 batch_operation(data_boundary, range);
2607 if (data_face.op_compute || data_boundary.op_compute)
2609 matrix_free.template loop<MatrixType, MatrixType>(
2610 cell_operation_wrapped,
2611 face_operation_wrapped,
2612 boundary_operation_wrapped,
2617 matrix_free.template cell_loop<MatrixType, MatrixType>(
2618 cell_operation_wrapped, matrix, matrix);
2624 template <
typename CLASS,
2630 typename VectorizedArrayType,
2642 VectorizedArrayType> &)
const,
2648 VectorizedArrayType> &,
2654 VectorizedArrayType> &)
2661 VectorizedArrayType> &)
2663 const CLASS *owning_class,
2664 const unsigned
int dof_handler_index,
2665 const unsigned
int quadrature_index,
2666 const unsigned
int first_selected_component)
2673 VectorizedArrayType,
2678 [&](
auto &phi) { (owning_class->*cell_operation)(phi); },
2679 [&](
auto &phi_m,
auto &phi_p) {
2680 (owning_class->*face_operation)(phi_m, phi_p);
2682 [&](
auto &phi) { (owning_class->*boundary_operation)(phi); },
2685 first_selected_component);