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