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_fe.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) 2015 - 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
21#include <deal.II/base/table.h>
23
24#include <deal.II/fe/fe_poly.h>
28
31#include <deal.II/grid/tria.h>
33
35
36#include <boost/container/small_vector.hpp>
37
38#include <algorithm>
39#include <array>
40#include <cmath>
41#include <memory>
42#include <numeric>
43
44
46
47
48template <int dim, int spacedim>
51 : fe(fe)
52 , polynomial_degree(fe.tensor_degree())
53 , n_shape_functions(fe.n_dofs_per_cell())
54{}
55
56
57
58template <int dim, int spacedim>
59std::size_t
74
75
76
77template <int dim, int spacedim>
78void
80 const Quadrature<dim> &q)
81{
82 // store the flags in the internal data object so we can access them
83 // in fill_fe_*_values()
84 this->update_each = update_flags;
85
86 const unsigned int n_q_points = q.size();
87
88 if (this->update_each & update_covariant_transformation)
89 covariant.resize(n_q_points);
90
91 if (this->update_each & update_contravariant_transformation)
92 contravariant.resize(n_q_points);
93
94 if (this->update_each & update_volume_elements)
95 volume_elements.resize(n_q_points);
96
97 // see if we need the (transformation) shape function values
98 // and/or gradients and resize the necessary arrays
99 if (this->update_each & update_quadrature_points)
100 shape_values.resize(n_shape_functions * n_q_points);
101
102 if (this->update_each &
110 shape_derivatives.resize(n_shape_functions * n_q_points);
111
112 if (this->update_each &
114 shape_second_derivatives.resize(n_shape_functions * n_q_points);
115
116 if (this->update_each & (update_jacobian_2nd_derivatives |
118 shape_third_derivatives.resize(n_shape_functions * n_q_points);
119
120 if (this->update_each & (update_jacobian_3rd_derivatives |
122 shape_fourth_derivatives.resize(n_shape_functions * n_q_points);
123
124 // now also fill the various fields with their correct values
125 compute_shape_function_values(q.get_points());
126
127 // copy (projected) quadrature weights
128 quadrature_weights = q.get_weights();
129}
130
131
132
133template <int dim, int spacedim>
134void
136 const UpdateFlags update_flags,
137 const Quadrature<dim> &q,
138 const unsigned int n_original_q_points)
139{
140 reinit(update_flags, q);
141
142 if (this->update_each &
145 {
146 aux.resize(dim - 1,
147 std::vector<Tensor<1, spacedim>>(n_original_q_points));
148
149 // Compute tangentials to the faces of the unit cell. In 1d, a
150 // face is a point, so there is no tangent space.
151 if constexpr (dim > 1)
152 {
153 const auto reference_cell = this->fe.reference_cell();
154 const auto n_faces = reference_cell.n_faces();
155
156 for (unsigned int i = 0; i < n_faces; ++i)
157 {
158 unit_tangentials[i].resize(n_original_q_points);
159 std::fill(unit_tangentials[i].begin(),
160 unit_tangentials[i].end(),
161 reference_cell.face_tangent_vector(i, 0));
162 if constexpr (dim > 2)
163 {
164 unit_tangentials[n_faces + i].resize(n_original_q_points);
165 std::fill(unit_tangentials[n_faces + i].begin(),
166 unit_tangentials[n_faces + i].end(),
167 reference_cell.face_tangent_vector(i, 1));
168 }
169 }
170 }
171 }
172}
173
174
175
176template <int dim, int spacedim>
177void
179 const std::vector<Point<dim>> &unit_points)
180{
181 const auto fe_poly = dynamic_cast<const FE_Poly<dim, spacedim> *>(&this->fe);
182
183 Assert(fe_poly != nullptr, ExcNotImplemented());
184
185 const auto &tensor_pols = fe_poly->get_poly_space();
186
187 const unsigned int n_shape_functions = fe.n_dofs_per_cell();
188 const unsigned int n_points = unit_points.size();
189
190 std::vector<double> values;
191 std::vector<Tensor<1, dim>> grads;
192 if (shape_values.size() != 0)
193 {
194 Assert(shape_values.size() == n_shape_functions * n_points,
196 values.resize(n_shape_functions);
197 }
198 if (shape_derivatives.size() != 0)
199 {
200 Assert(shape_derivatives.size() == n_shape_functions * n_points,
202 grads.resize(n_shape_functions);
203 }
204
205 std::vector<Tensor<2, dim>> grad2;
206 if (shape_second_derivatives.size() != 0)
207 {
208 Assert(shape_second_derivatives.size() == n_shape_functions * n_points,
210 grad2.resize(n_shape_functions);
211 }
212
213 std::vector<Tensor<3, dim>> grad3;
214 if (shape_third_derivatives.size() != 0)
215 {
216 Assert(shape_third_derivatives.size() == n_shape_functions * n_points,
218 grad3.resize(n_shape_functions);
219 }
220
221 std::vector<Tensor<4, dim>> grad4;
222 if (shape_fourth_derivatives.size() != 0)
223 {
224 Assert(shape_fourth_derivatives.size() == n_shape_functions * n_points,
226 grad4.resize(n_shape_functions);
227 }
228
229
230 if (shape_values.size() != 0 || shape_derivatives.size() != 0 ||
231 shape_second_derivatives.size() != 0 ||
232 shape_third_derivatives.size() != 0 ||
233 shape_fourth_derivatives.size() != 0)
234 for (unsigned int point = 0; point < n_points; ++point)
235 {
236 tensor_pols.evaluate(
237 unit_points[point], values, grads, grad2, grad3, grad4);
238
239 if (shape_values.size() != 0)
240 for (unsigned int i = 0; i < n_shape_functions; ++i)
241 shape(point, i) = values[i];
242
243 if (shape_derivatives.size() != 0)
244 for (unsigned int i = 0; i < n_shape_functions; ++i)
245 derivative(point, i) = grads[i];
246
247 if (shape_second_derivatives.size() != 0)
248 for (unsigned int i = 0; i < n_shape_functions; ++i)
249 second_derivative(point, i) = grad2[i];
250
251 if (shape_third_derivatives.size() != 0)
252 for (unsigned int i = 0; i < n_shape_functions; ++i)
253 third_derivative(point, i) = grad3[i];
254
255 if (shape_fourth_derivatives.size() != 0)
256 for (unsigned int i = 0; i < n_shape_functions; ++i)
257 fourth_derivative(point, i) = grad4[i];
258 }
259}
260
261
262namespace internal
263{
264 namespace MappingFEImplementation
265 {
266 namespace
267 {
274 template <int dim, int spacedim>
275 void
276 maybe_compute_q_points(
277 const typename QProjector<dim>::DataSetDescriptor data_set,
278 const typename ::MappingFE<dim, spacedim>::InternalData &data,
279 std::vector<Point<spacedim>> &quadrature_points,
280 const unsigned int n_q_points)
281 {
282 const UpdateFlags update_flags = data.update_each;
283
284 if (update_flags & update_quadrature_points)
285 for (unsigned int point = 0; point < n_q_points; ++point)
286 {
287 const double *shape = &data.shape(point + data_set, 0);
288 Point<spacedim> result =
289 (shape[0] * data.mapping_support_points[0]);
290 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
291 for (unsigned int i = 0; i < spacedim; ++i)
292 result[i] += shape[k] * data.mapping_support_points[k][i];
293 quadrature_points[point] = result;
294 }
295 }
296
297
298
307 template <int dim, int spacedim>
308 void
309 maybe_update_Jacobians(
310 const CellSimilarity::Similarity cell_similarity,
311 const typename ::QProjector<dim>::DataSetDescriptor data_set,
312 const typename ::MappingFE<dim, spacedim>::InternalData &data,
313 const unsigned int n_q_points)
314 {
315 const UpdateFlags update_flags = data.update_each;
316
317 if (update_flags & update_contravariant_transformation)
318 // if the current cell is just a
319 // translation of the previous one, no
320 // need to recompute jacobians...
321 if (cell_similarity != CellSimilarity::translation)
322 {
323 std::fill(data.contravariant.begin(),
324 data.contravariant.end(),
326
327 Assert(data.n_shape_functions > 0, ExcInternalError());
328
329 for (unsigned int point = 0; point < n_q_points; ++point)
330 {
331 double result[spacedim][dim];
332
333 // peel away part of sum to avoid zeroing the
334 // entries and adding for the first time
335 for (unsigned int i = 0; i < spacedim; ++i)
336 for (unsigned int j = 0; j < dim; ++j)
337 result[i][j] = data.derivative(point + data_set, 0)[j] *
338 data.mapping_support_points[0][i];
339 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
340 for (unsigned int i = 0; i < spacedim; ++i)
341 for (unsigned int j = 0; j < dim; ++j)
342 result[i][j] +=
343 data.derivative(point + data_set, k)[j] *
344 data.mapping_support_points[k][i];
345
346 // write result into contravariant data. for
347 // j=dim in the case dim<spacedim, there will
348 // never be any nonzero data that arrives in
349 // here, so it is ok anyway because it was
350 // initialized to zero at the initialization
351 for (unsigned int i = 0; i < spacedim; ++i)
352 for (unsigned int j = 0; j < dim; ++j)
353 data.contravariant[point][i][j] = result[i][j];
354 }
355 }
356
357 if (update_flags & update_covariant_transformation)
358 if (cell_similarity != CellSimilarity::translation)
359 {
360 for (unsigned int point = 0; point < n_q_points; ++point)
361 {
362 data.covariant[point] =
363 (data.contravariant[point]).covariant_form();
364 }
365 }
366
367 if (update_flags & update_volume_elements)
368 if (cell_similarity != CellSimilarity::translation)
369 {
370 for (unsigned int point = 0; point < n_q_points; ++point)
371 data.volume_elements[point] =
372 data.contravariant[point].determinant();
373 }
374 }
375
382 template <int dim, int spacedim>
383 void
384 maybe_update_jacobian_grads(
385 const CellSimilarity::Similarity cell_similarity,
386 const typename QProjector<dim>::DataSetDescriptor data_set,
387 const typename ::MappingFE<dim, spacedim>::InternalData &data,
388 std::vector<DerivativeForm<2, dim, spacedim>> &jacobian_grads,
389 const unsigned int n_q_points)
390 {
391 const UpdateFlags update_flags = data.update_each;
392 if (update_flags & update_jacobian_grads)
393 {
394 AssertIndexRange(n_q_points, jacobian_grads.size() + 1);
395
396 if (cell_similarity != CellSimilarity::translation)
397 for (unsigned int point = 0; point < n_q_points; ++point)
398 {
399 const Tensor<2, dim> *second =
400 &data.second_derivative(point + data_set, 0);
401 double result[spacedim][dim][dim];
402 for (unsigned int i = 0; i < spacedim; ++i)
403 for (unsigned int j = 0; j < dim; ++j)
404 for (unsigned int l = 0; l < dim; ++l)
405 result[i][j][l] =
406 (second[0][j][l] * data.mapping_support_points[0][i]);
407 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
408 for (unsigned int i = 0; i < spacedim; ++i)
409 for (unsigned int j = 0; j < dim; ++j)
410 for (unsigned int l = 0; l < dim; ++l)
411 result[i][j][l] +=
412 (second[k][j][l] *
413 data.mapping_support_points[k][i]);
414
415 for (unsigned int i = 0; i < spacedim; ++i)
416 for (unsigned int j = 0; j < dim; ++j)
417 for (unsigned int l = 0; l < dim; ++l)
418 jacobian_grads[point][i][j][l] = result[i][j][l];
419 }
420 }
421 }
422
429 template <int dim, int spacedim>
430 void
431 maybe_update_jacobian_pushed_forward_grads(
432 const CellSimilarity::Similarity cell_similarity,
433 const typename QProjector<dim>::DataSetDescriptor data_set,
434 const typename ::MappingFE<dim, spacedim>::InternalData &data,
435 std::vector<Tensor<3, spacedim>> &jacobian_pushed_forward_grads,
436 const unsigned int n_q_points)
437 {
438 const UpdateFlags update_flags = data.update_each;
439 if (update_flags & update_jacobian_pushed_forward_grads)
440 {
441 AssertIndexRange(n_q_points,
442 jacobian_pushed_forward_grads.size() + 1);
443
444 if (cell_similarity != CellSimilarity::translation)
445 {
446 double tmp[spacedim][spacedim][spacedim];
447 for (unsigned int point = 0; point < n_q_points; ++point)
448 {
449 const Tensor<2, dim> *second =
450 &data.second_derivative(point + data_set, 0);
451 double result[spacedim][dim][dim];
452 for (unsigned int i = 0; i < spacedim; ++i)
453 for (unsigned int j = 0; j < dim; ++j)
454 for (unsigned int l = 0; l < dim; ++l)
455 result[i][j][l] = (second[0][j][l] *
456 data.mapping_support_points[0][i]);
457 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
458 for (unsigned int i = 0; i < spacedim; ++i)
459 for (unsigned int j = 0; j < dim; ++j)
460 for (unsigned int l = 0; l < dim; ++l)
461 result[i][j][l] +=
462 (second[k][j][l] *
463 data.mapping_support_points[k][i]);
464
465 // first push forward the j-components
466 for (unsigned int i = 0; i < spacedim; ++i)
467 for (unsigned int j = 0; j < spacedim; ++j)
468 for (unsigned int l = 0; l < dim; ++l)
469 {
470 tmp[i][j][l] =
471 result[i][0][l] * data.covariant[point][j][0];
472 for (unsigned int jr = 1; jr < dim; ++jr)
473 {
474 tmp[i][j][l] += result[i][jr][l] *
475 data.covariant[point][j][jr];
476 }
477 }
478
479 // now, pushing forward the l-components
480 for (unsigned int i = 0; i < spacedim; ++i)
481 for (unsigned int j = 0; j < spacedim; ++j)
482 for (unsigned int l = 0; l < spacedim; ++l)
483 {
484 jacobian_pushed_forward_grads[point][i][j][l] =
485 tmp[i][j][0] * data.covariant[point][l][0];
486 for (unsigned int lr = 1; lr < dim; ++lr)
487 {
488 jacobian_pushed_forward_grads[point][i][j][l] +=
489 tmp[i][j][lr] * data.covariant[point][l][lr];
490 }
491 }
492 }
493 }
494 }
495 }
496
503 template <int dim, int spacedim>
504 void
505 maybe_update_jacobian_2nd_derivatives(
506 const CellSimilarity::Similarity cell_similarity,
507 const typename QProjector<dim>::DataSetDescriptor data_set,
508 const typename ::MappingFE<dim, spacedim>::InternalData &data,
509 std::vector<DerivativeForm<3, dim, spacedim>> &jacobian_2nd_derivatives,
510 const unsigned int n_q_points)
511 {
512 const UpdateFlags update_flags = data.update_each;
513 if (update_flags & update_jacobian_2nd_derivatives)
514 {
515 AssertIndexRange(n_q_points, jacobian_2nd_derivatives.size() + 1);
516
517 if (cell_similarity != CellSimilarity::translation)
518 {
519 for (unsigned int point = 0; point < n_q_points; ++point)
520 {
521 const Tensor<3, dim> *third =
522 &data.third_derivative(point + data_set, 0);
523 double result[spacedim][dim][dim][dim];
524 for (unsigned int i = 0; i < spacedim; ++i)
525 for (unsigned int j = 0; j < dim; ++j)
526 for (unsigned int l = 0; l < dim; ++l)
527 for (unsigned int m = 0; m < dim; ++m)
528 result[i][j][l][m] =
529 (third[0][j][l][m] *
530 data.mapping_support_points[0][i]);
531 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
532 for (unsigned int i = 0; i < spacedim; ++i)
533 for (unsigned int j = 0; j < dim; ++j)
534 for (unsigned int l = 0; l < dim; ++l)
535 for (unsigned int m = 0; m < dim; ++m)
536 result[i][j][l][m] +=
537 (third[k][j][l][m] *
538 data.mapping_support_points[k][i]);
539
540 for (unsigned int i = 0; i < spacedim; ++i)
541 for (unsigned int j = 0; j < dim; ++j)
542 for (unsigned int l = 0; l < dim; ++l)
543 for (unsigned int m = 0; m < dim; ++m)
544 jacobian_2nd_derivatives[point][i][j][l][m] =
545 result[i][j][l][m];
546 }
547 }
548 }
549 }
550
558 template <int dim, int spacedim>
559 void
560 maybe_update_jacobian_pushed_forward_2nd_derivatives(
561 const CellSimilarity::Similarity cell_similarity,
562 const typename QProjector<dim>::DataSetDescriptor data_set,
563 const typename ::MappingFE<dim, spacedim>::InternalData &data,
564 std::vector<Tensor<4, spacedim>>
565 &jacobian_pushed_forward_2nd_derivatives,
566 const unsigned int n_q_points)
567 {
568 const UpdateFlags update_flags = data.update_each;
570 {
571 AssertIndexRange(n_q_points,
572 jacobian_pushed_forward_2nd_derivatives.size() +
573 1);
574
575 if (cell_similarity != CellSimilarity::translation)
576 {
577 double tmp[spacedim][spacedim][spacedim][spacedim];
578 for (unsigned int point = 0; point < n_q_points; ++point)
579 {
580 const Tensor<3, dim> *third =
581 &data.third_derivative(point + data_set, 0);
582 double result[spacedim][dim][dim][dim];
583 for (unsigned int i = 0; i < spacedim; ++i)
584 for (unsigned int j = 0; j < dim; ++j)
585 for (unsigned int l = 0; l < dim; ++l)
586 for (unsigned int m = 0; m < dim; ++m)
587 result[i][j][l][m] =
588 (third[0][j][l][m] *
589 data.mapping_support_points[0][i]);
590 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
591 for (unsigned int i = 0; i < spacedim; ++i)
592 for (unsigned int j = 0; j < dim; ++j)
593 for (unsigned int l = 0; l < dim; ++l)
594 for (unsigned int m = 0; m < dim; ++m)
595 result[i][j][l][m] +=
596 (third[k][j][l][m] *
597 data.mapping_support_points[k][i]);
598
599 // push forward the j-coordinate
600 for (unsigned int i = 0; i < spacedim; ++i)
601 for (unsigned int j = 0; j < spacedim; ++j)
602 for (unsigned int l = 0; l < dim; ++l)
603 for (unsigned int m = 0; m < dim; ++m)
604 {
605 jacobian_pushed_forward_2nd_derivatives
606 [point][i][j][l][m] =
607 result[i][0][l][m] *
608 data.covariant[point][j][0];
609 for (unsigned int jr = 1; jr < dim; ++jr)
610 jacobian_pushed_forward_2nd_derivatives[point]
611 [i][j][l]
612 [m] +=
613 result[i][jr][l][m] *
614 data.covariant[point][j][jr];
615 }
616
617 // push forward the l-coordinate
618 for (unsigned int i = 0; i < spacedim; ++i)
619 for (unsigned int j = 0; j < spacedim; ++j)
620 for (unsigned int l = 0; l < spacedim; ++l)
621 for (unsigned int m = 0; m < dim; ++m)
622 {
623 tmp[i][j][l][m] =
624 jacobian_pushed_forward_2nd_derivatives[point]
625 [i][j][0]
626 [m] *
627 data.covariant[point][l][0];
628 for (unsigned int lr = 1; lr < dim; ++lr)
629 tmp[i][j][l][m] +=
630 jacobian_pushed_forward_2nd_derivatives
631 [point][i][j][lr][m] *
632 data.covariant[point][l][lr];
633 }
634
635 // push forward the m-coordinate
636 for (unsigned int i = 0; i < spacedim; ++i)
637 for (unsigned int j = 0; j < spacedim; ++j)
638 for (unsigned int l = 0; l < spacedim; ++l)
639 for (unsigned int m = 0; m < spacedim; ++m)
640 {
641 jacobian_pushed_forward_2nd_derivatives
642 [point][i][j][l][m] =
643 tmp[i][j][l][0] * data.covariant[point][m][0];
644 for (unsigned int mr = 1; mr < dim; ++mr)
645 jacobian_pushed_forward_2nd_derivatives[point]
646 [i][j][l]
647 [m] +=
648 tmp[i][j][l][mr] *
649 data.covariant[point][m][mr];
650 }
651 }
652 }
653 }
654 }
655
662 template <int dim, int spacedim>
663 void
664 maybe_update_jacobian_3rd_derivatives(
665 const CellSimilarity::Similarity cell_similarity,
666 const typename QProjector<dim>::DataSetDescriptor data_set,
667 const typename ::MappingFE<dim, spacedim>::InternalData &data,
668 std::vector<DerivativeForm<4, dim, spacedim>> &jacobian_3rd_derivatives,
669 const unsigned int n_q_points)
670 {
671 const UpdateFlags update_flags = data.update_each;
672 if (update_flags & update_jacobian_3rd_derivatives)
673 {
674 AssertIndexRange(n_q_points, jacobian_3rd_derivatives.size() + 1);
675
676 if (cell_similarity != CellSimilarity::translation)
677 {
678 for (unsigned int point = 0; point < n_q_points; ++point)
679 {
680 const Tensor<4, dim> *fourth =
681 &data.fourth_derivative(point + data_set, 0);
682 double result[spacedim][dim][dim][dim][dim];
683 for (unsigned int i = 0; i < spacedim; ++i)
684 for (unsigned int j = 0; j < dim; ++j)
685 for (unsigned int l = 0; l < dim; ++l)
686 for (unsigned int m = 0; m < dim; ++m)
687 for (unsigned int n = 0; n < dim; ++n)
688 result[i][j][l][m][n] =
689 (fourth[0][j][l][m][n] *
690 data.mapping_support_points[0][i]);
691 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
692 for (unsigned int i = 0; i < spacedim; ++i)
693 for (unsigned int j = 0; j < dim; ++j)
694 for (unsigned int l = 0; l < dim; ++l)
695 for (unsigned int m = 0; m < dim; ++m)
696 for (unsigned int n = 0; n < dim; ++n)
697 result[i][j][l][m][n] +=
698 (fourth[k][j][l][m][n] *
699 data.mapping_support_points[k][i]);
700
701 for (unsigned int i = 0; i < spacedim; ++i)
702 for (unsigned int j = 0; j < dim; ++j)
703 for (unsigned int l = 0; l < dim; ++l)
704 for (unsigned int m = 0; m < dim; ++m)
705 for (unsigned int n = 0; n < dim; ++n)
706 jacobian_3rd_derivatives[point][i][j][l][m][n] =
707 result[i][j][l][m][n];
708 }
709 }
710 }
711 }
712
720 template <int dim, int spacedim>
721 void
722 maybe_update_jacobian_pushed_forward_3rd_derivatives(
723 const CellSimilarity::Similarity cell_similarity,
724 const typename QProjector<dim>::DataSetDescriptor data_set,
725 const typename ::MappingFE<dim, spacedim>::InternalData &data,
726 std::vector<Tensor<5, spacedim>>
727 &jacobian_pushed_forward_3rd_derivatives,
728 const unsigned int n_q_points)
729 {
730 const UpdateFlags update_flags = data.update_each;
732 {
733 AssertIndexRange(n_q_points,
734 jacobian_pushed_forward_3rd_derivatives.size() +
735 1);
736
737 if (cell_similarity != CellSimilarity::translation)
738 {
739 double tmp[spacedim][spacedim][spacedim][spacedim][spacedim];
740 for (unsigned int point = 0; point < n_q_points; ++point)
741 {
742 const Tensor<4, dim> *fourth =
743 &data.fourth_derivative(point + data_set, 0);
744 double result[spacedim][dim][dim][dim][dim];
745 for (unsigned int i = 0; i < spacedim; ++i)
746 for (unsigned int j = 0; j < dim; ++j)
747 for (unsigned int l = 0; l < dim; ++l)
748 for (unsigned int m = 0; m < dim; ++m)
749 for (unsigned int n = 0; n < dim; ++n)
750 result[i][j][l][m][n] =
751 (fourth[0][j][l][m][n] *
752 data.mapping_support_points[0][i]);
753 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
754 for (unsigned int i = 0; i < spacedim; ++i)
755 for (unsigned int j = 0; j < dim; ++j)
756 for (unsigned int l = 0; l < dim; ++l)
757 for (unsigned int m = 0; m < dim; ++m)
758 for (unsigned int n = 0; n < dim; ++n)
759 result[i][j][l][m][n] +=
760 (fourth[k][j][l][m][n] *
761 data.mapping_support_points[k][i]);
762
763 // push-forward the j-coordinate
764 for (unsigned int i = 0; i < spacedim; ++i)
765 for (unsigned int j = 0; j < spacedim; ++j)
766 for (unsigned int l = 0; l < dim; ++l)
767 for (unsigned int m = 0; m < dim; ++m)
768 for (unsigned int n = 0; n < dim; ++n)
769 {
770 tmp[i][j][l][m][n] =
771 result[i][0][l][m][n] *
772 data.covariant[point][j][0];
773 for (unsigned int jr = 1; jr < dim; ++jr)
774 tmp[i][j][l][m][n] +=
775 result[i][jr][l][m][n] *
776 data.covariant[point][j][jr];
777 }
778
779 // push-forward the l-coordinate
780 for (unsigned int i = 0; i < spacedim; ++i)
781 for (unsigned int j = 0; j < spacedim; ++j)
782 for (unsigned int l = 0; l < spacedim; ++l)
783 for (unsigned int m = 0; m < dim; ++m)
784 for (unsigned int n = 0; n < dim; ++n)
785 {
786 jacobian_pushed_forward_3rd_derivatives
787 [point][i][j][l][m][n] =
788 tmp[i][j][0][m][n] *
789 data.covariant[point][l][0];
790 for (unsigned int lr = 1; lr < dim; ++lr)
791 jacobian_pushed_forward_3rd_derivatives
792 [point][i][j][l][m][n] +=
793 tmp[i][j][lr][m][n] *
794 data.covariant[point][l][lr];
795 }
796
797 // push-forward the m-coordinate
798 for (unsigned int i = 0; i < spacedim; ++i)
799 for (unsigned int j = 0; j < spacedim; ++j)
800 for (unsigned int l = 0; l < spacedim; ++l)
801 for (unsigned int m = 0; m < spacedim; ++m)
802 for (unsigned int n = 0; n < dim; ++n)
803 {
804 tmp[i][j][l][m][n] =
805 jacobian_pushed_forward_3rd_derivatives
806 [point][i][j][l][0][n] *
807 data.covariant[point][m][0];
808 for (unsigned int mr = 1; mr < dim; ++mr)
809 tmp[i][j][l][m][n] +=
810 jacobian_pushed_forward_3rd_derivatives
811 [point][i][j][l][mr][n] *
812 data.covariant[point][m][mr];
813 }
814
815 // push-forward the n-coordinate
816 for (unsigned int i = 0; i < spacedim; ++i)
817 for (unsigned int j = 0; j < spacedim; ++j)
818 for (unsigned int l = 0; l < spacedim; ++l)
819 for (unsigned int m = 0; m < spacedim; ++m)
820 for (unsigned int n = 0; n < spacedim; ++n)
821 {
822 jacobian_pushed_forward_3rd_derivatives
823 [point][i][j][l][m][n] =
824 tmp[i][j][l][m][0] *
825 data.covariant[point][n][0];
826 for (unsigned int nr = 1; nr < dim; ++nr)
827 jacobian_pushed_forward_3rd_derivatives
828 [point][i][j][l][m][n] +=
829 tmp[i][j][l][m][nr] *
830 data.covariant[point][n][nr];
831 }
832 }
833 }
834 }
835 }
836 } // namespace
837 } // namespace MappingFEImplementation
838} // namespace internal
839
840
841
842template <int dim, int spacedim>
844 : fe(fe.clone())
845 , polynomial_degree(fe.tensor_degree())
846{
848 ExcMessage("It only makes sense to create polynomial mappings "
849 "with a polynomial degree greater or equal to one."));
850 Assert(fe.n_components() == 1, ExcNotImplemented());
851
852 Assert(fe.has_support_points(), ExcNotImplemented());
853
854 const auto &mapping_support_points = fe.get_unit_support_points();
855
856 const auto reference_cell = fe.reference_cell();
857
858 const unsigned int n_points = mapping_support_points.size();
859 const unsigned int n_shape_functions = reference_cell.n_vertices();
860
862 Table<2, double>(n_points, n_shape_functions);
863
864 for (unsigned int point = 0; point < n_points; ++point)
865 for (unsigned int i = 0; i < n_shape_functions; ++i)
867 reference_cell.d_linear_shape_function(mapping_support_points[point],
868 i);
869}
870
871
872
873template <int dim, int spacedim>
875 : fe(mapping.fe->clone())
876 , polynomial_degree(mapping.polynomial_degree)
877 , mapping_support_point_weights(mapping.mapping_support_point_weights)
878{}
879
880
881
882template <int dim, int spacedim>
883std::unique_ptr<Mapping<dim, spacedim>>
885{
886 return std::make_unique<MappingFE<dim, spacedim>>(*this);
887}
888
889
890
891template <int dim, int spacedim>
892unsigned int
894{
895 return polynomial_degree;
896}
897
898
899
900template <int dim, int spacedim>
904 const Point<dim> &p) const
905{
906 const auto support_points = this->compute_mapping_support_points(cell);
907
908 Point<spacedim> mapped_point;
909
910 for (unsigned int i = 0; i < this->fe->n_dofs_per_cell(); ++i)
911 mapped_point += support_points[i] * this->fe->shape_value(i, p);
912
913 return mapped_point;
914}
915
916
917
918template <int dim, int spacedim>
922 const Point<spacedim> &p) const
923{
924 const auto support_points = this->compute_mapping_support_points(cell);
925
926 const double eps = 1.e-12 * cell->diameter();
927 const unsigned int loop_limit = 10;
928
929 Point<dim> p_unit;
930
931 unsigned int loop = 0;
932
933 // This loop solves the following problem:
934 // grad_F^T residual + (grad_F^T grad_F + grad_F^T hess_F^T dp) dp = 0
935 // where the term
936 // (grad_F^T hess_F dp) is approximated by (-hess_F * residual)
937 // This is basically a second order approximation of Newton method, where the
938 // Jacobian is corrected with a higher order term coming from the hessian.
939 do
940 {
941 Point<spacedim> mapped_point;
942
943 // Transpose of the gradient map
946
947 for (unsigned int i = 0; i < this->fe->n_dofs_per_cell(); ++i)
948 {
949 mapped_point += support_points[i] * this->fe->shape_value(i, p_unit);
950 const auto grad_F_i = this->fe->shape_grad(i, p_unit);
951 const auto hessian_F_i = this->fe->shape_grad_grad(i, p_unit);
952 for (unsigned int j = 0; j < dim; ++j)
953 {
954 grad_FT[j] += grad_F_i[j] * support_points[i];
955 for (unsigned int l = 0; l < dim; ++l)
956 hess_FT[j][l] += hessian_F_i[j][l] * support_points[i];
957 }
958 }
959
960 // Residual
961 const auto residual = p - mapped_point;
962 // Project the residual on the reference coordinate system
963 // to compute the error, and to filter components orthogonal to the
964 // manifold, and compute a 2nd order correction of the metric tensor
965 const auto grad_FT_residual = apply_transformation(grad_FT, residual);
966
967 // Do not invert nor compute the metric if not necessary.
968 if (grad_FT_residual.norm() <= eps)
969 break;
970
971 // Now compute the (corrected) metric tensor
972 Tensor<2, dim> corrected_metric_tensor;
973 for (unsigned int j = 0; j < dim; ++j)
974 for (unsigned int l = 0; l < dim; ++l)
975 corrected_metric_tensor[j][l] =
976 -grad_FT[j] * grad_FT[l] + hess_FT[j][l] * residual;
977
978 // And compute the update
979 const auto g_inverse = invert(corrected_metric_tensor);
980 p_unit -= Point<dim>(g_inverse * grad_FT_residual);
981
982 ++loop;
983 }
984 while (loop < loop_limit);
985
986 // Here we check that in the last execution of while the first
987 // condition was already wrong, meaning the residual was below
988 // eps. Only if the first condition failed, loop will have been
989 // increased and tested, and thus have reached the limit.
990 AssertThrow(loop < loop_limit,
992
993 return p_unit;
994}
995
996
997
998template <int dim, int spacedim>
1001{
1002 // add flags if the respective quantities are necessary to compute
1003 // what we need. note that some flags appear in both the conditions
1004 // and in subsequent set operations. this leads to some circular
1005 // logic. the only way to treat this is to iterate. since there are
1006 // 5 if-clauses in the loop, it will take at most 5 iterations to
1007 // converge. do them:
1008 UpdateFlags out = in;
1009 for (unsigned int i = 0; i < 5; ++i)
1010 {
1011 // The following is a little incorrect:
1012 // If not applied on a face,
1013 // update_boundary_forms does not
1014 // make sense. On the other hand,
1015 // it is necessary on a
1016 // face. Currently,
1017 // update_boundary_forms is simply
1018 // ignored for the interior of a
1019 // cell.
1021 out |= update_boundary_forms;
1022
1027
1028 if (out &
1033
1034 // The contravariant transformation is used in the Piola
1035 // transformation, which requires the determinant of the Jacobi
1036 // matrix of the transformation. Because we have no way of
1037 // knowing here whether the finite element wants to use the
1038 // contravariant or the Piola transforms, we add the JxW values
1039 // to the list of flags to be updated for each cell.
1042
1043 // the same is true when computing normal vectors: they require
1044 // the determinant of the Jacobian
1045 if (out & update_normal_vectors)
1047 }
1048
1049 return out;
1050}
1051
1052
1053
1054template <int dim, int spacedim>
1055std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1057 const Quadrature<dim> &q) const
1058{
1059 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1060 std::make_unique<InternalData>(*this->fe);
1061 data_ptr->reinit(this->requires_update_flags(update_flags), q);
1062 return data_ptr;
1063}
1064
1065
1066
1067template <int dim, int spacedim>
1068std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1070 const UpdateFlags update_flags,
1071 const hp::QCollection<dim - 1> &quadrature) const
1072{
1073 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1074 std::make_unique<InternalData>(*this->fe);
1075 auto &data = dynamic_cast<InternalData &>(*data_ptr);
1076 data.initialize_face(this->requires_update_flags(update_flags),
1078 this->fe->reference_cell(), quadrature),
1079 quadrature.max_n_quadrature_points());
1080
1081 return data_ptr;
1082}
1083
1084
1085
1086template <int dim, int spacedim>
1087std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1089 const UpdateFlags update_flags,
1090 const Quadrature<dim - 1> &quadrature) const
1091{
1092 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1093 std::make_unique<InternalData>(*this->fe);
1094 auto &data = dynamic_cast<InternalData &>(*data_ptr);
1095 data.initialize_face(this->requires_update_flags(update_flags),
1097 this->fe->reference_cell(), quadrature),
1098 quadrature.size());
1099
1100 return data_ptr;
1101}
1102
1103
1104
1105template <int dim, int spacedim>
1109 const CellSimilarity::Similarity cell_similarity,
1110 const Quadrature<dim> &quadrature,
1111 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1113 &output_data) const
1114{
1115 // ensure that the following static_cast is really correct:
1116 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
1118 const InternalData &data = static_cast<const InternalData &>(internal_data);
1119
1120 const unsigned int n_q_points = quadrature.size();
1121
1122 // recompute the support points of the transformation of this
1123 // cell. we tried to be clever here in an earlier version of the
1124 // library by checking whether the cell is the same as the one we
1125 // had visited last, but it turns out to be difficult to determine
1126 // that because a cell for the purposes of a mapping is
1127 // characterized not just by its (triangulation, level, index)
1128 // triple, but also by the locations of its vertices, the manifold
1129 // object attached to the cell and all of its bounding faces/edges,
1130 // etc. to reliably test that the "cell" we are on is, therefore,
1131 // not easily done
1132 const auto support_points = this->compute_mapping_support_points(cell);
1133 data.mapping_support_points.assign(support_points.begin(),
1134 support_points.end());
1135
1136 // if the order of the mapping is greater than 1, then do not reuse any cell
1137 // similarity information. This is necessary because the cell similarity
1138 // value is computed with just cell vertices and does not take into account
1139 // cell curvature.
1140 const CellSimilarity::Similarity computed_cell_similarity =
1141 (polynomial_degree == 1 ? cell_similarity : CellSimilarity::none);
1142
1143 internal::MappingFEImplementation::maybe_compute_q_points<dim, spacedim>(
1145 data,
1146 output_data.quadrature_points,
1147 n_q_points);
1148
1149 internal::MappingFEImplementation::maybe_update_Jacobians<dim, spacedim>(
1150 computed_cell_similarity,
1152 data,
1153 n_q_points);
1154
1155 internal::MappingFEImplementation::maybe_update_jacobian_grads<dim, spacedim>(
1156 computed_cell_similarity,
1158 data,
1159 output_data.jacobian_grads,
1160 n_q_points);
1161
1162 internal::MappingFEImplementation::maybe_update_jacobian_pushed_forward_grads<
1163 dim,
1164 spacedim>(computed_cell_similarity,
1166 data,
1168 n_q_points);
1169
1170 internal::MappingFEImplementation::maybe_update_jacobian_2nd_derivatives<
1171 dim,
1172 spacedim>(computed_cell_similarity,
1174 data,
1175 output_data.jacobian_2nd_derivatives,
1176 n_q_points);
1177
1178 internal::MappingFEImplementation::
1179 maybe_update_jacobian_pushed_forward_2nd_derivatives<dim, spacedim>(
1180 computed_cell_similarity,
1182 data,
1184 n_q_points);
1185
1186 internal::MappingFEImplementation::maybe_update_jacobian_3rd_derivatives<
1187 dim,
1188 spacedim>(computed_cell_similarity,
1190 data,
1191 output_data.jacobian_3rd_derivatives,
1192 n_q_points);
1193
1194 internal::MappingFEImplementation::
1195 maybe_update_jacobian_pushed_forward_3rd_derivatives<dim, spacedim>(
1196 computed_cell_similarity,
1198 data,
1200 n_q_points);
1201
1202 const UpdateFlags update_flags = data.update_each;
1203 const std::vector<double> &weights = quadrature.get_weights();
1204
1205 // Multiply quadrature weights by absolute value of Jacobian determinants or
1206 // the area element g=sqrt(DX^t DX) in case of codim > 0
1207
1208 if (update_flags & (update_normal_vectors | update_JxW_values))
1209 {
1210 AssertDimension(output_data.JxW_values.size(), n_q_points);
1211
1212 Assert(!(update_flags & update_normal_vectors) ||
1213 (output_data.normal_vectors.size() == n_q_points),
1214 ExcDimensionMismatch(output_data.normal_vectors.size(),
1215 n_q_points));
1216
1217
1218 if (computed_cell_similarity != CellSimilarity::translation)
1219 for (unsigned int point = 0; point < n_q_points; ++point)
1220 {
1221 if (dim == spacedim)
1222 {
1223 const double det = data.contravariant[point].determinant();
1224
1225 // check for distorted cells.
1226
1227 // TODO: this allows for anisotropies of up to 1e6 in 3d and
1228 // 1e12 in 2d. might want to find a finer
1229 // (dimension-independent) criterion
1230 Assert(det >
1231 1e-12 * Utilities::fixed_power<dim>(
1232 cell->diameter() / std::sqrt(double(dim))),
1234 cell->center(), det, point)));
1235
1236 output_data.JxW_values[point] = weights[point] * det;
1237 }
1238 // if dim==spacedim, then there is no cell normal to
1239 // compute. since this is for FEValues (and not FEFaceValues),
1240 // there are also no face normals to compute
1241 else // codim>0 case
1242 {
1243 Tensor<1, spacedim> DX_t[dim];
1244 for (unsigned int i = 0; i < spacedim; ++i)
1245 for (unsigned int j = 0; j < dim; ++j)
1246 DX_t[j][i] = data.contravariant[point][i][j];
1247
1248 Tensor<2, dim> G; // First fundamental form
1249 for (unsigned int i = 0; i < dim; ++i)
1250 for (unsigned int j = 0; j < dim; ++j)
1251 G[i][j] = DX_t[i] * DX_t[j];
1252
1253 output_data.JxW_values[point] =
1254 std::sqrt(determinant(G)) * weights[point];
1255
1256 if (computed_cell_similarity ==
1258 {
1259 // we only need to flip the normal
1260 if (update_flags & update_normal_vectors)
1261 output_data.normal_vectors[point] *= -1.;
1262 }
1263 else
1264 {
1265 if (update_flags & update_normal_vectors)
1266 {
1267 Assert(spacedim == dim + 1,
1268 ExcMessage(
1269 "There is no (unique) cell normal for " +
1271 "-dimensional cells in " +
1272 Utilities::int_to_string(spacedim) +
1273 "-dimensional space. This only works if the "
1274 "space dimension is one greater than the "
1275 "dimensionality of the mesh cells."));
1276
1277 if (dim == 1)
1278 output_data.normal_vectors[point] =
1279 cross_product_2d(-DX_t[0]);
1280 else // dim == 2
1281 output_data.normal_vectors[point] =
1282 cross_product_3d(DX_t[0], DX_t[1]);
1283
1284 output_data.normal_vectors[point] /=
1285 output_data.normal_vectors[point].norm();
1286
1287 if (cell->direction_flag() == false)
1288 output_data.normal_vectors[point] *= -1.;
1289 }
1290 }
1291 } // codim>0 case
1292 }
1293 }
1294
1295
1296
1297 // copy values from InternalData to vector given by reference
1298 if (update_flags & update_jacobians)
1299 {
1300 AssertDimension(output_data.jacobians.size(), n_q_points);
1301 if (computed_cell_similarity != CellSimilarity::translation)
1302 for (unsigned int point = 0; point < n_q_points; ++point)
1303 output_data.jacobians[point] = data.contravariant[point];
1304 }
1305
1306 // copy values from InternalData to vector given by reference
1307 if (update_flags & update_inverse_jacobians)
1308 {
1309 AssertDimension(output_data.inverse_jacobians.size(), n_q_points);
1310 if (computed_cell_similarity != CellSimilarity::translation)
1311 for (unsigned int point = 0; point < n_q_points; ++point)
1312 output_data.inverse_jacobians[point] =
1313 data.covariant[point].transpose();
1314 }
1315
1316 return computed_cell_similarity;
1317}
1318
1319
1320
1321namespace internal
1322{
1323 namespace MappingFEImplementation
1324 {
1325 namespace
1326 {
1337 template <int dim, int spacedim>
1338 void
1339 maybe_compute_face_data(
1340 const ::MappingFE<dim, spacedim> &mapping,
1341 const typename ::Triangulation<dim, spacedim>::cell_iterator
1342 &cell,
1343 const unsigned int face_no,
1344 const unsigned int subface_no,
1345 const unsigned int n_q_points,
1346 const typename QProjector<dim>::DataSetDescriptor data_set,
1347 const typename ::MappingFE<dim, spacedim>::InternalData &data,
1349 &output_data)
1350 {
1351 const UpdateFlags update_flags = data.update_each;
1352
1353 if (update_flags &
1356 {
1357 if (update_flags & update_boundary_forms)
1358 AssertIndexRange(n_q_points,
1359 output_data.boundary_forms.size() + 1);
1360 if (update_flags & update_normal_vectors)
1361 AssertIndexRange(n_q_points,
1362 output_data.normal_vectors.size() + 1);
1363 if (update_flags & update_JxW_values)
1364 AssertIndexRange(n_q_points, output_data.JxW_values.size() + 1);
1365
1366 Assert(data.aux.size() + 1 >= dim, ExcInternalError());
1367
1368 // first compute some common data that is used for evaluating
1369 // all of the flags below
1370
1371 // map the unit tangentials to the real cell. checking for
1372 // d!=dim-1 eliminates compiler warnings regarding unsigned int
1373 // expressions < 0.
1374 for (unsigned int d = 0; d != dim - 1; ++d)
1375 {
1376 Assert(face_no + cell->n_faces() * d <
1377 data.unit_tangentials.size(),
1379 Assert(
1380 data.aux[d].size() <=
1381 data.unit_tangentials[face_no + cell->n_faces() * d].size(),
1383
1384 mapping.transform(
1386 data.unit_tangentials[face_no + cell->n_faces() * d]),
1388 data,
1389 make_array_view(data.aux[d]));
1390 }
1391
1392 if (update_flags & update_boundary_forms)
1393 {
1394 // if dim==spacedim, we can use the unit tangentials to
1395 // compute the boundary form by simply taking the cross
1396 // product
1397 if (dim == spacedim)
1398 {
1399 for (unsigned int i = 0; i < n_q_points; ++i)
1400 switch (dim)
1401 {
1402 case 1:
1403 // in 1d, we don't have access to any of the
1404 // data.aux fields (because it has only dim-1
1405 // components), but we can still compute the
1406 // boundary form by simply looking at the number
1407 // of the face
1408 output_data.boundary_forms[i][0] =
1409 (face_no == 0 ? -1 : +1);
1410 break;
1411 case 2:
1412 output_data.boundary_forms[i] =
1413 cross_product_2d(data.aux[0][i]);
1414 break;
1415 case 3:
1416 output_data.boundary_forms[i] =
1417 cross_product_3d(data.aux[0][i], data.aux[1][i]);
1418 break;
1419 default:
1421 }
1422 }
1423 else //(dim < spacedim)
1424 {
1425 // in the codim-one case, the boundary form results from
1426 // the cross product of all the face tangential vectors
1427 // and the cell normal vector
1428 //
1429 // to compute the cell normal, use the same method used in
1430 // fill_fe_values for cells above
1431 AssertIndexRange(n_q_points, data.contravariant.size() + 1);
1432
1433 for (unsigned int point = 0; point < n_q_points; ++point)
1434 {
1435 if (dim == 1)
1436 {
1437 // J is a tangent vector
1438 output_data.boundary_forms[point] =
1439 data.contravariant[point].transpose()[0];
1440 output_data.boundary_forms[point] /=
1441 (face_no == 0 ? -1. : +1.) *
1442 output_data.boundary_forms[point].norm();
1443 }
1444
1445 if (dim == 2)
1446 {
1448 data.contravariant[point].transpose();
1449
1450 Tensor<1, spacedim> cell_normal =
1451 cross_product_3d(DX_t[0], DX_t[1]);
1452 cell_normal /= cell_normal.norm();
1453
1454 // then compute the face normal from the face
1455 // tangent and the cell normal:
1456 output_data.boundary_forms[point] =
1457 cross_product_3d(data.aux[0][point], cell_normal);
1458 }
1459 }
1460 }
1461 }
1462
1463 if (update_flags & update_JxW_values)
1464 for (unsigned int i = 0; i < n_q_points; ++i)
1465 {
1466 output_data.JxW_values[i] =
1467 output_data.boundary_forms[i].norm() *
1468 data.quadrature_weights[i + data_set];
1469
1470 if (subface_no != numbers::invalid_unsigned_int)
1471 {
1472 if (dim == 2)
1473 {
1474 const double area_ratio =
1475 1. / cell->reference_cell()
1476 .face_reference_cell(face_no)
1477 .n_isotropic_children();
1478 output_data.JxW_values[i] *= area_ratio;
1479 }
1480 else
1482 }
1483 }
1484
1485 if (update_flags & update_normal_vectors)
1486 for (unsigned int i = 0; i < n_q_points; ++i)
1487 output_data.normal_vectors[i] =
1488 Point<spacedim>(output_data.boundary_forms[i] /
1489 output_data.boundary_forms[i].norm());
1490
1491 if (update_flags & update_jacobians)
1492 for (unsigned int point = 0; point < n_q_points; ++point)
1493 output_data.jacobians[point] = data.contravariant[point];
1494
1495 if (update_flags & update_inverse_jacobians)
1496 for (unsigned int point = 0; point < n_q_points; ++point)
1497 output_data.inverse_jacobians[point] =
1498 data.covariant[point].transpose();
1499 }
1500 }
1501
1502
1509 template <int dim, int spacedim>
1510 void
1512 const ::MappingFE<dim, spacedim> &mapping,
1513 const typename ::Triangulation<dim, spacedim>::cell_iterator
1514 &cell,
1515 const unsigned int face_no,
1516 const unsigned int subface_no,
1517 const typename QProjector<dim>::DataSetDescriptor data_set,
1518 const Quadrature<dim - 1> &quadrature,
1519 const typename ::MappingFE<dim, spacedim>::InternalData &data,
1521 &output_data)
1522 {
1523 const unsigned int n_q_points = quadrature.size();
1524
1525 maybe_compute_q_points<dim, spacedim>(data_set,
1526 data,
1527 output_data.quadrature_points,
1528 n_q_points);
1529 maybe_update_Jacobians<dim, spacedim>(CellSimilarity::none,
1530 data_set,
1531 data,
1532 n_q_points);
1533 maybe_update_jacobian_grads<dim, spacedim>(CellSimilarity::none,
1534 data_set,
1535 data,
1536 output_data.jacobian_grads,
1537 n_q_points);
1538 maybe_update_jacobian_pushed_forward_grads<dim, spacedim>(
1540 data_set,
1541 data,
1543 n_q_points);
1544 maybe_update_jacobian_2nd_derivatives<dim, spacedim>(
1546 data_set,
1547 data,
1548 output_data.jacobian_2nd_derivatives,
1549 n_q_points);
1550 maybe_update_jacobian_pushed_forward_2nd_derivatives<dim, spacedim>(
1552 data_set,
1553 data,
1555 n_q_points);
1556 maybe_update_jacobian_3rd_derivatives<dim, spacedim>(
1558 data_set,
1559 data,
1560 output_data.jacobian_3rd_derivatives,
1561 n_q_points);
1562 maybe_update_jacobian_pushed_forward_3rd_derivatives<dim, spacedim>(
1564 data_set,
1565 data,
1567 n_q_points);
1568
1570 cell,
1571 face_no,
1572 subface_no,
1573 n_q_points,
1574 data_set,
1575 data,
1576 output_data);
1577 }
1578 } // namespace
1579 } // namespace MappingFEImplementation
1580} // namespace internal
1581
1582
1583
1584template <int dim, int spacedim>
1585void
1588 const unsigned int face_no,
1589 const hp::QCollection<dim - 1> &quadrature,
1590 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1592 &output_data) const
1593{
1594 // ensure that the following cast is really correct:
1595 Assert((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1597 const InternalData &data = static_cast<const InternalData &>(internal_data);
1598
1599 const auto support_points = this->compute_mapping_support_points(cell);
1600 data.mapping_support_points.assign(support_points.begin(),
1601 support_points.end());
1602
1603 internal::MappingFEImplementation::do_fill_fe_face_values(
1604 *this,
1605 cell,
1606 face_no,
1608 QProjector<dim>::DataSetDescriptor::face(this->fe->reference_cell(),
1609 face_no,
1610 cell->combined_face_orientation(
1611 face_no),
1612 quadrature),
1613 quadrature[quadrature.size() == 1 ? 0 : face_no],
1614 data,
1615 output_data);
1616}
1617
1618
1619
1620template <int dim, int spacedim>
1621void
1624 const unsigned int face_no,
1625 const unsigned int subface_no,
1626 const Quadrature<dim - 1> &quadrature,
1627 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1629 &output_data) const
1630{
1631 // ensure that the following cast is really correct:
1632 Assert((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1634 const InternalData &data = static_cast<const InternalData &>(internal_data);
1635
1636 const auto support_points = this->compute_mapping_support_points(cell);
1637 data.mapping_support_points.assign(support_points.begin(),
1638 support_points.end());
1639
1640 internal::MappingFEImplementation::do_fill_fe_face_values(
1641 *this,
1642 cell,
1643 face_no,
1644 subface_no,
1645 QProjector<dim>::DataSetDescriptor::subface(this->fe->reference_cell(),
1646 face_no,
1647 subface_no,
1648 cell->combined_face_orientation(
1649 face_no),
1650 quadrature.size(),
1651 cell->subface_case(face_no)),
1652 quadrature,
1653 data,
1654 output_data);
1655}
1656
1657
1658
1659namespace internal
1660{
1661 namespace MappingFEImplementation
1662 {
1663 namespace
1664 {
1665 template <int dim, int spacedim, int rank>
1666 void
1667 transform_fields(
1668 const ArrayView<const Tensor<rank, dim>> &input,
1669 const MappingKind mapping_kind,
1670 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1671 const ArrayView<Tensor<rank, spacedim>> &output)
1672 {
1673 // In the case of wedges and pyramids, faces might have different
1674 // numbers of quadrature points on each face with the result
1675 // that input and output have different sizes, since input has
1676 // the correct size but the size of output is the maximum of
1677 // all possible sizes.
1678 AssertIndexRange(input.size(), output.size() + 1);
1679
1680 Assert(
1681 (dynamic_cast<
1682 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1683 &mapping_data) != nullptr),
1685 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1686 static_cast<
1687 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1688 mapping_data);
1689
1690 switch (mapping_kind)
1691 {
1693 {
1694 Assert(
1697 "update_contravariant_transformation"));
1698
1699 for (unsigned int i = 0; i < input.size(); ++i)
1700 output[i] =
1701 apply_transformation(data.contravariant[i], input[i]);
1702
1703 return;
1704 }
1705
1706 case mapping_piola:
1707 {
1708 Assert(
1711 "update_contravariant_transformation"));
1712 Assert(
1713 data.update_each & update_volume_elements,
1715 "update_volume_elements"));
1716 Assert(rank == 1, ExcMessage("Only for rank 1"));
1717 if (rank != 1)
1718 return;
1719
1720 for (unsigned int i = 0; i < input.size(); ++i)
1721 {
1722 output[i] =
1723 apply_transformation(data.contravariant[i], input[i]);
1724 output[i] /= data.volume_elements[i];
1725 }
1726 return;
1727 }
1728 // We still allow this operation as in the
1729 // reference cell Derivatives are Tensor
1730 // rather than DerivativeForm
1731 case mapping_covariant:
1732 {
1733 Assert(
1736 "update_covariant_transformation"));
1737
1738 for (unsigned int i = 0; i < input.size(); ++i)
1739 output[i] = apply_transformation(data.covariant[i], input[i]);
1740
1741 return;
1742 }
1743
1744 default:
1746 }
1747 }
1748
1749
1750 template <int dim, int spacedim, int rank>
1751 void
1753 const ArrayView<const Tensor<rank, dim>> &input,
1754 const MappingKind mapping_kind,
1755 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1756 const ArrayView<Tensor<rank, spacedim>> &output)
1757 {
1758 AssertDimension(input.size(), output.size());
1759 Assert(
1760 (dynamic_cast<
1761 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1762 &mapping_data) != nullptr),
1764 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1765 static_cast<
1766 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1767 mapping_data);
1768
1769 switch (mapping_kind)
1770 {
1772 {
1773 Assert(
1776 "update_covariant_transformation"));
1777 Assert(
1780 "update_contravariant_transformation"));
1781 Assert(rank == 2, ExcMessage("Only for rank 2"));
1782
1783 for (unsigned int i = 0; i < output.size(); ++i)
1784 {
1786 apply_transformation(data.contravariant[i],
1787 transpose(input[i]));
1788 output[i] =
1789 apply_transformation(data.covariant[i], A.transpose());
1790 }
1791
1792 return;
1793 }
1794
1796 {
1797 Assert(
1800 "update_covariant_transformation"));
1801 Assert(rank == 2, ExcMessage("Only for rank 2"));
1802
1803 for (unsigned int i = 0; i < output.size(); ++i)
1804 {
1806 apply_transformation(data.covariant[i],
1807 transpose(input[i]));
1808 output[i] =
1809 apply_transformation(data.covariant[i], A.transpose());
1810 }
1811
1812 return;
1813 }
1814
1816 {
1817 Assert(
1820 "update_covariant_transformation"));
1821 Assert(
1824 "update_contravariant_transformation"));
1825 Assert(
1826 data.update_each & update_volume_elements,
1828 "update_volume_elements"));
1829 Assert(rank == 2, ExcMessage("Only for rank 2"));
1830
1831 for (unsigned int i = 0; i < output.size(); ++i)
1832 output[i] =
1834 data.contravariant[i],
1835 data.volume_elements[i],
1836 input[i]);
1837
1838 return;
1839 }
1840
1841 default:
1843 }
1844 }
1845
1846
1847
1848 template <int dim, int spacedim>
1849 void
1851 const ArrayView<const Tensor<3, dim>> &input,
1852 const MappingKind mapping_kind,
1853 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1854 const ArrayView<Tensor<3, spacedim>> &output)
1855 {
1856 AssertDimension(input.size(), output.size());
1857 Assert(
1858 (dynamic_cast<
1859 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1860 &mapping_data) != nullptr),
1862 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1863 static_cast<
1864 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1865 mapping_data);
1866
1867 switch (mapping_kind)
1868 {
1870 {
1871 Assert(
1874 "update_covariant_transformation"));
1875 Assert(
1878 "update_contravariant_transformation"));
1879
1880 for (unsigned int q = 0; q < output.size(); ++q)
1881 output[q] =
1883 data.contravariant[q],
1884 input[q]);
1885
1886 return;
1887 }
1888
1890 {
1891 Assert(
1894 "update_covariant_transformation"));
1895
1896 for (unsigned int q = 0; q < output.size(); ++q)
1897 output[q] =
1899 input[q]);
1900
1901 return;
1902 }
1903
1905 {
1906 Assert(
1909 "update_covariant_transformation"));
1910 Assert(
1913 "update_contravariant_transformation"));
1914 Assert(
1915 data.update_each & update_volume_elements,
1917 "update_volume_elements"));
1918
1919 for (unsigned int q = 0; q < output.size(); ++q)
1920 output[q] =
1922 data.contravariant[q],
1923 data.volume_elements[q],
1924 input[q]);
1925
1926 return;
1927 }
1928
1929 default:
1931 }
1932 }
1933
1934
1935
1936 template <int dim, int spacedim, int rank>
1937 void
1940 const MappingKind mapping_kind,
1941 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1943 {
1944 AssertDimension(input.size(), output.size());
1945 Assert(
1946 (dynamic_cast<
1947 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1948 &mapping_data) != nullptr),
1950 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1951 static_cast<
1952 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1953 mapping_data);
1954
1955 switch (mapping_kind)
1956 {
1957 case mapping_covariant:
1958 {
1959 Assert(
1962 "update_covariant_transformation"));
1963
1964 for (unsigned int i = 0; i < output.size(); ++i)
1965 output[i] = apply_transformation(data.covariant[i], input[i]);
1966
1967 return;
1968 }
1969 default:
1971 }
1972 }
1973 } // namespace
1974 } // namespace MappingFEImplementation
1975} // namespace internal
1976
1977
1978
1979template <int dim, int spacedim>
1980void
1982 const ArrayView<const Tensor<1, dim>> &input,
1983 const MappingKind mapping_kind,
1984 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1985 const ArrayView<Tensor<1, spacedim>> &output) const
1986{
1987 internal::MappingFEImplementation::transform_fields(input,
1988 mapping_kind,
1989 mapping_data,
1990 output);
1991}
1992
1993
1994
1995template <int dim, int spacedim>
1996void
1998 const ArrayView<const DerivativeForm<1, dim, spacedim>> &input,
1999 const MappingKind mapping_kind,
2000 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2001 const ArrayView<Tensor<2, spacedim>> &output) const
2002{
2003 internal::MappingFEImplementation::transform_differential_forms(input,
2004 mapping_kind,
2005 mapping_data,
2006 output);
2007}
2008
2009
2010
2011template <int dim, int spacedim>
2012void
2014 const ArrayView<const Tensor<2, dim>> &input,
2015 const MappingKind mapping_kind,
2016 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2017 const ArrayView<Tensor<2, spacedim>> &output) const
2018{
2019 switch (mapping_kind)
2020 {
2022 internal::MappingFEImplementation::transform_fields(input,
2023 mapping_kind,
2024 mapping_data,
2025 output);
2026 return;
2027
2031 internal::MappingFEImplementation::transform_gradients(input,
2032 mapping_kind,
2033 mapping_data,
2034 output);
2035 return;
2036 default:
2038 }
2039}
2040
2041
2042
2043template <int dim, int spacedim>
2044void
2046 const ArrayView<const DerivativeForm<2, dim, spacedim>> &input,
2047 const MappingKind mapping_kind,
2048 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2049 const ArrayView<Tensor<3, spacedim>> &output) const
2050{
2051 AssertDimension(input.size(), output.size());
2052 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
2054 const InternalData &data = static_cast<const InternalData &>(mapping_data);
2055
2056 switch (mapping_kind)
2057 {
2059 {
2062 "update_covariant_transformation"));
2063
2064 for (unsigned int q = 0; q < output.size(); ++q)
2065 output[q] =
2066 internal::apply_covariant_gradient(data.covariant[q], input[q]);
2067
2068 return;
2069 }
2070
2071 default:
2073 }
2074}
2075
2076
2077
2078template <int dim, int spacedim>
2079void
2081 const ArrayView<const Tensor<3, dim>> &input,
2082 const MappingKind mapping_kind,
2083 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2084 const ArrayView<Tensor<3, spacedim>> &output) const
2085{
2086 switch (mapping_kind)
2087 {
2091 internal::MappingFEImplementation::transform_hessians(input,
2092 mapping_kind,
2093 mapping_data,
2094 output);
2095 return;
2096 default:
2098 }
2099}
2100
2101
2102
2103namespace
2104{
2105 template <int spacedim>
2106 bool
2107 check_all_manifold_ids_identical(
2109 {
2110 return true;
2111 }
2112
2113
2114
2115 template <int spacedim>
2116 bool
2117 check_all_manifold_ids_identical(
2119 {
2120 const auto m_id = cell->manifold_id();
2121
2122 for (const auto f : cell->face_indices())
2123 if (m_id != cell->face(f)->manifold_id())
2124 return false;
2125
2126 return true;
2127 }
2128
2129
2130
2131 template <int spacedim>
2132 bool
2133 check_all_manifold_ids_identical(
2135 {
2136 const auto m_id = cell->manifold_id();
2137
2138 for (const auto f : cell->face_indices())
2139 if (m_id != cell->face(f)->manifold_id())
2140 return false;
2141
2142 for (const auto l : cell->line_indices())
2143 if (m_id != cell->line(l)->manifold_id())
2144 return false;
2145
2146 return true;
2147 }
2148} // namespace
2149
2150
2151
2152template <int dim, int spacedim>
2153boost::container::small_vector<Point<spacedim>, 200>
2155 const typename Triangulation<dim, spacedim>::cell_iterator &cell) const
2156{
2157 boost::container::small_vector<Point<spacedim>, 200> points;
2159 ReferenceCells::max_n_vertices<dim>()>
2160 vertices(cell->n_vertices());
2161 for (const unsigned int i : cell->vertex_indices())
2162 vertices[i] = cell->vertex(i);
2163
2164 points.resize(mapping_support_point_weights.size(0));
2165 if (check_all_manifold_ids_identical(cell))
2166 {
2167 // version 1) all geometric entities have the same manifold:
2168 cell->get_manifold().get_new_points(ArrayView<const Point<spacedim>>(
2169 vertices),
2170 mapping_support_point_weights,
2171 ArrayView<Point<spacedim>>(points));
2172 }
2173 else
2174 {
2175 // version 1) geometric entities have different manifold
2176
2177 // helper function to compute mapped points on subentities
2178 // note[PM]: this function currently only uses the vertices
2179 // of cells to create new points on subentities; however,
2180 // one should use all bounding points to create new points
2181 // as in the case of MappingQ.
2182 const auto process = [&](const auto &manifold,
2183 const auto &indices,
2184 const unsigned n_points) {
2185 if ((indices.size() == 0) || (n_points == 0))
2186 return;
2187
2188 const unsigned int n_shape_functions =
2189 this->fe->reference_cell().n_vertices();
2190
2191 Table<2, double> mapping_support_point_weights_local(n_points,
2192 n_shape_functions);
2193 std::vector<Point<spacedim>> mapping_support_points_local(n_points);
2194
2195 for (unsigned int p = 0; p < n_points; ++p)
2196 for (unsigned int i = 0; i < n_shape_functions; ++i)
2197 mapping_support_point_weights_local(p, i) =
2198 mapping_support_point_weights(
2199 indices[p + (indices.size() - n_points)], i);
2200
2201 manifold.get_new_points(ArrayView<const Point<spacedim>>(vertices),
2202 mapping_support_point_weights_local,
2204 mapping_support_points_local));
2205
2206 for (unsigned int p = 0; p < n_points; ++p)
2207 points[indices[p + (indices.size() - n_points)]] =
2208 mapping_support_points_local[p];
2209 };
2210
2211 // create dummy DoFHandler to extract indices on subobjects
2212 const auto &fe = *this->fe;
2214 GridGenerator::reference_cell(tria, fe.reference_cell());
2215 DoFHandler<dim, spacedim> dof_handler(tria);
2216 dof_handler.distribute_dofs(fe);
2217 const auto &cell_ref = dof_handler.begin_active();
2218
2219 std::vector<types::global_dof_index> indices;
2220
2221 // add vertices
2222 for (const unsigned int i : cell->vertex_indices())
2223 points[i] = vertices[i];
2224
2225 // process and add line support points
2226 for (unsigned int l = 0; l < cell_ref->n_lines(); ++l)
2227 {
2228 const auto accessor = cell_ref->line(l);
2229 indices.resize(fe.n_dofs_per_line() + 2 * fe.n_dofs_per_vertex());
2230 accessor->get_dof_indices(indices);
2231 process(cell->line(l)->get_manifold(), indices, fe.n_dofs_per_line());
2232 }
2233
2234 // process and add face support points
2235 if constexpr (dim >= 3)
2236 {
2237 for (unsigned int f = 0; f < cell_ref->n_faces(); ++f)
2238 {
2239 const auto accessor = cell_ref->face(f);
2240 indices.resize(fe.n_dofs_per_face());
2241 accessor->get_dof_indices(indices);
2242 process(cell->face(f)->get_manifold(),
2243 indices,
2244 fe.n_dofs_per_quad());
2245 }
2246 }
2247
2248 // process and add volume support points
2249 if constexpr (dim >= 2)
2250 {
2251 indices.resize(fe.n_dofs_per_cell());
2252 cell_ref->get_dof_indices(indices);
2253 process(cell->get_manifold(),
2254 indices,
2255 (dim == 2) ? fe.n_dofs_per_quad() : fe.n_dofs_per_hex());
2256 }
2257 }
2258
2259 return points;
2260}
2261
2262
2263
2264template <int dim, int spacedim>
2267 const typename Triangulation<dim, spacedim>::cell_iterator &cell) const
2268{
2269 return BoundingBox<spacedim>(this->compute_mapping_support_points(cell));
2270}
2271
2272
2273
2274template <int dim, int spacedim>
2275bool
2277 const ReferenceCell<dim> &reference_cell) const
2278{
2279 Assert(dim == reference_cell.get_dimension(),
2280 ExcMessage("The dimension of your mapping (" +
2282 ") and the reference cell cell_type (" +
2283 Utilities::to_string(reference_cell.get_dimension()) +
2284 " ) do not agree."));
2285
2286 return fe->reference_cell() == reference_cell;
2287}
2288
2289
2290
2291//--------------------------- Explicit instantiations -----------------------
2292#include "fe/mapping_fe.inst"
2293
2294
*  iterator end()
*  *  iterator begin()
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
DerivativeForm< 1, spacedim, dim, Number > transpose() const
void distribute_dofs(const FiniteElement< dim, spacedim > &fe)
active_cell_iterator begin_active(const unsigned int level=0) const
void initialize_face(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
void compute_shape_function_values(const std::vector< Point< dim > > &unit_points)
virtual std::size_t memory_consumption() const override
Definition mapping_fe.cc:60
InternalData(const FiniteElement< dim, spacedim > &fe)
Definition mapping_fe.cc:49
virtual void reinit(const UpdateFlags update_flags, const Quadrature< dim > &quadrature) override
Definition mapping_fe.cc:79
virtual CellSimilarity::Similarity fill_fe_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellSimilarity::Similarity cell_similarity, const Quadrature< dim > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
const unsigned int polynomial_degree
Definition mapping_fe.h:457
MappingFE(const FiniteElement< dim, spacedim > &fe)
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_face_data(const UpdateFlags flags, const hp::QCollection< dim - 1 > &quadrature) const override
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const override
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
virtual boost::container::small_vector< Point< spacedim >, 200 > compute_mapping_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
virtual void fill_fe_face_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const hp::QCollection< dim - 1 > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
Table< 2, double > mapping_support_point_weights
Definition mapping_fe.h:467
virtual void transform(const ArrayView< const Tensor< 1, dim > > &input, const MappingKind kind, const typename Mapping< dim, spacedim >::InternalDataBase &internal, const ArrayView< Tensor< 1, spacedim > > &output) const override
virtual BoundingBox< spacedim > get_bounding_box(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const override
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags, const Quadrature< dim > &quadrature) const override
virtual bool is_compatible_with(const ReferenceCell< dim > &reference_cell) const override
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_subface_data(const UpdateFlags flags, const Quadrature< dim - 1 > &quadrature) const override
unsigned int get_degree() const
virtual void fill_fe_subface_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int subface_no, const Quadrature< dim - 1 > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() const override
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const override
const std::unique_ptr< FiniteElement< dim, spacedim > > fe
Definition mapping_fe.h:451
Abstract base class for mapping classes.
Definition mapping.h:318
Definition point.h:111
Class storing the offset index into a Quadrature rule created by project_to_all_faces() or project_to...
Definition qprojector.h:204
static DataSetDescriptor cell()
Definition qprojector.h:314
Class which transforms dim - 1-dimensional quadrature rules to dim-dimensional face quadratures.
Definition qprojector.h:68
const std::vector< double > & get_weights() const
const std::vector< Point< dim > > & get_points() const
unsigned int size() const
numbers::NumberTraits< Number >::real_type norm() const
unsigned int size() const
Definition collection.h:314
unsigned int max_n_quadrature_points() const
std::vector< DerivativeForm< 1, spacedim, dim > > inverse_jacobians
std::vector< Tensor< 5, spacedim > > jacobian_pushed_forward_3rd_derivatives
std::vector< DerivativeForm< 4, dim, spacedim > > jacobian_3rd_derivatives
std::vector< DerivativeForm< 3, dim, spacedim > > jacobian_2nd_derivatives
std::vector< Tensor< 4, spacedim > > jacobian_pushed_forward_2nd_derivatives
std::vector< Tensor< 3, spacedim > > jacobian_pushed_forward_grads
std::vector< DerivativeForm< 2, dim, spacedim > > jacobian_grads
std::vector< DerivativeForm< 1, dim, spacedim > > jacobians
#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)
Tensor< 1, spacedim, typename ProductType< Number1, Number2 >::type > apply_transformation(const DerivativeForm< 1, dim, spacedim, Number1 > &grad_F, const Tensor< 1, dim, Number2 > &d_x)
#define DEAL_II_NOT_IMPLEMENTED()
Point< 2 > second
Definition grid_out.cc:4640
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
UpdateFlags
@ update_jacobian_pushed_forward_2nd_derivatives
@ update_volume_elements
Determinant of the Jacobian.
@ update_contravariant_transformation
Contravariant transformation.
@ update_jacobian_pushed_forward_grads
@ update_jacobian_3rd_derivatives
@ update_jacobian_grads
Gradient of volume element.
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_covariant_transformation
Covariant transformation.
@ update_jacobians
Volume element.
@ update_inverse_jacobians
Volume element.
@ update_quadrature_points
Transformed quadrature points.
@ update_jacobian_pushed_forward_3rd_derivatives
@ update_boundary_forms
Outer normal vector, not normalized.
@ update_jacobian_2nd_derivatives
MappingKind
Definition mapping.h:79
@ mapping_piola
Definition mapping.h:114
@ mapping_covariant_gradient
Definition mapping.h:100
@ mapping_covariant
Definition mapping.h:89
@ mapping_contravariant
Definition mapping.h:94
@ mapping_contravariant_hessian
Definition mapping.h:156
@ mapping_covariant_hessian
Definition mapping.h:150
@ mapping_contravariant_gradient
Definition mapping.h:106
@ mapping_piola_gradient
Definition mapping.h:120
@ mapping_piola_hessian
Definition mapping.h:162
std::vector< index_type > data
Definition mpi.cc:734
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell< dim > &reference_cell)
constexpr char A
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
Definition utilities.cc:210
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
*  *  if(update_pressure &update_flags) *  compute_pressure(constitutive_request
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:473
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:464
void transform_differential_forms(const ArrayView< const DerivativeForm< rank, dim, spacedim > > &input, const MappingKind mapping_kind, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_data, const ArrayView< Tensor< rank+1, spacedim > > &output)
void do_fill_fe_face_values(const ::MappingQ< dim, spacedim > &mapping, const typename ::Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int subface_no, const typename QProjector< dim >::DataSetDescriptor data_set, const Quadrature< dim - 1 > &quadrature, const typename ::MappingQ< dim, spacedim >::InternalData &data, const std::vector< Polynomials::Polynomial< double > > &polynomials_1d, const std::vector< unsigned int > &renumber_lexicographic_to_hierarchic, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data)
void transform_gradients(const ArrayView< const Tensor< rank, dim > > &input, const MappingKind mapping_kind, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_data, const ArrayView< Tensor< rank, spacedim > > &output)
void transform_hessians(const ArrayView< const Tensor< 3, dim > > &input, const MappingKind mapping_kind, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_data, const ArrayView< Tensor< 3, spacedim > > &output)
void maybe_compute_face_data(const ::MappingQ< dim, spacedim > &mapping, const typename ::Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int subface_no, const unsigned int n_q_points, const std::vector< double > &weights, const typename ::MappingQ< dim, spacedim >::InternalData &data, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data)
Tensor< 3, spacedim, Number > apply_contravariant_hessian(const DerivativeForm< 1, dim, spacedim, Number > &covariant, const DerivativeForm< 1, dim, spacedim, Number > &contravariant, const Tensor< 3, dim, Number > &input)
Tensor< 3, spacedim, Number > apply_piola_hessian(const DerivativeForm< 1, dim, spacedim, Number > &covariant, const DerivativeForm< 1, dim, spacedim, Number > &contravariant, const Number &volume_element, const Tensor< 3, dim, Number > &input)
Tensor< 2, spacedim, Number > apply_piola_gradient(const DerivativeForm< 1, dim, spacedim, Number > &covariant, const DerivativeForm< 1, dim, spacedim, Number > &contravariant, const Number &volume_element, const Tensor< 2, dim, Number > &input)
Tensor< 3, spacedim, Number > apply_covariant_gradient(const DerivativeForm< 1, dim, spacedim, Number > &covariant, const DerivativeForm< 2, dim, spacedim, Number > &input)
Tensor< 3, spacedim, Number > apply_covariant_hessian(const DerivativeForm< 1, dim, spacedim, Number > &covariant, const Tensor< 3, dim, Number > &input)
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:171
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)