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
mapping_q_cache.cc
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) 2019 - 2025 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
17
19
20#include <deal.II/fe/fe_dgq.h>
22#include <deal.II/fe/fe_q.h>
23#include <deal.II/fe/fe_tools.h>
26
30
31#include <functional>
32
34
35template <int dim, int spacedim>
37 const unsigned int polynomial_degree)
38 : MappingQ<dim, spacedim>(polynomial_degree)
39 , uses_level_info(false)
40{}
41
42
43
44template <int dim, int spacedim>
46 const MappingQCache<dim, spacedim> &mapping)
47 : MappingQ<dim, spacedim>(mapping)
48 , support_point_cache(mapping.support_point_cache)
49 , uses_level_info(mapping.uses_level_info)
50{}
51
52
53
54template <int dim, int spacedim>
56{
57 // When this object goes out of scope, we want the cache to get cleared and
58 // free its memory before the signal is disconnected in order to not work on
59 // invalid memory that has been left back by freeing an object of this
60 // class.
61 support_point_cache.reset();
62 clear_signal.disconnect();
63}
64
65
66
67template <int dim, int spacedim>
68std::unique_ptr<Mapping<dim, spacedim>>
70{
71 return std::make_unique<MappingQCache<dim, spacedim>>(*this);
72}
73
74
75
76template <int dim, int spacedim>
77bool
82
83
84
85template <int dim, int spacedim>
86void
88 const Mapping<dim, spacedim> &mapping,
89 const Triangulation<dim, spacedim> &triangulation)
90{
91 // FE and FEValues in the case they are needed
94 fe_values_all;
95
96 this->initialize(
97 triangulation,
98 [&](const typename Triangulation<dim, spacedim>::cell_iterator &cell) {
99 const auto mapping_q =
100 dynamic_cast<const MappingQ<dim, spacedim> *>(&mapping);
101 if (mapping_q != nullptr && this->get_degree() == mapping_q->get_degree())
102 {
103 boost::container::small_vector<Point<spacedim>, 200> points;
104 mapping_q->compute_mapping_support_points(cell, points);
105 return std::vector<Point<spacedim>>(points.begin(), points.end());
106 }
107 else
108 {
109 // get FEValues (thread-safe); in the case that this thread has not
110 // created a an FEValues object yet, this helper-function also
111 // creates one with the right quadrature rule
112 auto &fe_values = fe_values_all.get();
113 if (fe_values.get() == nullptr)
114 {
115 const QGaussLobatto<dim> quadrature_gl(this->polynomial_degree +
116 1);
117
118 std::vector<Point<dim>> quadrature_points;
119 for (const auto i :
120 FETools::hierarchic_to_lexicographic_numbering<dim>(
121 this->polynomial_degree))
122 quadrature_points.push_back(quadrature_gl.point(i));
123 const Quadrature<dim> quadrature(quadrature_points);
124
125 fe_values = std::make_unique<FEValues<dim, spacedim>>(
126 mapping, fe, quadrature, update_quadrature_points);
127 }
128
129 fe_values->reinit(cell);
130 return fe_values->get_quadrature_points();
131 }
132 });
133}
134
135
136
137template <int dim, int spacedim>
138void
140 const Triangulation<dim, spacedim> &triangulation,
141 const std::function<std::vector<Point<spacedim>>(
143 &compute_points_on_cell)
144{
145 clear_signal.disconnect();
146 clear_signal = triangulation.signals.any_change.connect(
147 [&]() -> void { this->support_point_cache.reset(); });
148
149 support_point_cache =
150 std::make_shared<std::vector<std::vector<std::vector<Point<spacedim>>>>>(
151 triangulation.n_levels());
152 for (unsigned int l = 0; l < triangulation.n_levels(); ++l)
153 (*support_point_cache)[l].resize(triangulation.n_raw_cells(l));
154
156 triangulation.begin(),
157 triangulation.end(),
158 [&](const typename Triangulation<dim, spacedim>::cell_iterator &cell,
159 void *,
160 void *) {
161 const auto result = compute_points_on_cell(cell);
162 (*support_point_cache)[cell->level()][cell->index()].assign(
163 result.begin(), result.end());
164 // Do not use `this` in Assert because nvcc when using C++20 assumes that
165 // `this` is an integer and we get the following error: invalid type
166 // argument of unary '*' (have 'int')
167 const unsigned int d = this->get_degree() + 1;
168 AssertDimension(
169 (*support_point_cache)[cell->level()][cell->index()].size(),
170 Utilities::pow(d, dim));
171 },
172 /* copier */ std::function<void(void *)>(),
173 /* scratch_data */ nullptr,
174 /* copy_data */ nullptr,
176 /* chunk_size = */ 1);
177
178 uses_level_info = true;
179}
180
181
182
183template <int dim, int spacedim>
184void
186 const Mapping<dim, spacedim> &mapping,
188 const std::function<Point<spacedim>(
190 const Point<spacedim> &)> &transformation_function,
191 const bool function_describes_relative_displacement)
192{
193 // FE and FEValues in the case they are needed
196 fe_values_all;
197
198 this->initialize(
199 tria,
200 [&](const typename Triangulation<dim, spacedim>::cell_iterator &cell) {
201 boost::container::small_vector<Point<spacedim>, 200> points;
202
203 const auto mapping_q =
204 dynamic_cast<const MappingQ<dim, spacedim> *>(&mapping);
205
206 if (mapping_q != nullptr && this->get_degree() == mapping_q->get_degree())
207 {
208 mapping_q->compute_mapping_support_points(cell, points);
209 }
210 else
211 {
212 // get FEValues (thread-safe); in the case that this thread has not
213 // created a an FEValues object yet, this helper-function also
214 // creates one with the right quadrature rule
215 auto &fe_values = fe_values_all.get();
216 if (fe_values.get() == nullptr)
217 {
218 const QGaussLobatto<dim> quadrature_gl(this->polynomial_degree +
219 1);
220
221 std::vector<Point<dim>> quadrature_points;
222 for (const auto i :
223 FETools::hierarchic_to_lexicographic_numbering<dim>(
224 this->polynomial_degree))
225 quadrature_points.push_back(quadrature_gl.point(i));
226 const Quadrature<dim> quadrature(quadrature_points);
227
228 fe_values = std::make_unique<FEValues<dim, spacedim>>(
229 mapping, fe, quadrature, update_quadrature_points);
230 }
231
232 fe_values->reinit(cell);
233 const auto &quadrature_points = fe_values->get_quadrature_points();
234 points.assign(quadrature_points.begin(), quadrature_points.end());
235 }
236
237 for (auto &p : points)
238 if (function_describes_relative_displacement)
239 p += transformation_function(cell, p);
240 else
241 p = transformation_function(cell, p);
242
243 return std::vector<Point<spacedim>>(points.begin(), points.end());
244 });
245
246 uses_level_info = true;
247}
248
249
250
251template <int dim, int spacedim>
252void
254 const Mapping<dim, spacedim> &mapping,
256 const Function<spacedim> &transformation_function,
257 const bool function_describes_relative_displacement)
258{
259 AssertDimension(transformation_function.n_components, spacedim);
260
261 this->initialize(
262 mapping,
263 tria,
264 [&](const auto &, const auto &point) {
265 Point<spacedim> new_point;
266 for (unsigned int c = 0; c < spacedim; ++c)
267 new_point[c] = transformation_function.value(point, c);
268 return new_point;
269 },
270 function_describes_relative_displacement);
271
272 uses_level_info = true;
273}
274
275
276
277namespace
278{
279 template <typename VectorType>
280 void
281 copy_locally_owned_data_from(
282 const VectorType &vector,
284 &vector_ghosted)
285 {
287 temp.reinit(vector.locally_owned_elements());
289 vector_ghosted.import_elements(temp, VectorOperation::insert);
290 }
291} // namespace
292
293
294
295template <int dim, int spacedim>
296template <typename VectorType>
297void
299 const Mapping<dim, spacedim> &mapping,
300 const DoFHandler<dim, spacedim> &dof_handler,
301 const VectorType &vector,
302 const bool vector_describes_relative_displacement)
303{
304 AssertDimension(dof_handler.get_fe_collection().size(), 1);
305 const FiniteElement<dim, spacedim> &fe = dof_handler.get_fe();
307 AssertDimension(fe.element_multiplicity(0), spacedim);
308
309 const unsigned int is_fe_q =
310 dynamic_cast<const FE_Q<dim, spacedim> *>(&fe.base_element(0)) != nullptr;
311 const unsigned int is_fe_dgq =
312 dynamic_cast<const FE_DGQ<dim, spacedim> *>(&fe.base_element(0)) != nullptr;
313
314 const auto lexicographic_to_hierarchic_numbering =
316 FETools::hierarchic_to_lexicographic_numbering<spacedim>(
317 this->get_degree()));
318
319 // Step 1: copy global vector so that the ghost values are such that the
320 // cache can be set up for all ghost cells
322 vector_ghosted;
323 const IndexSet locally_relevant_dofs =
325 vector_ghosted.reinit(dof_handler.locally_owned_dofs(),
326 locally_relevant_dofs,
327 dof_handler.get_mpi_communicator());
328 copy_locally_owned_data_from(vector, vector_ghosted);
329 vector_ghosted.update_ghost_values();
330
331 // FE and FEValues in the case they are needed
332 FE_Nothing<dim, spacedim> fe_nothing;
334 fe_values_all;
335
336 // Interpolation of values is needed if we cannot just read off locations
337 // from the solution vectors (as in the case of FE_Q and FE_DGQ with the
338 // same polynomial degree as this class has).
339 const bool interpolation_of_values_is_needed =
340 ((is_fe_q || is_fe_dgq) && fe.degree == this->get_degree()) == false;
341
342 // Step 2: loop over all cells
343 this->initialize(
344 dof_handler.get_triangulation(),
345 [&](const typename Triangulation<dim, spacedim>::cell_iterator &cell_tria)
346 -> std::vector<Point<spacedim>> {
347 const bool is_active_non_artificial_cell =
348 (cell_tria->is_active() == true) &&
349 (cell_tria->is_artificial() == false);
350
351 const typename DoFHandler<dim, spacedim>::cell_iterator cell_dofs(
352 &cell_tria->get_triangulation(),
353 cell_tria->level(),
354 cell_tria->index(),
355 &dof_handler);
356
357 const auto mapping_q =
358 dynamic_cast<const MappingQ<dim, spacedim> *>(&mapping);
359
360 // Step 2a) set up and reinit FEValues (if needed)
361 if (
362 ((vector_describes_relative_displacement ||
363 (is_active_non_artificial_cell == false)) &&
364 ((mapping_q != nullptr &&
365 this->get_degree() == mapping_q->get_degree()) ==
366 false)) /*condition 1: points need to be computed via FEValues*/
367 ||
368 (is_active_non_artificial_cell && interpolation_of_values_is_needed) /*condition 2: interpolation of values is needed*/)
369 {
370 // get FEValues (thread-safe); in the case that this thread has
371 // not created a an FEValues object yet, this helper-function also
372 // creates one with the right quadrature rule
373 auto &fe_values = fe_values_all.get();
374 if (fe_values.get() == nullptr)
375 {
376 const QGaussLobatto<dim> quadrature_gl(this->polynomial_degree +
377 1);
378
379 std::vector<Point<dim>> quadrature_points;
380 for (const auto i :
381 FETools::hierarchic_to_lexicographic_numbering<dim>(
382 this->polynomial_degree))
383 quadrature_points.push_back(quadrature_gl.point(i));
384 const Quadrature<dim> quadrature(quadrature_points);
385
386 fe_values = std::make_unique<FEValues<dim, spacedim>>(
387 mapping,
388 interpolation_of_values_is_needed ?
389 fe :
390 static_cast<const FiniteElement<dim, spacedim> &>(fe_nothing),
391 quadrature,
392 update_quadrature_points | update_values);
393 }
394
395 if (interpolation_of_values_is_needed)
396 fe_values->reinit(cell_dofs);
397 else
398 fe_values->reinit(cell_tria);
399 }
400
401 boost::container::small_vector<Point<spacedim>, 200> points;
402
403 // Step 2b) read of quadrature points in the relative displacement case
404 // note: we also take this path for non-active or artificial cells so that
405 // these cells are filled with some useful data
406 if (vector_describes_relative_displacement ||
407 is_active_non_artificial_cell == false)
408 {
409 if (mapping_q != nullptr &&
410 this->get_degree() == mapping_q->get_degree())
411 {
412 mapping_q->compute_mapping_support_points(cell_tria, points);
413 }
414 else
415 {
416 const auto &quadrature_points =
417 fe_values_all.get()->get_quadrature_points();
418 points.assign(quadrature_points.begin(), quadrature_points.end());
419 }
420
421 // for non-active or artificial cells we are done here and return
422 // the absolute positions, since the provided vector cannot contain
423 // any useful information for these cells
424 if (is_active_non_artificial_cell == false)
425 return std::vector<Point<spacedim>>(points.begin(), points.end());
426 }
427 else
428 {
429 points.resize(
430 Utilities::pow<unsigned int>(this->get_degree() + 1, dim));
431 }
432
433 // Step 2c) read global vector and adjust points accordingly
434 if (interpolation_of_values_is_needed == false)
435 {
436 // case 1: FE_Q or FE_DGQ with same degree as this class has; this
437 // is the simple case since no interpolation is needed
438 std::vector<types::global_dof_index> dof_indices(
439 fe.n_dofs_per_cell());
440 cell_dofs->get_dof_indices(dof_indices);
441
442 for (unsigned int i = 0; i < dof_indices.size(); ++i)
443 {
444 const auto id = fe.system_to_component_index(i);
445
446 if (is_fe_q)
447 {
448 // case 1a: FE_Q
449 if (vector_describes_relative_displacement)
450 points[id.second][id.first] +=
451 vector_ghosted(dof_indices[i]);
452 else
453 points[id.second][id.first] =
454 vector_ghosted(dof_indices[i]);
455 }
456 else
457 {
458 // case 1b: FE_DGQ
459 if (vector_describes_relative_displacement)
460 points[lexicographic_to_hierarchic_numbering[id.second]]
461 [id.first] += vector_ghosted(dof_indices[i]);
462 else
463 points[lexicographic_to_hierarchic_numbering[id.second]]
464 [id.first] = vector_ghosted(dof_indices[i]);
465 }
466 }
467 }
468 else
469 {
470 // case 2: general case; interpolation is needed
471 // note: the following code could be optimized for tensor-product
472 // elements via application of sum factorization as is done on
473 // MatrixFree/FEEvaluation
474 auto &fe_values = fe_values_all.get();
475
476 std::vector<Vector<typename VectorType::value_type>> values(
477 fe_values->n_quadrature_points,
479
480 fe_values->get_function_values(vector_ghosted, values);
481
482 for (unsigned int q = 0; q < fe_values->n_quadrature_points; ++q)
483 for (unsigned int c = 0; c < spacedim; ++c)
484 if (vector_describes_relative_displacement)
485 points[q][c] += values[q][c];
486 else
487 points[q][c] = values[q][c];
488 }
489
490 return std::vector<Point<spacedim>>(points.begin(), points.end());
491 });
492
493 uses_level_info = false;
494}
495
496
497
498template <int dim, int spacedim>
499template <typename VectorType>
500void
502 const Mapping<dim, spacedim> &mapping,
503 const DoFHandler<dim, spacedim> &dof_handler,
504 const MGLevelObject<VectorType> &vectors,
505 const bool vector_describes_relative_displacement)
506{
507 AssertDimension(dof_handler.get_fe_collection().size(), 1);
508 const FiniteElement<dim, spacedim> &fe = dof_handler.get_fe();
510 AssertDimension(fe.element_multiplicity(0), spacedim);
511 AssertDimension(0, vectors.min_level());
513 vectors.max_level());
514
515 const unsigned int is_fe_q =
516 dynamic_cast<const FE_Q<dim, spacedim> *>(&fe.base_element(0)) != nullptr;
517 const unsigned int is_fe_dgq =
518 dynamic_cast<const FE_DGQ<dim, spacedim> *>(&fe.base_element(0)) != nullptr;
519
520 const auto lexicographic_to_hierarchic_numbering =
522 FETools::hierarchic_to_lexicographic_numbering<spacedim>(
523 this->get_degree()));
524
525 // Step 1: copy global vector so that the ghost values are such that the
526 // cache can be set up for all ghost cells
529 vectors_ghosted(vectors.min_level(), vectors.max_level());
530
531 for (unsigned int l = vectors.min_level(); l <= vectors.max_level(); ++l)
532 {
533 const IndexSet locally_relevant_dofs =
535 vectors_ghosted[l].reinit(dof_handler.locally_owned_mg_dofs(l),
536 locally_relevant_dofs,
537 dof_handler.get_mpi_communicator());
538 copy_locally_owned_data_from(vectors[l], vectors_ghosted[l]);
539 vectors_ghosted[l].update_ghost_values();
540 }
541
542 // FE and FEValues in the case they are needed
543 FE_Nothing<dim, spacedim> fe_nothing;
545 fe_values_all;
546
547 // Interpolation of values is needed if we cannot just read off locations
548 // from the solution vectors (as in the case of FE_Q and FE_DGQ with the
549 // same polynomial degree as this class has).
550 const bool interpolation_of_values_is_needed =
551 ((is_fe_q || is_fe_dgq) && fe.degree == this->get_degree()) == false;
552
553 // Step 2: loop over all cells
554 this->initialize(
555 dof_handler.get_triangulation(),
556 [&](const typename Triangulation<dim, spacedim>::cell_iterator &cell_tria)
557 -> std::vector<Point<spacedim>> {
558 const bool is_non_artificial_cell =
559 cell_tria->level_subdomain_id() != numbers::artificial_subdomain_id;
560
561 const typename DoFHandler<dim, spacedim>::level_cell_iterator cell_dofs(
562 &cell_tria->get_triangulation(),
563 cell_tria->level(),
564 cell_tria->index(),
565 &dof_handler);
566
567 const auto mapping_q =
568 dynamic_cast<const MappingQ<dim, spacedim> *>(&mapping);
569
570 // Step 2a) set up and reinit FEValues (if needed)
571 if (
572 ((vector_describes_relative_displacement ||
573 (is_non_artificial_cell == false)) &&
574 ((mapping_q != nullptr &&
575 this->get_degree() == mapping_q->get_degree()) ==
576 false)) /*condition 1: points need to be computed via FEValues*/
577 ||
578 (is_non_artificial_cell == true && interpolation_of_values_is_needed) /*condition 2: interpolation of values is needed*/)
579 {
580 // get FEValues (thread-safe); in the case that this thread has
581 // not created a an FEValues object yet, this helper-function also
582 // creates one with the right quadrature rule
583 auto &fe_values = fe_values_all.get();
584 if (fe_values.get() == nullptr)
585 {
586 const QGaussLobatto<dim> quadrature_gl(this->polynomial_degree +
587 1);
588
589 std::vector<Point<dim>> quadrature_points;
590 for (const auto i :
591 FETools::hierarchic_to_lexicographic_numbering<dim>(
592 this->polynomial_degree))
593 quadrature_points.push_back(quadrature_gl.point(i));
594 const Quadrature<dim> quadrature(quadrature_points);
595
596 fe_values = std::make_unique<FEValues<dim, spacedim>>(
597 mapping,
598 interpolation_of_values_is_needed ?
599 fe :
600 static_cast<const FiniteElement<dim, spacedim> &>(fe_nothing),
601 quadrature,
602 update_quadrature_points | update_values);
603 }
604
605 if (interpolation_of_values_is_needed)
606 fe_values->reinit(cell_dofs);
607 else
608 fe_values->reinit(cell_tria);
609 }
610
611 boost::container::small_vector<Point<spacedim>, 200> points;
612
613 // Step 2b) read of quadrature points in the relative displacement case
614 // note: we also take this path for non-active or artificial cells so that
615 // these cells are filled with some useful data
616 if (vector_describes_relative_displacement ||
617 (is_non_artificial_cell == false))
618 {
619 if (mapping_q != nullptr &&
620 this->get_degree() == mapping_q->get_degree())
621 {
622 mapping_q->compute_mapping_support_points(cell_tria, points);
623 }
624 else
625 {
626 const auto &quadrature_points =
627 fe_values_all.get()->get_quadrature_points();
628 points.assign(quadrature_points.begin(), quadrature_points.end());
629 }
630
631 // for non-active or artificial cells we are done here and return
632 // the absolute positions, since the provided vector cannot contain
633 // any useful information for these cells
634 if (is_non_artificial_cell == false)
635 return std::vector<Point<spacedim>>(points.begin(), points.end());
636 }
637 else
638 {
639 points.resize(
640 Utilities::pow<unsigned int>(this->get_degree() + 1, dim));
641 }
642
643 // Step 2c) read global vector and adjust points accordingly
644 if (interpolation_of_values_is_needed == false)
645 {
646 // case 1: FE_Q or FE_DGQ with same degree as this class has; this
647 // is the simple case since no interpolation is needed
648 std::vector<types::global_dof_index> dof_indices(
649 fe.n_dofs_per_cell());
650 cell_dofs->get_mg_dof_indices(dof_indices);
651
652 for (unsigned int i = 0; i < dof_indices.size(); ++i)
653 {
654 const auto id = fe.system_to_component_index(i);
655
656 if (is_fe_q)
657 {
658 // case 1a: FE_Q
659 if (vector_describes_relative_displacement)
660 points[id.second][id.first] +=
661 vectors_ghosted[cell_tria->level()](dof_indices[i]);
662 else
663 points[id.second][id.first] =
664 vectors_ghosted[cell_tria->level()](dof_indices[i]);
665 }
666 else
667 {
668 // case 1b: FE_DGQ
669 if (vector_describes_relative_displacement)
670 points[lexicographic_to_hierarchic_numbering[id.second]]
671 [id.first] +=
672 vectors_ghosted[cell_tria->level()](dof_indices[i]);
673 else
674 points[lexicographic_to_hierarchic_numbering[id.second]]
675 [id.first] =
676 vectors_ghosted[cell_tria->level()](dof_indices[i]);
677 }
678 }
679 }
680 else
681 {
682 // case 2: general case; interpolation is needed
683 // note: the following code could be optimized for tensor-product
684 // elements via application of sum factorization as is done on
685 // MatrixFree/FEEvaluation
686 auto &fe_values = fe_values_all.get();
687
688 std::vector<types::global_dof_index> dof_indices(
689 fe.n_dofs_per_cell());
690 cell_dofs->get_mg_dof_indices(dof_indices);
691
692 std::vector<typename VectorType::value_type> dof_values(
693 fe.n_dofs_per_cell());
694
695 for (unsigned int i = 0; i < fe.n_dofs_per_cell(); ++i)
696 dof_values[i] = vectors_ghosted[cell_tria->level()](dof_indices[i]);
697
698 for (unsigned int c = 0; c < spacedim; ++c)
699 for (unsigned int i = 0; i < fe.n_dofs_per_cell(); ++i)
700 for (unsigned int q = 0; q < fe_values->n_quadrature_points; ++q)
701 if (vector_describes_relative_displacement == false && i == 0)
702 points[q][c] =
703 dof_values[i] * fe_values->shape_value_component(i, q, c);
704 else
705 points[q][c] +=
706 dof_values[i] * fe_values->shape_value_component(i, q, c);
707 }
708
709 return std::vector<Point<spacedim>>(points.begin(), points.end());
710 });
711
712 uses_level_info = true;
713}
714
715
716
717template <int dim, int spacedim>
718std::size_t
720{
721 if (support_point_cache.get() != nullptr)
722 return sizeof(*this) +
723 MemoryConsumption::memory_consumption(*support_point_cache);
724 else
725 return sizeof(*this);
726}
727
728
729
730template <int dim, int spacedim>
731void
734 boost::container::small_vector<Point<spacedim>, 200> &points) const
735{
736 Assert(support_point_cache.get() != nullptr,
737 ExcMessage("Must call MappingQCache::initialize() before "
738 "using it or after mesh has changed!"));
739
740 Assert(uses_level_info || cell->is_active(), ExcInternalError());
741
742 AssertIndexRange(cell->level(), support_point_cache->size());
743 AssertIndexRange(cell->index(), (*support_point_cache)[cell->level()].size());
744 const auto &cached_points =
745 (*support_point_cache)[cell->level()][cell->index()];
746 points.assign(cached_points.begin(), cached_points.end());
747}
748
749
750
751template <int dim, int spacedim>
752boost::container::small_vector<Point<spacedim>,
753#ifndef _MSC_VER
754 ReferenceCells::max_n_vertices<dim>()
755#else
757#endif
758 >
760 const typename Triangulation<dim, spacedim>::cell_iterator &cell) const
761{
762 Assert(support_point_cache.get() != nullptr,
763 ExcMessage("Must call MappingQCache::initialize() before "
764 "using it or after mesh has changed!"));
765
766 Assert(uses_level_info || cell->is_active(), ExcInternalError());
767
768 AssertIndexRange(cell->level(), support_point_cache->size());
769 AssertIndexRange(cell->index(), (*support_point_cache)[cell->level()].size());
770 const auto ptr = (*support_point_cache)[cell->level()][cell->index()].begin();
771 return boost::container::small_vector<Point<spacedim>,
772#ifndef _MSC_VER
773 ReferenceCells::max_n_vertices<dim>()
774#else
776#endif
777 >(ptr, ptr + cell->n_vertices());
778}
779
780
781
782//--------------------------- Explicit instantiations -----------------------
783#include "fe/mapping_q_cache.inst"
784
785
const hp::FECollection< dim, spacedim > & get_fe_collection() const
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
const IndexSet & locally_owned_mg_dofs(const unsigned int level) const
const Triangulation< dim, spacedim > & get_triangulation() const
const IndexSet & locally_owned_dofs() const
MPI_Comm get_mpi_communicator() const
Definition fe_q.h:552
const unsigned int degree
Definition fe_data.h:450
unsigned int n_dofs_per_cell() const
virtual const FiniteElement< dim, spacedim > & base_element(const unsigned int index) const
std::pair< unsigned int, unsigned int > system_to_component_index(const unsigned int index) const
unsigned int element_multiplicity(const unsigned int index) const
unsigned int n_base_elements() const
const unsigned int n_components
Definition function.h:162
virtual RangeNumberType value(const Point< dim > &p, const unsigned int component=0) const
void import_elements(const ::Vector< Number > &vec, VectorOperation::values operation, const std::shared_ptr< const Utilities::MPI::CommunicationPatternBase > &communication_pattern={})
virtual void reinit(const size_type size, const bool omit_zeroing_entries=false)
void import_elements(const Vector< Number, MemorySpace2 > &src, VectorOperation::values operation)
void reinit(const size_type size, const bool omit_zeroing_entries=false)
unsigned int max_level() const
unsigned int min_level() const
std::size_t memory_consumption() const
virtual bool preserves_vertex_locations() const override
virtual boost::container::small_vector< Point< spacedim >, ReferenceCells::max_n_vertices< dim >() > get_vertices(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const override
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() const override
void initialize(const Mapping< dim, spacedim > &mapping, const Triangulation< dim, spacedim > &triangulation)
virtual void compute_mapping_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, boost::container::small_vector< Point< spacedim >, 200 > &a) const override
friend class MappingQCache
Definition mapping_q.h:664
virtual void compute_mapping_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, boost::container::small_vector< Point< spacedim >, 200 > &points) const
Abstract base class for mapping classes.
Definition mapping.h:318
static unsigned int n_threads()
Definition point.h:111
A class that provides a separate storage location on each thread that accesses the object.
cell_iterator begin(const unsigned int level=0) const
unsigned int n_levels() const
cell_iterator end() const
unsigned int n_raw_cells(const unsigned int level) const
virtual unsigned int n_global_levels() const
Signals signals
Definition tria.h:2588
unsigned int size() const
Definition collection.h:314
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
@ update_quadrature_points
Transformed quadrature points.
IndexSet extract_locally_relevant_dofs(const DoFHandler< dim, spacedim > &dof_handler)
IndexSet extract_locally_relevant_level_dofs(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int level)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1670
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
boost::signals2::signal< void()> any_change
Definition tria.h:2460