16#ifndef dealii_matrix_free_tools_h
17#define dealii_matrix_free_tools_h
41 template <
int dim,
typename AdditionalData>
44 AdditionalData & additional_data);
59 typename VectorizedArrayType>
69 VectorizedArrayType> &)> &local_vmult,
70 const unsigned int dof_no = 0,
71 const unsigned int quad_no = 0,
72 const unsigned int first_selected_component = 0);
77 template <
typename CLASS,
83 typename VectorizedArrayType>
93 VectorizedArrayType> &)
const,
94 const CLASS * owning_class,
95 const unsigned int dof_no = 0,
96 const unsigned int quad_no = 0,
97 const unsigned int first_selected_component = 0);
113 typename VectorizedArrayType,
125 VectorizedArrayType> &)> &local_vmult,
126 const unsigned int dof_no = 0,
127 const unsigned int quad_no = 0,
128 const unsigned int first_selected_component = 0);
133 template <
typename CLASS,
139 typename VectorizedArrayType,
151 VectorizedArrayType> &)
const,
152 const CLASS * owning_class,
153 const unsigned int dof_no = 0,
154 const unsigned int quad_no = 0,
155 const unsigned int first_selected_component = 0);
162 template <
int dim,
typename AdditionalData>
165 AdditionalData & additional_data)
168 const unsigned int level = additional_data.mg_level;
173 additional_data.cell_vectorization_category.assign(
176 additional_data.cell_vectorization_category.assign(tria.
n_active_cells(),
183 std::sort(bids.begin(), bids.end());
186 unsigned int n_bids = bids.size() + 1;
188 for (
unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell;
189 i++, offset = offset * n_bids)
193 const auto to_category = [&](
const auto &cell) {
194 unsigned int c_num = 0;
195 for (
unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell; i++)
197 auto &face = *cell->face(i);
198 if (face.at_boundary() && !cell->has_periodic_neighbor(i))
200 factors[i] * (1 + std::distance(bids.begin(),
201 std::find(bids.begin(),
203 face.boundary_id())));
212 if (cell->is_locally_owned())
214 .cell_vectorization_category[cell->active_cell_index()] =
222 if (cell->is_locally_owned_on_level())
223 additional_data.cell_vectorization_category[cell->index()] =
229 additional_data.hold_all_faces_to_owned_cells =
true;
230 additional_data.cell_vectorization_categories_strict =
true;
231 additional_data.mapping_update_flags_faces_by_cells =
232 additional_data.mapping_update_flags_inner_faces |
233 additional_data.mapping_update_flags_boundary_faces;
238 template <
typename Number>
245 std::vector<unsigned int> row_lid_to_gid;
246 std::vector<unsigned int> row;
247 std::vector<unsigned int> col;
248 std::vector<Number> val;
256 typename VectorizedArrayType>
257 class ComputeDiagonalHelper
260 static const unsigned int n_lanes = VectorizedArrayType::size();
267 VectorizedArrayType> &phi)
272 reinit(
const unsigned int cell)
274 this->phi.reinit(cell);
276 const unsigned int first_selected_component =
277 phi.get_first_selected_component();
278 const auto & dof_info = phi.get_dof_info();
279 const unsigned int n_fe_components = dof_info.start_components.back();
280 const unsigned int dofs_per_component = phi.dofs_per_component;
281 const auto & matrix_free = phi.get_matrix_free();
283 const unsigned int n_lanes_filled =
286 std::array<const unsigned int *, n_lanes> dof_indices{};
288 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
290 dof_info.dof_indices.data() +
292 .row_starts[(cell * n_lanes + v) * n_fe_components +
293 first_selected_component]
299 c_pools = std::array<internal::LocalCSR<Number>, n_lanes>();
301 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
303 unsigned int index_indicators, next_index_indicators;
307 .row_starts[(cell * n_lanes + v) * n_fe_components +
308 first_selected_component]
310 next_index_indicators =
312 .row_starts[(cell * n_lanes + v) * n_fe_components +
313 first_selected_component + 1]
318 std::vector<std::tuple<unsigned int, unsigned int, Number>>
319 locally_relevant_constrains;
323 if (n_components == 1 || n_fe_components == 1)
328 unsigned int ind_local = 0;
329 for (; index_indicators != next_index_indicators;
330 ++index_indicators, ++ind_local)
332 const std::pair<unsigned short, unsigned short> indicator =
333 dof_info.constraint_indicator[index_indicators];
335 for (
unsigned int j = 0; j < indicator.first;
337 locally_relevant_constrains.emplace_back(
338 ind_local, dof_indices[v][j], 1.0);
340 dof_indices[v] += indicator.first;
342 const Number *data_val =
344 const Number *end_pool =
347 for (; data_val != end_pool; ++data_val, ++dof_indices[v])
348 locally_relevant_constrains.emplace_back(ind_local,
355 for (; ind_local < dofs_per_component;
356 ++dof_indices[v], ++ind_local)
357 locally_relevant_constrains.emplace_back(ind_local,
368 for (
unsigned int comp = 0; comp < n_components; ++comp)
370 unsigned int ind_local = 0;
374 for (; index_indicators != next_index_indicators;
375 ++index_indicators, ++ind_local)
377 const std::pair<unsigned short, unsigned short>
379 dof_info.constraint_indicator[index_indicators];
382 for (
unsigned int j = 0; j < indicator.first;
384 locally_relevant_constrains.emplace_back(
385 comp * dofs_per_component + ind_local,
388 dof_indices[v] += indicator.first;
390 const Number *data_val =
392 const Number *end_pool =
395 for (; data_val != end_pool;
396 ++data_val, ++dof_indices[v])
397 locally_relevant_constrains.emplace_back(
398 comp * dofs_per_component + ind_local,
406 for (; ind_local < dofs_per_component;
407 ++dof_indices[v], ++ind_local)
408 locally_relevant_constrains.emplace_back(
409 comp * dofs_per_component + ind_local,
413 if (comp + 1 < n_components)
415 next_index_indicators =
417 .row_starts[(cell * n_lanes + v) * n_fe_components +
418 first_selected_component + comp + 2]
427 std::sort(locally_relevant_constrains.begin(),
428 locally_relevant_constrains.end(),
429 [](
const auto &a,
const auto &
b) {
430 if (std::get<1>(a) < std::get<1>(b))
432 return (std::get<1>(a) == std::get<1>(b)) &&
433 (std::get<0>(a) < std::get<0>(b));
437 locally_relevant_constrains.erase(
438 unique(locally_relevant_constrains.begin(),
439 locally_relevant_constrains.end(),
440 [](
const auto &a,
const auto &
b) {
441 return (std::get<1>(a) == std::get<1>(b)) &&
442 (std::get<0>(a) == std::get<0>(b));
444 locally_relevant_constrains.end());
447 auto &c_pool = c_pools[v];
449 if (locally_relevant_constrains.size() > 0)
450 c_pool.row_lid_to_gid.emplace_back(
451 std::get<1>(locally_relevant_constrains.front()));
452 for (
const auto &j : locally_relevant_constrains)
454 if (c_pool.row_lid_to_gid.back() != std::get<1>(j))
456 c_pool.row_lid_to_gid.push_back(std::get<1>(j));
457 c_pool.row.push_back(c_pool.val.size());
460 c_pool.col.emplace_back(std::get<0>(j));
461 c_pool.val.emplace_back(std::get<2>(j));
464 if (c_pool.val.size() > 0)
465 c_pool.row.push_back(c_pool.val.size());
492 for (
unsigned int v = 0; v < n_lanes_filled; ++v)
493 diagonals_local_constrained[v].assign(
494 c_pools[v].row_lid_to_gid.size(), Number(0.0));
498 prepare_basis_vector(
const unsigned int i)
505 for (
unsigned int j = 0; j < phi.dofs_per_cell; ++j)
506 phi.begin_dof_values()[j] =
static_cast<Number
>(i == j);
512 const auto ith_column = phi.begin_dof_values();
516 for (
unsigned int v = 0;
517 v < phi.get_matrix_free().n_active_entries_per_cell_batch(
518 phi.get_current_cell_index());
521 const auto &c_pool = c_pools[v];
523 for (
unsigned int j = 0; j < c_pool.row.size() - 1; ++j)
527 const auto scale_iterator =
529 c_pool.col.begin() + c_pool.row[j + 1],
533 if (scale_iterator == c_pool.col.begin() + c_pool.row[j + 1])
537 if (*scale_iterator != i)
542 for (
unsigned int k = c_pool.row[j]; k < c_pool.row[j + 1]; ++k)
543 temp += c_pool.val[k] * ith_column[c_pool.col[k]][v];
546 diagonals_local_constrained[v][j] +=
548 c_pool.val[std::distance(c_pool.col.begin(), scale_iterator)];
554 distribute_local_to_global(
558 for (
unsigned int v = 0;
559 v < phi.get_matrix_free().n_active_entries_per_cell_batch(
560 phi.get_current_cell_index());
562 for (
unsigned int j = 0; j < c_pools[v].row.size() - 1; ++j)
565 c_pools[v].row_lid_to_gid[j],
566 diagonals_local_constrained[v][j]);
575 VectorizedArrayType> φ
579 std::array<internal::LocalCSR<Number>, n_lanes> c_pools;
584 std::array<std::vector<Number>, n_lanes> diagonals_local_constrained;
594 typename VectorizedArrayType>
604 VectorizedArrayType> &)> &local_vmult,
605 const unsigned int dof_no,
606 const unsigned int quad_no,
607 const unsigned int first_selected_component)
616 matrix_free.template cell_loop<VectorType, int>(
620 const std::pair<unsigned int, unsigned int> &range)
mutable {
627 phi(matrix_free, range, dof_no, quad_no, first_selected_component);
629 internal::ComputeDiagonalHelper<dim,
637 for (
unsigned int cell = range.first; cell < range.second; ++cell)
641 for (
unsigned int i = 0; i < phi.dofs_per_cell; ++i)
643 helper.prepare_basis_vector(i);
648 helper.distribute_local_to_global(diagonal_global);
656 template <
typename CLASS,
662 typename VectorizedArrayType>
672 VectorizedArrayType> &)
const,
673 const CLASS * owning_class,
674 const unsigned int dof_no,
675 const unsigned int quad_no,
676 const unsigned int first_selected_component)
683 VectorizedArrayType>(
686 [&](
auto &feeval) { (owning_class->*cell_operation)(feeval); },
689 first_selected_component);
698 template <
typename MatrixType,
700 typename std::enable_if<std::is_same<
701 typename std::remove_const<
typename std::remove_reference<
702 typename MatrixType::value_type>::type>::type,
703 typename std::remove_const<
typename std::remove_reference<
704 Number>::type>::type>::value>::type * =
nullptr>
706 create_new_affine_constraints_if_needed(
719 template <
typename MatrixType,
721 typename std::enable_if<!std::is_same<
722 typename std::remove_const<
typename std::remove_reference<
723 typename MatrixType::value_type>::type>::type,
724 typename std::remove_const<
typename std::remove_reference<
725 Number>::type>::type>::value>::type * =
nullptr>
727 create_new_affine_constraints_if_needed(
734 std::make_unique<AffineConstraints<typename MatrixType::value_type>>();
737 return *new_constraints;
746 typename VectorizedArrayType,
758 VectorizedArrayType> &)> &local_vmult,
759 const unsigned int dof_no,
760 const unsigned int quad_no,
761 const unsigned int first_selected_component)
763 std::unique_ptr<AffineConstraints<typename MatrixType::value_type>>
764 constraints_for_matrix;
766 internal::create_new_affine_constraints_if_needed(
matrix,
768 constraints_for_matrix);
770 matrix_free.template cell_loop<MatrixType, MatrixType>(
771 [&](
const auto &,
auto &dst,
const auto &,
const auto range) {
779 matrix_free, range, dof_no, quad_no, first_selected_component);
781 unsigned int const dofs_per_cell = integrator.dofs_per_cell;
783 std::vector<types::global_dof_index> dof_indices(dofs_per_cell);
784 std::vector<types::global_dof_index> dof_indices_mf(dofs_per_cell);
786 std::array<FullMatrix<typename MatrixType::value_type>,
787 VectorizedArrayType::size()>
790 std::fill_n(matrices.begin(),
791 VectorizedArrayType::size(),
795 const auto lexicographic_numbering =
799 first_selected_component,
800 integrator.get_active_fe_index(),
801 integrator.get_active_quadrature_index())
804 for (
auto cell = range.first; cell < range.second; ++cell)
806 integrator.reinit(cell);
808 unsigned int const n_filled_lanes =
811 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
814 for (
unsigned int j = 0; j < dofs_per_cell; ++j)
816 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
817 integrator.begin_dof_values()[i] =
818 static_cast<Number
>(i == j);
820 local_vmult(integrator);
822 for (
unsigned int i = 0; i < dofs_per_cell; ++i)
823 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
824 matrices[v](i, j) = integrator.begin_dof_values()[i][v];
827 for (
unsigned int v = 0; v < n_filled_lanes; ++v)
833 cell_v->get_mg_dof_indices(dof_indices);
835 cell_v->get_dof_indices(dof_indices);
837 for (
unsigned int j = 0; j < dof_indices.size(); ++j)
838 dof_indices_mf[j] = dof_indices[lexicographic_numbering[j]];
852 template <
typename CLASS,
858 typename VectorizedArrayType,
870 VectorizedArrayType> &)
const,
871 const CLASS * owning_class,
872 const unsigned int dof_no,
873 const unsigned int quad_no,
874 const unsigned int first_selected_component)
882 MatrixType>(matrix_free,
886 (owning_class->*cell_operation)(feeval);
890 first_selected_component);
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
void copy_from(const AffineConstraints< other_number > &other)
const internal::MatrixFreeFunctions::ShapeInfo< VectorizedArrayType > & get_shape_info(const unsigned int dof_handler_index_component=0, const unsigned int quad_index=0, const unsigned int fe_base_element=0, const unsigned int hp_active_fe_index=0, const unsigned int hp_active_quad_index=0) const
unsigned int n_active_entries_per_cell_batch(const unsigned int cell_batch_index) const
unsigned int get_mg_level() const
const Number * constraint_pool_begin(const unsigned int pool_index) const
DoFHandler< dim >::cell_iterator get_cell_iterator(const unsigned int cell_batch_index, const unsigned int lane_index, const unsigned int dof_handler_index=0) const
const Number * constraint_pool_end(const unsigned int pool_index) const
void initialize_dof_vector(VectorType &vec, const unsigned int dof_handler_index=0) const
cell_iterator begin(const unsigned int level=0) const
unsigned int n_active_cells() const
cell_iterator end() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
active_cell_iterator begin_active(const unsigned int level=0) const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
@ matrix
Contents is actually a matrix.
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
void vector_access_add(VectorType &vec, const unsigned int entry, const typename VectorType::value_type &val)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
static const unsigned int invalid_unsigned_int
std::vector< unsigned int > lexicographic_numbering