deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\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\}}\)
Loading...
Searching...
No Matches
constraint_info.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2022 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#ifndef dealii_matrix_free_constraint_info_h
15#define dealii_matrix_free_constraint_info_h
16
17
18#include <deal.II/base/config.h>
19
21
26
27#include <limits>
28
30
31namespace internal
32{
33 namespace MatrixFreeFunctions
34 {
39 template <typename Number>
41 {
43
51 template <typename number2>
52 unsigned short
54 const std::vector<std::pair<types::global_dof_index, number2>>
55 &entries);
56
60 std::size_t
62
63 std::vector<std::pair<types::global_dof_index, double>>
65 std::vector<types::global_dof_index> constraint_indices;
66
67 std::pair<std::vector<Number>, types::global_dof_index> next_constraint;
68 std::map<std::vector<Number>,
72 };
73
74
75
81 template <int dim, typename Number, typename IndexType = unsigned int>
83 {
84 public:
89
94 void
96
101 void
102 reinit(const DoFHandler<dim, dim> &dof_handler,
103 const unsigned int n_cells,
104 const bool use_fast_hanging_node_algorithm = true);
105
106 void
108 const unsigned int cell_no,
109 const unsigned int mg_level,
111 const ::AffineConstraints<typename Number::value_type>
112 &constraints,
113 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
114
118 void
119 reinit(const unsigned int n_cells);
120
121 void
123 const unsigned int cell_no,
124 const std::vector<types::global_dof_index> &dof_indices,
125 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner);
126
127 void
129
130 std::shared_ptr<const Utilities::MPI::Partitioner>
132
133 template <typename T, typename VectorType>
134 void
135 read_write_operation(const T &operation,
136 VectorType &global_vector,
137 Number *local_vector,
138 const unsigned int first_cell,
139 const unsigned int n_cells,
140 const unsigned int n_dofs_per_cell,
141 const bool apply_constraints) const;
142
143 void
145 const unsigned int first_cell,
146 const unsigned int n_lanes_filled,
147 const bool transpose,
148 AlignedVector<Number> &evaluation_data_coarse) const;
149
153 std::size_t
155
156 private:
157 // for setup
159 std::vector<std::vector<IndexType>> dof_indices_per_cell;
160 std::vector<std::vector<IndexType>> plain_dof_indices_per_cell;
161 std::vector<std::vector<std::pair<unsigned short, unsigned short>>>
163
164 std::unique_ptr<HangingNodes<dim>> hanging_nodes;
165 std::vector<std::vector<unsigned int>> lexicographic_numbering;
166
167 std::vector<types::global_dof_index> local_dof_indices;
168 std::vector<types::global_dof_index> local_dof_indices_lex;
169 std::vector<ConstraintKinds> mask;
170
172 std::pair<types::global_dof_index, types::global_dof_index> local_range;
173
174 public:
175 // for read_write_operation()
176 std::vector<unsigned int> dof_indices;
177 std::vector<std::pair<unsigned short, unsigned short>>
179 std::vector<std::pair<unsigned int, unsigned int>> row_starts;
180
181 std::vector<unsigned int> plain_dof_indices;
182 std::vector<unsigned int> row_starts_plain_indices;
183
184 // for constraint_pool_begin/end()
185 std::vector<typename Number::value_type> constraint_pool_data;
186 std::vector<unsigned int> constraint_pool_row_index;
187
188 std::vector<ShapeInfo<typename Number::value_type>> shape_infos;
189 std::vector<compressed_constraint_kind> hanging_node_constraint_masks;
190 std::vector<unsigned int> active_fe_indices;
191
192 private:
193 inline const typename Number::value_type *
194 constraint_pool_begin(const unsigned int row) const;
195
196 inline const typename Number::value_type *
197 constraint_pool_end(const unsigned int row) const;
198 };
199
200
201
202 // ------------------------- inline functions --------------------------
203
204 // NOLINTNEXTLINE(modernize-use-equals-default)
205 template <typename Number>
207 : constraints(FloatingPointComparator<Number>(
208 1. * std::numeric_limits<double>::epsilon() * 1024.))
209 {}
210
211
212
213 template <typename Number>
214 template <typename number2>
215 unsigned short
217 const std::vector<std::pair<types::global_dof_index, number2>> &entries)
218 {
219 next_constraint.first.resize(entries.size());
220 if (entries.size() > 0)
221 {
222 constraint_indices.resize(entries.size());
223 // Use assign so that values for nonmatching Number / number2 are
224 // converted:
225 constraint_entries.assign(entries.begin(), entries.end());
226 std::sort(constraint_entries.begin(),
227 constraint_entries.end(),
228 [](const std::pair<types::global_dof_index, double> &p1,
229 const std::pair<types::global_dof_index, double> &p2) {
230 return p1.second < p2.second;
231 });
232 for (types::global_dof_index j = 0; j < constraint_entries.size();
233 j++)
234 {
235 // copy the indices of the constraint entries after sorting.
236 constraint_indices[j] = constraint_entries[j].first;
237
238 // one_constraint takes the weights of the constraint
239 next_constraint.first[j] = constraint_entries[j].second;
240 }
241 }
242
243 // check whether or not constraint is already in pool. the initial
244 // implementation computed a hash value based on the truncated array (to
245 // given accuracy around 1e-13) in order to easily detect different
246 // arrays and then made a fine-grained check when the hash values were
247 // equal. this was quite lengthy and now we use a std::map with a
248 // user-defined comparator to compare floating point arrays to a
249 // tolerance 1e-13.
251 const auto position = constraints.find(next_constraint.first);
252 if (position != constraints.end())
253 insert_position = position->second;
254 else
255 {
256 next_constraint.second = constraints.size();
257 constraints.insert(next_constraint);
258 insert_position = next_constraint.second;
259 }
260
261 // we want to store the result as a short variable, so we have to make
262 // sure that the result does not exceed the limits when casting.
263 Assert(insert_position < (1 << (8 * sizeof(unsigned short))),
265 return static_cast<unsigned short>(insert_position);
266 }
267
268
269
270 template <int dim, typename Number, typename IndexType>
274
275
276
277 template <int dim, typename Number, typename IndexType>
278 void
280 const IndexSet &locally_owned_indices)
281 {
282 this->locally_owned_indices = locally_owned_indices;
283
284 if (locally_owned_indices.is_empty())
285 local_range = {0, 0};
286 else
287 local_range = {locally_owned_indices.nth_index_in_set(0),
288 locally_owned_indices.nth_index_in_set(0) +
289 locally_owned_indices.n_elements()};
290 }
291
292
293
294 template <int dim, typename Number, typename IndexType>
295 inline void
297 const DoFHandler<dim, dim> &dof_handler,
298 const unsigned int n_cells,
299 const bool use_fast_hanging_node_algorithm)
300 {
301 this->dof_indices_per_cell.resize(n_cells);
302 this->plain_dof_indices_per_cell.resize(n_cells);
303 this->constraint_indicator_per_cell.resize(n_cells);
304
305 // note: has_hanging_nodes() is a global operatrion
306 const bool has_hanging_nodes =
307 dof_handler.get_triangulation().has_hanging_nodes();
308
309 if (use_fast_hanging_node_algorithm && has_hanging_nodes)
310 {
311 hanging_nodes = std::make_unique<HangingNodes<dim>>(
312 dof_handler.get_triangulation());
313
314 hanging_node_constraint_masks.resize(n_cells);
315 }
316
317 const auto &fes = dof_handler.get_fe_collection();
318 lexicographic_numbering.resize(fes.size());
319 shape_infos.resize(fes.size());
320
321 for (unsigned int i = 0; i < fes.size(); ++i)
322 {
323 if (fes[i].reference_cell().is_hyper_cube())
324 {
325 const Quadrature<1> dummy_quadrature(
326 std::vector<Point<1>>(1, Point<1>()));
327 shape_infos[i].reinit(dummy_quadrature, fes[i], 0);
328 }
329 else
330 {
331 const auto dummy_quadrature =
332 fes[i].reference_cell().get_gauss_type_quadrature(1);
333 shape_infos[i].reinit(dummy_quadrature, fes[i], 0);
334 }
335
336 lexicographic_numbering[i] = shape_infos[i].lexicographic_numbering;
337 }
338 active_fe_indices.resize(n_cells);
339 }
340
341
342
343 template <int dim, typename Number, typename IndexType>
344 inline void
346 {
347 this->dof_indices_per_cell.resize(n_cells);
348 this->plain_dof_indices_per_cell.resize(0);
349 this->constraint_indicator_per_cell.resize(n_cells);
350 }
351
352
353
354 template <int dim, typename Number, typename IndexType>
355 inline void
357 const unsigned int cell_no,
358 const unsigned int mg_level,
360 const ::AffineConstraints<typename Number::value_type> &constraints,
361 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner)
362 {
363 local_dof_indices.resize(cell->get_fe().n_dofs_per_cell());
364 local_dof_indices_lex.resize(cell->get_fe().n_dofs_per_cell());
365
366 if (mg_level == numbers::invalid_unsigned_int)
367 cell->get_dof_indices(local_dof_indices);
368 else
369 cell->get_mg_dof_indices(local_dof_indices);
370
371 {
372 AssertIndexRange(cell->active_fe_index(), shape_infos.size());
373
374 const auto &lexicographic_numbering =
375 shape_infos[cell->active_fe_index()].lexicographic_numbering;
376
377 AssertDimension(lexicographic_numbering.size(),
378 local_dof_indices.size());
379
380 for (unsigned int i = 0; i < cell->get_fe().n_dofs_per_cell(); ++i)
381 local_dof_indices_lex[i] =
382 local_dof_indices[lexicographic_numbering[i]];
383 }
384
385 std::pair<unsigned short, unsigned short> constraint_iterator(0, 0);
386
387 AssertIndexRange(cell_no, this->constraint_indicator_per_cell.size());
388 AssertIndexRange(cell_no, this->dof_indices_per_cell.size());
389 AssertIndexRange(cell_no, this->plain_dof_indices_per_cell.size());
390
391 auto &constraint_indicator = this->constraint_indicator_per_cell[cell_no];
392 auto &dof_indices = this->dof_indices_per_cell[cell_no];
393 auto &plain_dof_indices = this->plain_dof_indices_per_cell[cell_no];
394
395 AssertDimension(constraint_indicator_per_cell[cell_no].size(), 0);
396 AssertDimension(this->dof_indices_per_cell[cell_no].size(), 0);
397 AssertDimension(this->plain_dof_indices_per_cell[cell_no].size(), 0);
398
399 const auto global_to_local =
400 [&](const types::global_dof_index global_index) -> IndexType {
401 if (partitioner)
402 return partitioner->global_to_local(global_index);
403 else
404 {
405 if (local_range.first <= global_index &&
406 global_index < local_range.second)
407 return global_index - local_range.first;
408 else
409 return global_index + (local_range.second - local_range.first);
410 }
411 };
412
413 // plain indices
414 plain_dof_indices.resize(local_dof_indices_lex.size());
415 for (unsigned int i = 0; i < local_dof_indices_lex.size(); ++i)
416 plain_dof_indices[i] = global_to_local(local_dof_indices_lex[i]);
417
418 if (hanging_nodes)
419 {
420 AssertIndexRange(cell_no, this->hanging_node_constraint_masks.size());
421 AssertIndexRange(cell_no, this->active_fe_indices.size());
422
423 mask.assign(
424 cell->get_fe().n_components(),
426 hanging_nodes->setup_constraints(
427 cell, {}, lexicographic_numbering, local_dof_indices_lex, mask);
428
429 hanging_node_constraint_masks[cell_no] = compress(mask[0], dim);
430 active_fe_indices[cell_no] = cell->active_fe_index();
431 }
432
433 for (auto current_dof : local_dof_indices_lex)
434 {
435 const auto *entries_ptr =
436 constraints.get_constraint_entries(current_dof);
437
438 // dof is constrained
439 if (entries_ptr != nullptr)
440 {
441 const auto &entries = *entries_ptr;
442 const types::global_dof_index n_entries = entries.size();
443 if (n_entries == 1 &&
444 std::abs(entries[0].second -
445 typename Number::value_type(1.)) <
446 100 * std::numeric_limits<double>::epsilon())
447 {
448 current_dof = entries[0].first;
449 goto no_constraint;
450 }
451
452 constraint_indicator.push_back(constraint_iterator);
453 constraint_indicator.back().second =
454 constraint_values.insert_entries(entries);
455
456 // reset constraint iterator for next round
457 constraint_iterator.first = 0;
458
459 if (n_entries > 0)
460 {
461 const std::vector<types::global_dof_index>
462 &constraint_indices = constraint_values.constraint_indices;
463 for (unsigned int j = 0; j < n_entries; ++j)
464 {
465 dof_indices.push_back(
466 global_to_local(constraint_indices[j]));
467 }
468 }
469 }
470 else
471 {
472 no_constraint:
473 dof_indices.push_back(global_to_local(current_dof));
474
475 // make sure constraint_iterator.first is always within the
476 // bounds of unsigned short
477 Assert(constraint_iterator.first <
478 (1 << (8 * sizeof(unsigned short))) - 1,
480 constraint_iterator.first++;
481 }
482 }
483 }
484
485
486
487 template <int dim, typename Number, typename IndexType>
488 inline void
490 const unsigned int cell_no,
491 const std::vector<types::global_dof_index> &local_dof_indices_lex,
492 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner)
493 {
494 const auto global_to_local =
495 [&](const types::global_dof_index global_index) -> IndexType {
496 if (partitioner)
497 return partitioner->global_to_local(global_index);
498 else
499 {
500 if (local_range.first <= global_index &&
501 global_index < local_range.second)
502 return global_index - local_range.first;
503 else
504 return global_index + (local_range.second - local_range.first);
505 }
506 };
507
508 std::pair<unsigned short, unsigned short> constraint_iterator(0, 0);
509
510 auto &constraint_indicator = this->constraint_indicator_per_cell[cell_no];
511 auto &dof_indices = this->dof_indices_per_cell[cell_no];
512
513 for (const auto current_dof : local_dof_indices_lex)
514 {
515 // dof is constrained
516 if (current_dof == numbers::invalid_dof_index)
517 {
518 const std::vector<
519 std::pair<types::global_dof_index, typename Number::value_type>>
520 entries = {};
521
522 constraint_indicator.push_back(constraint_iterator);
523 constraint_indicator.back().second =
524 constraint_values.insert_entries(entries);
525
526 constraint_iterator.first = 0;
527 }
528 else
529 {
530 dof_indices.push_back(global_to_local(current_dof));
531
532 // make sure constraint_iterator.first is always within the
533 // bounds of unsigned short
534 Assert(constraint_iterator.first <
535 (1 << (8 * sizeof(unsigned short))) - 1,
537 constraint_iterator.first++;
538 }
539 }
540 }
541
542
543
544 template <int dim, typename Number, typename IndexType>
545 inline void
547 {
549 std::pair<types::global_dof_index, types::global_dof_index>{0,
550 0}),
552
553 this->dof_indices = {};
554 this->plain_dof_indices = {};
555 this->constraint_indicator = {};
556
557 this->row_starts = {};
558 this->row_starts.emplace_back(0, 0);
559
560 if (this->plain_dof_indices_per_cell.empty() == false)
561 {
562 this->row_starts_plain_indices = {};
563 this->row_starts_plain_indices.emplace_back(0);
564 }
565
566 for (unsigned int i = 0; i < this->dof_indices_per_cell.size(); ++i)
567 {
568 this->dof_indices.insert(this->dof_indices.end(),
569 this->dof_indices_per_cell[i].begin(),
570 this->dof_indices_per_cell[i].end());
571 this->constraint_indicator.insert(
572 this->constraint_indicator.end(),
573 constraint_indicator_per_cell[i].begin(),
574 constraint_indicator_per_cell[i].end());
575
576 this->row_starts.emplace_back(this->dof_indices.size(),
577 this->constraint_indicator.size());
578
579 if (this->plain_dof_indices_per_cell.empty() == false)
580 {
581 this->plain_dof_indices.insert(
582 this->plain_dof_indices.end(),
583 this->plain_dof_indices_per_cell[i].begin(),
584 this->plain_dof_indices_per_cell[i].end());
585
586 this->row_starts_plain_indices.emplace_back(
587 this->plain_dof_indices.size());
588 }
589 }
590
591 std::vector<const std::vector<double> *> constraints(
592 constraint_values.constraints.size());
593 unsigned int length = 0;
594 for (const auto &it : constraint_values.constraints)
595 {
596 AssertIndexRange(it.second, constraints.size());
597 constraints[it.second] = &it.first;
598 length += it.first.size();
599 }
600
601 constraint_pool_data.clear();
602 constraint_pool_data.reserve(length);
603 constraint_pool_row_index.reserve(constraint_values.constraints.size() +
604 1);
605 constraint_pool_row_index.resize(1, 0);
606
607 for (const auto &constraint : constraints)
608 {
609 Assert(constraint != nullptr, ExcInternalError());
610 constraint_pool_data.insert(constraint_pool_data.end(),
611 constraint->begin(),
612 constraint->end());
613 constraint_pool_row_index.push_back(constraint_pool_data.size());
614 }
615
616 AssertDimension(constraint_pool_data.size(), length);
617
618 this->dof_indices_per_cell.clear();
619 this->plain_dof_indices_per_cell.clear();
620 constraint_indicator_per_cell.clear();
621
622 if (hanging_nodes &&
623 std::all_of(hanging_node_constraint_masks.begin(),
624 hanging_node_constraint_masks.end(),
625 [](const auto i) {
626 return i == unconstrained_compressed_constraint_kind;
627 }))
628 hanging_node_constraint_masks.clear();
629 }
630
631
632 template <int dim, typename Number, typename IndexType>
633 inline std::shared_ptr<const Utilities::MPI::Partitioner>
635 {
636 this->dof_indices.clear();
637 this->plain_dof_indices.clear();
638 this->constraint_indicator.clear();
639
640 this->row_starts.clear();
641 this->row_starts.reserve(this->dof_indices_per_cell.size());
642 this->row_starts.emplace_back(0, 0);
643
644 if (this->plain_dof_indices_per_cell.empty() == false)
645 {
646 this->row_starts_plain_indices.clear();
647 this->row_starts_plain_indices.reserve(
648 this->dof_indices_per_cell.size());
649 this->row_starts_plain_indices.emplace_back(0);
650 }
651
652 std::vector<types::global_dof_index> ghost_dofs;
653 std::pair<unsigned int, unsigned int> counts = {0, 0};
654
655 for (unsigned int i = 0; i < this->dof_indices_per_cell.size(); ++i)
656 {
657 counts.first += this->dof_indices_per_cell[i].size();
658
659 for (const auto &j : this->dof_indices_per_cell[i])
660 if (j >= (local_range.second - local_range.first))
661 ghost_dofs.push_back(j -
662 (local_range.second - local_range.first));
663
664 if (this->plain_dof_indices_per_cell.empty() == false)
665 {
666 counts.second += this->plain_dof_indices_per_cell[i].size();
667
668 for (const auto &j : this->plain_dof_indices_per_cell[i])
669 if (j >= (local_range.second - local_range.first))
670 ghost_dofs.push_back(
671 j - (local_range.second - local_range.first));
672 }
673 }
674
675 std::sort(ghost_dofs.begin(), ghost_dofs.end());
676 ghost_dofs.erase(std::unique(ghost_dofs.begin(), ghost_dofs.end()),
677 ghost_dofs.end());
678
679 IndexSet locally_relevant_dofs(locally_owned_indices.size());
680 locally_relevant_dofs.add_indices(ghost_dofs.begin(), ghost_dofs.end());
681
682 const auto partitioner =
683 std::make_shared<Utilities::MPI::Partitioner>(locally_owned_indices,
684 locally_relevant_dofs,
685 comm);
686
687 this->dof_indices.reserve(counts.first);
688 this->plain_dof_indices.reserve(counts.second);
689
690 for (unsigned int i = 0; i < this->dof_indices_per_cell.size(); ++i)
691 {
692 for (const auto &j : this->dof_indices_per_cell[i])
693 if (j < (local_range.second - local_range.first))
694 this->dof_indices.push_back(j);
695 else
696 this->dof_indices.push_back(partitioner->global_to_local(
697 j - (local_range.second - local_range.first)));
698
699 this->constraint_indicator.insert(
700 this->constraint_indicator.end(),
701 constraint_indicator_per_cell[i].begin(),
702 constraint_indicator_per_cell[i].end());
703
704 this->row_starts.emplace_back(this->dof_indices.size(),
705 this->constraint_indicator.size());
706
707 if (this->plain_dof_indices_per_cell.empty() == false)
708 {
709 for (const auto &j : this->plain_dof_indices_per_cell[i])
710 if (j < (local_range.second - local_range.first))
711 this->plain_dof_indices.push_back(j);
712 else
713 this->plain_dof_indices.push_back(
714 partitioner->global_to_local(
715 j - (local_range.second - local_range.first)));
716
717 this->row_starts_plain_indices.emplace_back(
718 this->plain_dof_indices.size());
719 }
720 }
721
722 std::vector<const std::vector<double> *> constraints(
723 constraint_values.constraints.size());
724 unsigned int length = 0;
725 for (const auto &it : constraint_values.constraints)
726 {
727 AssertIndexRange(it.second, constraints.size());
728 constraints[it.second] = &it.first;
729 length += it.first.size();
730 }
731
732 constraint_pool_data.clear();
733 constraint_pool_data.reserve(length);
734 constraint_pool_row_index.reserve(constraint_values.constraints.size() +
735 1);
736 constraint_pool_row_index.resize(1, 0);
737
738 for (const auto &constraint : constraints)
739 {
740 Assert(constraint != nullptr, ExcInternalError());
741 constraint_pool_data.insert(constraint_pool_data.end(),
742 constraint->begin(),
743 constraint->end());
744 constraint_pool_row_index.push_back(constraint_pool_data.size());
745 }
746
747 AssertDimension(constraint_pool_data.size(), length);
748
749 this->dof_indices_per_cell.clear();
750 this->plain_dof_indices_per_cell.clear();
751 constraint_indicator_per_cell.clear();
752
753 if (hanging_nodes &&
754 std::all_of(hanging_node_constraint_masks.begin(),
755 hanging_node_constraint_masks.end(),
756 [](const auto i) {
757 return i == unconstrained_compressed_constraint_kind;
758 }))
759 hanging_node_constraint_masks.clear();
760
761 return partitioner;
762 }
763
764
765
766 template <int dim, typename Number, typename IndexType>
767 template <typename T, typename VectorType>
768 inline void
770 const T &operation,
771 VectorType &global_vector,
772 Number *local_vector,
773 const unsigned int first_cell,
774 const unsigned int n_cells,
775 const unsigned int n_dofs_per_cell,
776 const bool apply_constraints) const
777 {
778 if ((row_starts_plain_indices.empty() == false) &&
779 (apply_constraints == false))
780 {
781 for (unsigned int v = 0; v < n_cells; ++v)
782 {
783 const unsigned int cell_index = first_cell + v;
784 const unsigned int *dof_indices =
785 this->plain_dof_indices.data() +
786 this->row_starts_plain_indices[cell_index];
787
788 for (unsigned int i = 0; i < n_dofs_per_cell; ++dof_indices, ++i)
789 operation.process_dof(*dof_indices,
790 global_vector,
791 local_vector[i][v]);
792 }
793
794 return;
795 }
796
797 for (unsigned int v = 0; v < n_cells; ++v)
798 {
799 const unsigned int cell_index = first_cell + v;
800 const unsigned int *dof_indices =
801 this->dof_indices.data() + this->row_starts[cell_index].first;
802 unsigned int index_indicators = this->row_starts[cell_index].second;
803 unsigned int next_index_indicators =
804 this->row_starts[cell_index + 1].second;
805
806 unsigned int ind_local = 0;
807 for (; index_indicators != next_index_indicators; ++index_indicators)
808 {
809 const std::pair<unsigned short, unsigned short> indicator =
810 this->constraint_indicator[index_indicators];
811
812 // run through values up to next constraint
813 for (unsigned int j = 0; j < indicator.first; ++j)
814 operation.process_dof(dof_indices[j],
815 global_vector,
816 local_vector[ind_local + j][v]);
817
818 ind_local += indicator.first;
819 dof_indices += indicator.first;
820
821 // constrained case: build the local value as a linear
822 // combination of the global value according to constraints
823 typename Number::value_type value;
824 operation.pre_constraints(local_vector[ind_local][v], value);
825
826 const typename Number::value_type *data_val =
827 this->constraint_pool_begin(indicator.second);
828 const typename Number::value_type *end_pool =
829 this->constraint_pool_end(indicator.second);
830 for (; data_val != end_pool; ++data_val, ++dof_indices)
831 operation.process_constraint(*dof_indices,
832 *data_val,
833 global_vector,
834 value);
835
836 operation.post_constraints(value, local_vector[ind_local][v]);
837 ++ind_local;
838 }
839
840 AssertIndexRange(ind_local, n_dofs_per_cell + 1);
841
842 for (; ind_local < n_dofs_per_cell; ++dof_indices, ++ind_local)
843 operation.process_dof(*dof_indices,
844 global_vector,
845 local_vector[ind_local][v]);
846 }
847 }
848
849
850
851 template <int dim, typename Number, typename IndexType>
852 inline void
854 const unsigned int first_cell,
855 const unsigned int n_lanes_filled,
856 const bool transpose,
857 AlignedVector<Number> &evaluation_data_coarse) const
858 {
859 if (hanging_node_constraint_masks.empty())
860 return;
861
863 Number::size()>
864 constraint_mask;
865
866 bool hn_available = false;
867
868 for (unsigned int v = 0; v < n_lanes_filled; ++v)
869 {
870 const auto mask = hanging_node_constraint_masks[first_cell + v];
871
872 constraint_mask[v] = mask;
873
875 }
876
877 if (hn_available == true)
878 {
879 std::fill(constraint_mask.begin() + n_lanes_filled,
880 constraint_mask.end(),
882
883 for (unsigned int i = 1; i < n_lanes_filled; ++i)
884 AssertDimension(active_fe_indices[first_cell],
885 active_fe_indices[first_cell + i]);
886
887 const auto &shape_info = shape_infos[active_fe_indices[first_cell]];
888
890 dim,
891 typename Number::value_type,
892 Number>::apply(shape_info.n_components,
893 shape_info.data.front().fe_degree,
894 shape_info,
895 transpose,
896 constraint_mask,
897 evaluation_data_coarse.begin());
898 }
899 }
900
901
902
903 template <int dim, typename Number, typename IndexType>
904 inline const typename Number::value_type *
906 const unsigned int row) const
907 {
908 AssertIndexRange(row, constraint_pool_row_index.size() - 1);
909 return constraint_pool_data.empty() ?
910 nullptr :
911 constraint_pool_data.data() + constraint_pool_row_index[row];
912 }
913
914
915
916 template <int dim, typename Number, typename IndexType>
917 inline const typename Number::value_type *
919 const unsigned int row) const
920 {
921 AssertIndexRange(row, constraint_pool_row_index.size() - 1);
922 return constraint_pool_data.empty() ?
923 nullptr :
924 constraint_pool_data.data() + constraint_pool_row_index[row + 1];
925 }
926
927
928
929 template <int dim, typename Number, typename IndexType>
930 inline std::size_t
932 {
933 std::size_t size = 0;
934
935 size += MemoryConsumption::memory_consumption(constraint_values);
936 size += MemoryConsumption::memory_consumption(dof_indices_per_cell);
937 size += MemoryConsumption::memory_consumption(plain_dof_indices_per_cell);
938 size +=
939 MemoryConsumption::memory_consumption(constraint_indicator_per_cell);
940
941 if (hanging_nodes)
943
944 size += MemoryConsumption::memory_consumption(lexicographic_numbering);
946 size += MemoryConsumption::memory_consumption(constraint_indicator);
948 size += MemoryConsumption::memory_consumption(plain_dof_indices);
949 size += MemoryConsumption::memory_consumption(row_starts_plain_indices);
950 size += MemoryConsumption::memory_consumption(constraint_pool_data);
951 size += MemoryConsumption::memory_consumption(constraint_pool_row_index);
953 size +=
954 MemoryConsumption::memory_consumption(hanging_node_constraint_masks);
955 size += MemoryConsumption::memory_consumption(active_fe_indices);
956
957 return size;
958 }
959
960
961
962 template <typename Number>
963 inline std::size_t
965 {
966 std::size_t size = 0;
967
968 size += MemoryConsumption::memory_consumption(constraint_entries);
969 size += MemoryConsumption::memory_consumption(constraint_indices);
970
971 // TODO: map does not have memory_consumption()
972 // size += MemoryConsumption::memory_consumption(constraints);
973
974 return size;
975 }
976
977 } // namespace MatrixFreeFunctions
978} // namespace internal
979
981
982#endif
iterator begin()
const hp::FECollection< dim, spacedim > & get_fe_collection() const
const Triangulation< dim, spacedim > & get_triangulation() const
bool is_empty() const
Definition index_set.h:1909
size_type n_elements() const
Definition index_set.h:1917
size_type nth_index_in_set(const size_type local_index) const
Definition index_set.h:1958
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
Definition point.h:111
virtual bool has_hanging_nodes() const
void apply_hanging_node_constraints(const unsigned int first_cell, const unsigned int n_lanes_filled, const bool transpose, AlignedVector< Number > &evaluation_data_coarse) const
std::vector< ShapeInfo< typename Number::value_type > > shape_infos
std::vector< std::vector< unsigned int > > lexicographic_numbering
void read_write_operation(const T &operation, VectorType &global_vector, Number *local_vector, const unsigned int first_cell, const unsigned int n_cells, const unsigned int n_dofs_per_cell, const bool apply_constraints) const
std::vector< typename Number::value_type > constraint_pool_data
std::vector< std::pair< unsigned short, unsigned short > > constraint_indicator
const Number::value_type * constraint_pool_begin(const unsigned int row) const
std::vector< types::global_dof_index > local_dof_indices_lex
std::vector< std::vector< IndexType > > dof_indices_per_cell
void set_locally_owned_indices(const IndexSet &locally_owned_indices)
void read_dof_indices(const unsigned int cell_no, const std::vector< types::global_dof_index > &dof_indices, const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner)
std::pair< types::global_dof_index, types::global_dof_index > local_range
const Number::value_type * constraint_pool_end(const unsigned int row) const
std::vector< types::global_dof_index > local_dof_indices
std::vector< compressed_constraint_kind > hanging_node_constraint_masks
std::shared_ptr< const Utilities::MPI::Partitioner > finalize(const MPI_Comm comm)
std::vector< unsigned int > constraint_pool_row_index
std::unique_ptr< HangingNodes< dim > > hanging_nodes
void read_dof_indices(const unsigned int cell_no, const unsigned int mg_level, const TriaIterator< DoFCellAccessor< dim, dim, false > > &cell, const ::AffineConstraints< typename Number::value_type > &constraints, const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner)
std::vector< std::vector< std::pair< unsigned short, unsigned short > > > constraint_indicator_per_cell
std::vector< std::vector< IndexType > > plain_dof_indices_per_cell
void reinit(const unsigned int n_cells)
void reinit(const DoFHandler< dim, dim > &dof_handler, const unsigned int n_cells, const bool use_fast_hanging_node_algorithm=true)
std::vector< unsigned int > row_starts_plain_indices
std::vector< std::pair< unsigned int, unsigned int > > row_starts
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
Point< 2 > second
Definition grid_out.cc:4640
unsigned int cell_index
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
std::pair< types::global_dof_index, types::global_dof_index > local_range
Definition mpi.cc:814
std::size_t size
Definition mpi.cc:733
const MPI_Comm comm
Definition mpi.cc:912
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
compressed_constraint_kind compress(const ConstraintKinds kind_in, const unsigned int dim)
std::uint8_t compressed_constraint_kind
Definition dof_info.h:84
constexpr compressed_constraint_kind unconstrained_compressed_constraint_kind
constexpr types::global_dof_index invalid_dof_index
Definition types.h:259
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
STL namespace.
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:92
std::vector< types::global_dof_index > constraint_indices
std::map< std::vector< Number >, types::global_dof_index, FloatingPointComparator< Number > > constraints
unsigned short insert_entries(const std::vector< std::pair< types::global_dof_index, number2 > > &entries)
std::vector< std::pair< types::global_dof_index, double > > constraint_entries
std::pair< std::vector< Number >, types::global_dof_index > next_constraint