Reference documentation for deal.II version 9.3.2
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
tools.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2020 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_matrix_free_tools_h
17 #define dealii_matrix_free_tools_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/grid/tria.h>
22 
26 
27 
29 
34 namespace MatrixFreeTools
35 {
41  template <int dim, typename AdditionalData>
42  void
44  AdditionalData & additional_data);
45 
54  template <int dim,
55  int fe_degree,
56  int n_q_points_1d,
57  int n_components,
58  typename Number,
59  typename VectorizedArrayType>
60  void
64  const std::function<void(FEEvaluation<dim,
65  fe_degree,
66  n_q_points_1d,
67  n_components,
68  Number,
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);
73 
77  template <typename CLASS,
78  int dim,
79  int fe_degree,
80  int n_q_points_1d,
81  int n_components,
82  typename Number,
83  typename VectorizedArrayType>
84  void
88  void (CLASS::*cell_operation)(FEEvaluation<dim,
89  fe_degree,
90  n_q_points_1d,
91  n_components,
92  Number,
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);
98 
99 
108  template <int dim,
109  int fe_degree,
110  int n_q_points_1d,
111  int n_components,
112  typename Number,
113  typename VectorizedArrayType,
114  typename MatrixType>
115  void
118  const AffineConstraints<Number> & constraints,
119  MatrixType & matrix,
120  const std::function<void(FEEvaluation<dim,
121  fe_degree,
122  n_q_points_1d,
123  n_components,
124  Number,
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);
129 
133  template <typename CLASS,
134  int dim,
135  int fe_degree,
136  int n_q_points_1d,
137  int n_components,
138  typename Number,
139  typename VectorizedArrayType,
140  typename MatrixType>
141  void
144  const AffineConstraints<Number> & constraints,
145  MatrixType & matrix,
146  void (CLASS::*cell_operation)(FEEvaluation<dim,
147  fe_degree,
148  n_q_points_1d,
149  n_components,
150  Number,
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);
156 
157 
158  // implementations
159 
160 #ifndef DOXYGEN
161 
162  template <int dim, typename AdditionalData>
163  void
165  AdditionalData & additional_data)
166  {
167  // ... determine if we are on an active or a multigrid level
168  const unsigned int level = additional_data.mg_level;
169  const bool is_mg = (level != numbers::invalid_unsigned_int);
170 
171  // ... create empty list for the category of each cell
172  if (is_mg)
173  additional_data.cell_vectorization_category.assign(
174  std::distance(tria.begin(level), tria.end(level)), 0);
175  else
176  additional_data.cell_vectorization_category.assign(tria.n_active_cells(),
177  0);
178 
179  // ... set up scaling factor
180  std::vector<unsigned int> factors(GeometryInfo<dim>::faces_per_cell);
181 
182  auto bids = tria.get_boundary_ids();
183  std::sort(bids.begin(), bids.end());
184 
185  {
186  unsigned int n_bids = bids.size() + 1;
187  int offset = 1;
188  for (unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell;
189  i++, offset = offset * n_bids)
190  factors[i] = offset;
191  }
192 
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++)
196  {
197  auto &face = *cell->face(i);
198  if (face.at_boundary() && !cell->has_periodic_neighbor(i))
199  c_num +=
200  factors[i] * (1 + std::distance(bids.begin(),
201  std::find(bids.begin(),
202  bids.end(),
203  face.boundary_id())));
204  }
205  return c_num;
206  };
207 
208  if (!is_mg)
209  {
210  for (auto cell = tria.begin_active(); cell != tria.end(); ++cell)
211  {
212  if (cell->is_locally_owned())
213  additional_data
214  .cell_vectorization_category[cell->active_cell_index()] =
215  to_category(cell);
216  }
217  }
218  else
219  {
220  for (auto cell = tria.begin(level); cell != tria.end(level); ++cell)
221  {
222  if (cell->is_locally_owned_on_level())
223  additional_data.cell_vectorization_category[cell->index()] =
224  to_category(cell);
225  }
226  }
227 
228  // ... finalize set up of matrix_free
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;
234  }
235 
236  namespace internal
237  {
238  template <typename Number>
239  struct LocalCSR
240  {
241  LocalCSR()
242  : row{0}
243  {}
244 
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;
249  };
250 
251  template <int dim,
252  int fe_degree,
253  int n_q_points_1d,
254  int n_components,
255  typename Number,
256  typename VectorizedArrayType>
257  class ComputeDiagonalHelper
258  {
259  public:
260  static const unsigned int n_lanes = VectorizedArrayType::size();
261 
262  ComputeDiagonalHelper(FEEvaluation<dim,
263  fe_degree,
264  n_q_points_1d,
265  n_components,
266  Number,
267  VectorizedArrayType> &phi)
268  : phi(phi)
269  {}
270 
271  void
272  reinit(const unsigned int cell)
273  {
274  this->phi.reinit(cell);
275  // STEP 1: get relevant information from FEEvaluation
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();
282 
283  const unsigned int n_lanes_filled =
284  matrix_free.n_active_entries_per_cell_batch(cell);
285 
286  std::array<const unsigned int *, n_lanes> dof_indices{};
287  {
288  for (unsigned int v = 0; v < n_lanes_filled; ++v)
289  dof_indices[v] =
290  dof_info.dof_indices.data() +
291  dof_info
292  .row_starts[(cell * n_lanes + v) * n_fe_components +
293  first_selected_component]
294  .first;
295  }
296 
297  // STEP 2: setup CSR storage of transposed locally-relevant
298  // constraint matrix
299  c_pools = std::array<internal::LocalCSR<Number>, n_lanes>();
300 
301  for (unsigned int v = 0; v < n_lanes_filled; ++v)
302  {
303  unsigned int index_indicators, next_index_indicators;
304 
305  index_indicators =
306  dof_info
307  .row_starts[(cell * n_lanes + v) * n_fe_components +
308  first_selected_component]
309  .second;
310  next_index_indicators =
311  dof_info
312  .row_starts[(cell * n_lanes + v) * n_fe_components +
313  first_selected_component + 1]
314  .second;
315 
316  // STEP 2a: setup locally-relevant constraint matrix in a
317  // coordinate list (COO)
318  std::vector<std::tuple<unsigned int, unsigned int, Number>>
319  locally_relevant_constrains; // (constrained local index,
320  // global index of dof which
321  // constrains, weight)
322 
323  if (n_components == 1 || n_fe_components == 1)
324  {
325  AssertDimension(n_components,
326  1); // TODO: currently no block vector supported
327 
328  unsigned int ind_local = 0;
329  for (; index_indicators != next_index_indicators;
330  ++index_indicators, ++ind_local)
331  {
332  const std::pair<unsigned short, unsigned short> indicator =
333  dof_info.constraint_indicator[index_indicators];
334 
335  for (unsigned int j = 0; j < indicator.first;
336  ++j, ++ind_local)
337  locally_relevant_constrains.emplace_back(
338  ind_local, dof_indices[v][j], 1.0);
339 
340  dof_indices[v] += indicator.first;
341 
342  const Number *data_val =
343  matrix_free.constraint_pool_begin(indicator.second);
344  const Number *end_pool =
345  matrix_free.constraint_pool_end(indicator.second);
346 
347  for (; data_val != end_pool; ++data_val, ++dof_indices[v])
348  locally_relevant_constrains.emplace_back(ind_local,
349  *dof_indices[v],
350  *data_val);
351  }
352 
353  AssertIndexRange(ind_local, dofs_per_component + 1);
354 
355  for (; ind_local < dofs_per_component;
356  ++dof_indices[v], ++ind_local)
357  locally_relevant_constrains.emplace_back(ind_local,
358  *dof_indices[v],
359  1.0);
360  }
361  else
362  {
363  // case with vector-valued finite elements where all
364  // components are included in one single vector. Assumption:
365  // first come all entries to the first component, then all
366  // entries to the second one, and so on. This is ensured by
367  // the way MatrixFree reads out the indices.
368  for (unsigned int comp = 0; comp < n_components; ++comp)
369  {
370  unsigned int ind_local = 0;
371 
372  // check whether there is any constraint on the current
373  // cell
374  for (; index_indicators != next_index_indicators;
375  ++index_indicators, ++ind_local)
376  {
377  const std::pair<unsigned short, unsigned short>
378  indicator =
379  dof_info.constraint_indicator[index_indicators];
380 
381  // run through values up to next constraint
382  for (unsigned int j = 0; j < indicator.first;
383  ++j, ++ind_local)
384  locally_relevant_constrains.emplace_back(
385  comp * dofs_per_component + ind_local,
386  dof_indices[v][j],
387  1.0);
388  dof_indices[v] += indicator.first;
389 
390  const Number *data_val =
391  matrix_free.constraint_pool_begin(indicator.second);
392  const Number *end_pool =
393  matrix_free.constraint_pool_end(indicator.second);
394 
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,
399  *dof_indices[v],
400  *data_val);
401  }
402 
403  AssertIndexRange(ind_local, dofs_per_component + 1);
404 
405  // get the dof values past the last constraint
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,
410  *dof_indices[v],
411  1.0);
412 
413  if (comp + 1 < n_components)
414  {
415  next_index_indicators =
416  dof_info
417  .row_starts[(cell * n_lanes + v) * n_fe_components +
418  first_selected_component + comp + 2]
419  .second;
420  }
421  }
422  }
423 
424  // STEP 2b: transpose COO
425 
426  // presort vector for transposed access
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))
431  return true;
432  return (std::get<1>(a) == std::get<1>(b)) &&
433  (std::get<0>(a) < std::get<0>(b));
434  });
435 
436  // make sure that all entries are unique
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));
443  }),
444  locally_relevant_constrains.end());
445 
446  // STEP 2c: translate COO to CRS
447  auto &c_pool = c_pools[v];
448  {
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)
453  {
454  if (c_pool.row_lid_to_gid.back() != std::get<1>(j))
455  {
456  c_pool.row_lid_to_gid.push_back(std::get<1>(j));
457  c_pool.row.push_back(c_pool.val.size());
458  }
459 
460  c_pool.col.emplace_back(std::get<0>(j));
461  c_pool.val.emplace_back(std::get<2>(j));
462  }
463 
464  if (c_pool.val.size() > 0)
465  c_pool.row.push_back(c_pool.val.size());
466  }
467  }
468  // STEP 3: compute element matrix A_e, apply
469  // locally-relevant constraints C_e^T * A_e * C_e, and get the
470  // the diagonal entry
471  // (C_e^T * A_e * C_e)(i,i)
472  // or
473  // C_e^T(i,:) * A_e * C_e(:,i).
474  //
475  // Since, we compute the element matrix column-by-column and as a
476  // result never actually have the full element matrix, we actually
477  // perform following steps:
478  // 1) loop over all columns of the element matrix
479  // a) compute column i
480  // b) compute for each j (rows of C_e^T):
481  // (C_e^T(j,:) * A_e(:,i)) * C_e(i,j)
482  // or
483  // (C_e^T(j,:) * A_e(:,i)) * C_e^T(j,i)
484  // This gives a contribution the j-th entry of the
485  // locally-relevant diagonal and comprises the multiplication
486  // by the locally-relevant constraint matrix from the left and
487  // the right. There is no contribution to the j-th vector
488  // entry if the j-th row of C_e^T is empty or C_e^T(j,i) is
489  // zero.
490 
491  // set size locally-relevant diagonal
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));
495  }
496 
497  void
498  prepare_basis_vector(const unsigned int i)
499  {
500  this->i = i;
501 
502  // compute i-th column of element stiffness matrix:
503  // this could be simply performed as done at the moment with
504  // matrix-free operator evaluation applied to a ith-basis vector
505  for (unsigned int j = 0; j < phi.dofs_per_cell; ++j)
506  phi.begin_dof_values()[j] = static_cast<Number>(i == j);
507  }
508 
509  void
510  submit()
511  {
512  const auto ith_column = phi.begin_dof_values();
513 
514  // apply local constraint matrix from left and from right:
515  // loop over all rows of transposed constrained matrix
516  for (unsigned int v = 0;
517  v < phi.get_matrix_free().n_active_entries_per_cell_batch(
518  phi.get_current_cell_index());
519  ++v)
520  {
521  const auto &c_pool = c_pools[v];
522 
523  for (unsigned int j = 0; j < c_pool.row.size() - 1; ++j)
524  {
525  // check if the result will be zero, so that we can skip
526  // the following computations -> binary search
527  const auto scale_iterator =
528  std::lower_bound(c_pool.col.begin() + c_pool.row[j],
529  c_pool.col.begin() + c_pool.row[j + 1],
530  i);
531 
532  // explanation: j-th row of C_e^T is empty (see above)
533  if (scale_iterator == c_pool.col.begin() + c_pool.row[j + 1])
534  continue;
535 
536  // explanation: C_e^T(j,i) is zero (see above)
537  if (*scale_iterator != i)
538  continue;
539 
540  // apply constraint matrix from the left
541  Number temp = 0.0;
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];
544 
545  // apply constraint matrix from the right
546  diagonals_local_constrained[v][j] +=
547  temp *
548  c_pool.val[std::distance(c_pool.col.begin(), scale_iterator)];
549  }
550  }
551  }
552 
553  void
554  distribute_local_to_global(
556  {
557  // STEP 4: assembly results: add into global vector
558  for (unsigned int v = 0;
559  v < phi.get_matrix_free().n_active_entries_per_cell_batch(
560  phi.get_current_cell_index());
561  ++v)
562  for (unsigned int j = 0; j < c_pools[v].row.size() - 1; ++j)
564  diagonal_global,
565  c_pools[v].row_lid_to_gid[j],
566  diagonals_local_constrained[v][j]);
567  }
568 
569  private:
570  FEEvaluation<dim,
571  fe_degree,
572  n_q_points_1d,
573  n_components,
574  Number,
575  VectorizedArrayType> &phi;
576 
577  unsigned int i;
578 
579  std::array<internal::LocalCSR<Number>, n_lanes> c_pools;
580 
581  // local storage: buffer so that we access the global vector once
582  // note: may be larger then dofs_per_cell in the presence of
583  // constraints!
584  std::array<std::vector<Number>, n_lanes> diagonals_local_constrained;
585  };
586 
587  } // namespace internal
588 
589  template <int dim,
590  int fe_degree,
591  int n_q_points_1d,
592  int n_components,
593  typename Number,
594  typename VectorizedArrayType>
595  void
599  const std::function<void(FEEvaluation<dim,
600  fe_degree,
601  n_q_points_1d,
602  n_components,
603  Number,
604  VectorizedArrayType> &)> &local_vmult,
605  const unsigned int dof_no,
606  const unsigned int quad_no,
607  const unsigned int first_selected_component)
608  {
610 
611  // initialize vector
612  matrix_free.initialize_dof_vector(diagonal_global, dof_no);
613 
614  int dummy = 0;
615 
616  matrix_free.template cell_loop<VectorType, int>(
617  [&](const MatrixFree<dim, Number, VectorizedArrayType> &matrix_free,
619  const int &,
620  const std::pair<unsigned int, unsigned int> &range) mutable {
621  FEEvaluation<dim,
622  fe_degree,
623  n_q_points_1d,
624  n_components,
625  Number,
626  VectorizedArrayType>
627  phi(matrix_free, range, dof_no, quad_no, first_selected_component);
628 
629  internal::ComputeDiagonalHelper<dim,
630  fe_degree,
631  n_q_points_1d,
632  n_components,
633  Number,
634  VectorizedArrayType>
635  helper(phi);
636 
637  for (unsigned int cell = range.first; cell < range.second; ++cell)
638  {
639  helper.reinit(cell);
640 
641  for (unsigned int i = 0; i < phi.dofs_per_cell; ++i)
642  {
643  helper.prepare_basis_vector(i);
644  local_vmult(phi);
645  helper.submit();
646  }
647 
648  helper.distribute_local_to_global(diagonal_global);
649  }
650  },
651  diagonal_global,
652  dummy,
653  false);
654  }
655 
656  template <typename CLASS,
657  int dim,
658  int fe_degree,
659  int n_q_points_1d,
660  int n_components,
661  typename Number,
662  typename VectorizedArrayType>
663  void
667  void (CLASS::*cell_operation)(FEEvaluation<dim,
668  fe_degree,
669  n_q_points_1d,
670  n_components,
671  Number,
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)
677  {
678  compute_diagonal<dim,
679  fe_degree,
680  n_q_points_1d,
681  n_components,
682  Number,
683  VectorizedArrayType>(
684  matrix_free,
685  diagonal_global,
686  [&](auto &feeval) { (owning_class->*cell_operation)(feeval); },
687  dof_no,
688  quad_no,
689  first_selected_component);
690  }
691 
692  namespace internal
693  {
698  template <typename MatrixType,
699  typename Number,
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(
707  const MatrixType &,
708  const AffineConstraints<Number> &constraints,
710  {
711  return constraints;
712  }
713 
719  template <typename MatrixType,
720  typename Number,
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(
728  const MatrixType &,
729  const AffineConstraints<Number> &constraints,
731  &new_constraints)
732  {
733  new_constraints =
734  std::make_unique<AffineConstraints<typename MatrixType::value_type>>();
735  new_constraints->copy_from(constraints);
736 
737  return *new_constraints;
738  }
739  } // namespace internal
740 
741  template <int dim,
742  int fe_degree,
743  int n_q_points_1d,
744  int n_components,
745  typename Number,
746  typename VectorizedArrayType,
747  typename MatrixType>
748  void
751  const AffineConstraints<Number> & constraints_in,
752  MatrixType & matrix,
753  const std::function<void(FEEvaluation<dim,
754  fe_degree,
755  n_q_points_1d,
756  n_components,
757  Number,
758  VectorizedArrayType> &)> &local_vmult,
759  const unsigned int dof_no,
760  const unsigned int quad_no,
761  const unsigned int first_selected_component)
762  {
763  std::unique_ptr<AffineConstraints<typename MatrixType::value_type>>
764  constraints_for_matrix;
766  internal::create_new_affine_constraints_if_needed(matrix,
767  constraints_in,
768  constraints_for_matrix);
769 
770  matrix_free.template cell_loop<MatrixType, MatrixType>(
771  [&](const auto &, auto &dst, const auto &, const auto range) {
772  FEEvaluation<dim,
773  fe_degree,
774  n_q_points_1d,
775  n_components,
776  Number,
777  VectorizedArrayType>
778  integrator(
779  matrix_free, range, dof_no, quad_no, first_selected_component);
780 
781  unsigned int const dofs_per_cell = integrator.dofs_per_cell;
782 
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);
785 
786  std::array<FullMatrix<typename MatrixType::value_type>,
787  VectorizedArrayType::size()>
788  matrices;
789 
790  std::fill_n(matrices.begin(),
791  VectorizedArrayType::size(),
793  dofs_per_cell));
794 
795  const auto lexicographic_numbering =
796  matrix_free
797  .get_shape_info(dof_no,
798  quad_no,
799  first_selected_component,
800  integrator.get_active_fe_index(),
801  integrator.get_active_quadrature_index())
803 
804  for (auto cell = range.first; cell < range.second; ++cell)
805  {
806  integrator.reinit(cell);
807 
808  unsigned int const n_filled_lanes =
809  matrix_free.n_active_entries_per_cell_batch(cell);
810 
811  for (unsigned int v = 0; v < n_filled_lanes; ++v)
812  matrices[v] = 0.0;
813 
814  for (unsigned int j = 0; j < dofs_per_cell; ++j)
815  {
816  for (unsigned int i = 0; i < dofs_per_cell; ++i)
817  integrator.begin_dof_values()[i] =
818  static_cast<Number>(i == j);
819 
820  local_vmult(integrator);
821 
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];
825  }
826 
827  for (unsigned int v = 0; v < n_filled_lanes; ++v)
828  {
829  const auto cell_v =
830  matrix_free.get_cell_iterator(cell, v, dof_no);
831 
832  if (matrix_free.get_mg_level() != numbers::invalid_unsigned_int)
833  cell_v->get_mg_dof_indices(dof_indices);
834  else
835  cell_v->get_dof_indices(dof_indices);
836 
837  for (unsigned int j = 0; j < dof_indices.size(); ++j)
838  dof_indices_mf[j] = dof_indices[lexicographic_numbering[j]];
839 
840  constraints.distribute_local_to_global(matrices[v],
841  dof_indices_mf,
842  dst);
843  }
844  }
845  },
846  matrix,
847  matrix);
848 
849  matrix.compress(VectorOperation::add);
850  }
851 
852  template <typename CLASS,
853  int dim,
854  int fe_degree,
855  int n_q_points_1d,
856  int n_components,
857  typename Number,
858  typename VectorizedArrayType,
859  typename MatrixType>
860  void
863  const AffineConstraints<Number> & constraints,
864  MatrixType & matrix,
865  void (CLASS::*cell_operation)(FEEvaluation<dim,
866  fe_degree,
867  n_q_points_1d,
868  n_components,
869  Number,
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)
875  {
876  compute_matrix<dim,
877  fe_degree,
878  n_q_points_1d,
879  n_components,
880  Number,
881  VectorizedArrayType,
882  MatrixType>(matrix_free,
883  constraints,
884  matrix,
885  [&](auto &feeval) {
886  (owning_class->*cell_operation)(feeval);
887  },
888  dof_no,
889  quad_no,
890  first_selected_component);
891  }
892 
893 #endif // DOXYGEN
894 
895 } // namespace MatrixFreeTools
896 
898 
899 
900 #endif
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)
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
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
const Number * constraint_pool_end(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
void initialize_dof_vector(VectorType &vec, const unsigned int dof_handler_index=0) const
virtual std::vector< types::boundary_id > get_boundary_ids() const
cell_iterator begin(const unsigned int level=0) const
unsigned int n_active_cells() const
cell_iterator end() const
active_cell_iterator begin_active(const unsigned int level=0) const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:396
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:397
Point< 2 > second
Definition: grid_out.cc:4588
Point< 2 > first
Definition: grid_out.cc:4587
unsigned int level
Definition: grid_out.cc:4590
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1622
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
@ matrix
Contents is actually a matrix.
void compute_diagonal(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, LinearAlgebra::distributed::Vector< Number > &diagonal_global, const std::function< void(FEEvaluation< dim, fe_degree, n_q_points_1d, n_components, Number, VectorizedArrayType > &)> &local_vmult, const unsigned int dof_no=0, const unsigned int quad_no=0, const unsigned int first_selected_component=0)
void categorize_by_boundary_ids(const Triangulation< dim > &tria, AdditionalData &additional_data)
void compute_matrix(const MatrixFree< dim, Number, VectorizedArrayType > &matrix_free, const AffineConstraints< Number > &constraints, MatrixType &matrix, const std::function< void(FEEvaluation< dim, fe_degree, n_q_points_1d, n_components, Number, VectorizedArrayType > &)> &local_vmult, const unsigned int dof_no=0, const unsigned int quad_no=0, const unsigned int first_selected_component=0)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:1111
void vector_access_add(VectorType &vec, const unsigned int entry, const typename VectorType::value_type &val)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
Definition: matrix_block.h:618
static const unsigned int invalid_unsigned_int
Definition: types.h:196
std::vector< unsigned int > lexicographic_numbering
Definition: shape_info.h:380