Reference documentation for deal.II version 9.3.3
\(\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
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>(
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 {
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
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)
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
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
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