deal.II version 9.8.0
\(\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>
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
89 covariant.resize(n_q_points);
90
93
96
97 // see if we need the (transformation) shape function values
98 // and/or gradients and resize the necessary arrays
101
102 if (this->update_each &
111
112 if (this->update_each &
115
119
123
124 // now also fill the various fields with their correct values
126
127 // copy (projected) quadrature 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 unit cell.
150 const auto reference_cell = this->fe.reference_cell();
151 const auto n_faces = reference_cell.n_faces();
152
153 for (unsigned int i = 0; i < n_faces; ++i)
154 {
155 unit_tangentials[i].resize(n_original_q_points);
156 std::fill(unit_tangentials[i].begin(),
158 reference_cell.face_tangent_vector(i, 0));
159 if (dim > 2)
160 {
161 unit_tangentials[n_faces + i].resize(n_original_q_points);
162 std::fill(unit_tangentials[n_faces + i].begin(),
163 unit_tangentials[n_faces + i].end(),
164 reference_cell.face_tangent_vector(i, 1));
165 }
166 }
167 }
168}
169
170
171
172template <int dim, int spacedim>
173void
175 const std::vector<Point<dim>> &unit_points)
176{
177 const auto fe_poly = dynamic_cast<const FE_Poly<dim, spacedim> *>(&this->fe);
178
179 Assert(fe_poly != nullptr, ExcNotImplemented());
180
181 const auto &tensor_pols = fe_poly->get_poly_space();
182
183 const unsigned int n_shape_functions = fe.n_dofs_per_cell();
184 const unsigned int n_points = unit_points.size();
185
186 std::vector<double> values;
187 std::vector<Tensor<1, dim>> grads;
188 if (shape_values.size() != 0)
189 {
190 Assert(shape_values.size() == n_shape_functions * n_points,
192 values.resize(n_shape_functions);
193 }
194 if (shape_derivatives.size() != 0)
195 {
196 Assert(shape_derivatives.size() == n_shape_functions * n_points,
198 grads.resize(n_shape_functions);
199 }
200
201 std::vector<Tensor<2, dim>> grad2;
202 if (shape_second_derivatives.size() != 0)
203 {
206 grad2.resize(n_shape_functions);
207 }
208
209 std::vector<Tensor<3, dim>> grad3;
210 if (shape_third_derivatives.size() != 0)
211 {
214 grad3.resize(n_shape_functions);
215 }
216
217 std::vector<Tensor<4, dim>> grad4;
218 if (shape_fourth_derivatives.size() != 0)
219 {
222 grad4.resize(n_shape_functions);
223 }
224
225
226 if (shape_values.size() != 0 || shape_derivatives.size() != 0 ||
227 shape_second_derivatives.size() != 0 ||
228 shape_third_derivatives.size() != 0 ||
229 shape_fourth_derivatives.size() != 0)
230 for (unsigned int point = 0; point < n_points; ++point)
231 {
232 tensor_pols.evaluate(
233 unit_points[point], values, grads, grad2, grad3, grad4);
234
235 if (shape_values.size() != 0)
236 for (unsigned int i = 0; i < n_shape_functions; ++i)
237 shape(point, i) = values[i];
238
239 if (shape_derivatives.size() != 0)
240 for (unsigned int i = 0; i < n_shape_functions; ++i)
241 derivative(point, i) = grads[i];
242
243 if (shape_second_derivatives.size() != 0)
244 for (unsigned int i = 0; i < n_shape_functions; ++i)
245 second_derivative(point, i) = grad2[i];
246
247 if (shape_third_derivatives.size() != 0)
248 for (unsigned int i = 0; i < n_shape_functions; ++i)
249 third_derivative(point, i) = grad3[i];
250
251 if (shape_fourth_derivatives.size() != 0)
252 for (unsigned int i = 0; i < n_shape_functions; ++i)
253 fourth_derivative(point, i) = grad4[i];
254 }
255}
256
257
258namespace internal
259{
261 {
262 namespace
263 {
270 template <int dim, int spacedim>
271 void
272 maybe_compute_q_points(
273 const typename QProjector<dim>::DataSetDescriptor data_set,
274 const typename ::MappingFE<dim, spacedim>::InternalData &data,
275 std::vector<Point<spacedim>> &quadrature_points,
276 const unsigned int n_q_points)
277 {
278 const UpdateFlags update_flags = data.update_each;
279
280 if (update_flags & update_quadrature_points)
281 for (unsigned int point = 0; point < n_q_points; ++point)
282 {
283 const double *shape = &data.shape(point + data_set, 0);
284 Point<spacedim> result =
285 (shape[0] * data.mapping_support_points[0]);
286 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
287 for (unsigned int i = 0; i < spacedim; ++i)
288 result[i] += shape[k] * data.mapping_support_points[k][i];
289 quadrature_points[point] = result;
290 }
291 }
292
293
294
303 template <int dim, int spacedim>
304 void
305 maybe_update_Jacobians(
306 const CellSimilarity::Similarity cell_similarity,
307 const typename ::QProjector<dim>::DataSetDescriptor data_set,
308 const typename ::MappingFE<dim, spacedim>::InternalData &data,
309 const unsigned int n_q_points)
310 {
311 const UpdateFlags update_flags = data.update_each;
312
313 if (update_flags & update_contravariant_transformation)
314 // if the current cell is just a
315 // translation of the previous one, no
316 // need to recompute jacobians...
317 if (cell_similarity != CellSimilarity::translation)
318 {
319 std::fill(data.contravariant.begin(),
320 data.contravariant.end(),
322
323 Assert(data.n_shape_functions > 0, ExcInternalError());
324
325 for (unsigned int point = 0; point < n_q_points; ++point)
326 {
327 double result[spacedim][dim];
328
329 // peel away part of sum to avoid zeroing the
330 // entries and adding for the first time
331 for (unsigned int i = 0; i < spacedim; ++i)
332 for (unsigned int j = 0; j < dim; ++j)
333 result[i][j] = data.derivative(point + data_set, 0)[j] *
334 data.mapping_support_points[0][i];
335 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
336 for (unsigned int i = 0; i < spacedim; ++i)
337 for (unsigned int j = 0; j < dim; ++j)
338 result[i][j] +=
339 data.derivative(point + data_set, k)[j] *
340 data.mapping_support_points[k][i];
341
342 // write result into contravariant data. for
343 // j=dim in the case dim<spacedim, there will
344 // never be any nonzero data that arrives in
345 // here, so it is ok anyway because it was
346 // initialized to zero at the initialization
347 for (unsigned int i = 0; i < spacedim; ++i)
348 for (unsigned int j = 0; j < dim; ++j)
349 data.contravariant[point][i][j] = result[i][j];
350 }
351 }
352
353 if (update_flags & update_covariant_transformation)
354 if (cell_similarity != CellSimilarity::translation)
355 {
356 for (unsigned int point = 0; point < n_q_points; ++point)
357 {
358 data.covariant[point] =
359 (data.contravariant[point]).covariant_form();
360 }
361 }
362
363 if (update_flags & update_volume_elements)
364 if (cell_similarity != CellSimilarity::translation)
365 {
366 for (unsigned int point = 0; point < n_q_points; ++point)
367 data.volume_elements[point] =
368 data.contravariant[point].determinant();
369 }
370 }
371
378 template <int dim, int spacedim>
379 void
380 maybe_update_jacobian_grads(
381 const CellSimilarity::Similarity cell_similarity,
382 const typename QProjector<dim>::DataSetDescriptor data_set,
383 const typename ::MappingFE<dim, spacedim>::InternalData &data,
384 std::vector<DerivativeForm<2, dim, spacedim>> &jacobian_grads,
385 const unsigned int n_q_points)
386 {
387 const UpdateFlags update_flags = data.update_each;
388 if (update_flags & update_jacobian_grads)
389 {
390 AssertIndexRange(n_q_points, jacobian_grads.size() + 1);
391
392 if (cell_similarity != CellSimilarity::translation)
393 for (unsigned int point = 0; point < n_q_points; ++point)
394 {
395 const Tensor<2, dim> *second =
396 &data.second_derivative(point + data_set, 0);
397 double result[spacedim][dim][dim];
398 for (unsigned int i = 0; i < spacedim; ++i)
399 for (unsigned int j = 0; j < dim; ++j)
400 for (unsigned int l = 0; l < dim; ++l)
401 result[i][j][l] =
402 (second[0][j][l] * data.mapping_support_points[0][i]);
403 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
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[k][j][l] *
409 data.mapping_support_points[k][i]);
410
411 for (unsigned int i = 0; i < spacedim; ++i)
412 for (unsigned int j = 0; j < dim; ++j)
413 for (unsigned int l = 0; l < dim; ++l)
414 jacobian_grads[point][i][j][l] = result[i][j][l];
415 }
416 }
417 }
418
425 template <int dim, int spacedim>
426 void
427 maybe_update_jacobian_pushed_forward_grads(
428 const CellSimilarity::Similarity cell_similarity,
429 const typename QProjector<dim>::DataSetDescriptor data_set,
430 const typename ::MappingFE<dim, spacedim>::InternalData &data,
431 std::vector<Tensor<3, spacedim>> &jacobian_pushed_forward_grads,
432 const unsigned int n_q_points)
433 {
434 const UpdateFlags update_flags = data.update_each;
435 if (update_flags & update_jacobian_pushed_forward_grads)
436 {
438 jacobian_pushed_forward_grads.size() + 1);
439
440 if (cell_similarity != CellSimilarity::translation)
441 {
442 double tmp[spacedim][spacedim][spacedim];
443 for (unsigned int point = 0; point < n_q_points; ++point)
444 {
445 const Tensor<2, dim> *second =
446 &data.second_derivative(point + data_set, 0);
447 double result[spacedim][dim][dim];
448 for (unsigned int i = 0; i < spacedim; ++i)
449 for (unsigned int j = 0; j < dim; ++j)
450 for (unsigned int l = 0; l < dim; ++l)
451 result[i][j][l] = (second[0][j][l] *
452 data.mapping_support_points[0][i]);
453 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
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] +=
458 (second[k][j][l] *
459 data.mapping_support_points[k][i]);
460
461 // first push forward the j-components
462 for (unsigned int i = 0; i < spacedim; ++i)
463 for (unsigned int j = 0; j < spacedim; ++j)
464 for (unsigned int l = 0; l < dim; ++l)
465 {
466 tmp[i][j][l] =
467 result[i][0][l] * data.covariant[point][j][0];
468 for (unsigned int jr = 1; jr < dim; ++jr)
469 {
470 tmp[i][j][l] += result[i][jr][l] *
471 data.covariant[point][j][jr];
472 }
473 }
474
475 // now, pushing forward the l-components
476 for (unsigned int i = 0; i < spacedim; ++i)
477 for (unsigned int j = 0; j < spacedim; ++j)
478 for (unsigned int l = 0; l < spacedim; ++l)
479 {
480 jacobian_pushed_forward_grads[point][i][j][l] =
481 tmp[i][j][0] * data.covariant[point][l][0];
482 for (unsigned int lr = 1; lr < dim; ++lr)
483 {
484 jacobian_pushed_forward_grads[point][i][j][l] +=
485 tmp[i][j][lr] * data.covariant[point][l][lr];
486 }
487 }
488 }
489 }
490 }
491 }
492
499 template <int dim, int spacedim>
500 void
501 maybe_update_jacobian_2nd_derivatives(
502 const CellSimilarity::Similarity cell_similarity,
503 const typename QProjector<dim>::DataSetDescriptor data_set,
504 const typename ::MappingFE<dim, spacedim>::InternalData &data,
505 std::vector<DerivativeForm<3, dim, spacedim>> &jacobian_2nd_derivatives,
506 const unsigned int n_q_points)
507 {
508 const UpdateFlags update_flags = data.update_each;
509 if (update_flags & update_jacobian_2nd_derivatives)
510 {
511 AssertIndexRange(n_q_points, jacobian_2nd_derivatives.size() + 1);
512
513 if (cell_similarity != CellSimilarity::translation)
514 {
515 for (unsigned int point = 0; point < n_q_points; ++point)
516 {
517 const Tensor<3, dim> *third =
518 &data.third_derivative(point + data_set, 0);
519 double result[spacedim][dim][dim][dim];
520 for (unsigned int i = 0; i < spacedim; ++i)
521 for (unsigned int j = 0; j < dim; ++j)
522 for (unsigned int l = 0; l < dim; ++l)
523 for (unsigned int m = 0; m < dim; ++m)
524 result[i][j][l][m] =
525 (third[0][j][l][m] *
526 data.mapping_support_points[0][i]);
527 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
528 for (unsigned int i = 0; i < spacedim; ++i)
529 for (unsigned int j = 0; j < dim; ++j)
530 for (unsigned int l = 0; l < dim; ++l)
531 for (unsigned int m = 0; m < dim; ++m)
532 result[i][j][l][m] +=
533 (third[k][j][l][m] *
534 data.mapping_support_points[k][i]);
535
536 for (unsigned int i = 0; i < spacedim; ++i)
537 for (unsigned int j = 0; j < dim; ++j)
538 for (unsigned int l = 0; l < dim; ++l)
539 for (unsigned int m = 0; m < dim; ++m)
540 jacobian_2nd_derivatives[point][i][j][l][m] =
541 result[i][j][l][m];
542 }
543 }
544 }
545 }
546
554 template <int dim, int spacedim>
555 void
556 maybe_update_jacobian_pushed_forward_2nd_derivatives(
557 const CellSimilarity::Similarity cell_similarity,
558 const typename QProjector<dim>::DataSetDescriptor data_set,
559 const typename ::MappingFE<dim, spacedim>::InternalData &data,
560 std::vector<Tensor<4, spacedim>>
561 &jacobian_pushed_forward_2nd_derivatives,
562 const unsigned int n_q_points)
563 {
564 const UpdateFlags update_flags = data.update_each;
566 {
568 jacobian_pushed_forward_2nd_derivatives.size() +
569 1);
570
571 if (cell_similarity != CellSimilarity::translation)
572 {
573 double tmp[spacedim][spacedim][spacedim][spacedim];
574 for (unsigned int point = 0; point < n_q_points; ++point)
575 {
576 const Tensor<3, dim> *third =
577 &data.third_derivative(point + data_set, 0);
578 double result[spacedim][dim][dim][dim];
579 for (unsigned int i = 0; i < spacedim; ++i)
580 for (unsigned int j = 0; j < dim; ++j)
581 for (unsigned int l = 0; l < dim; ++l)
582 for (unsigned int m = 0; m < dim; ++m)
583 result[i][j][l][m] =
584 (third[0][j][l][m] *
585 data.mapping_support_points[0][i]);
586 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
587 for (unsigned int i = 0; i < spacedim; ++i)
588 for (unsigned int j = 0; j < dim; ++j)
589 for (unsigned int l = 0; l < dim; ++l)
590 for (unsigned int m = 0; m < dim; ++m)
591 result[i][j][l][m] +=
592 (third[k][j][l][m] *
593 data.mapping_support_points[k][i]);
594
595 // push forward the j-coordinate
596 for (unsigned int i = 0; i < spacedim; ++i)
597 for (unsigned int j = 0; j < spacedim; ++j)
598 for (unsigned int l = 0; l < dim; ++l)
599 for (unsigned int m = 0; m < dim; ++m)
600 {
601 jacobian_pushed_forward_2nd_derivatives
602 [point][i][j][l][m] =
603 result[i][0][l][m] *
604 data.covariant[point][j][0];
605 for (unsigned int jr = 1; jr < dim; ++jr)
606 jacobian_pushed_forward_2nd_derivatives[point]
607 [i][j][l]
608 [m] +=
609 result[i][jr][l][m] *
610 data.covariant[point][j][jr];
611 }
612
613 // push forward the l-coordinate
614 for (unsigned int i = 0; i < spacedim; ++i)
615 for (unsigned int j = 0; j < spacedim; ++j)
616 for (unsigned int l = 0; l < spacedim; ++l)
617 for (unsigned int m = 0; m < dim; ++m)
618 {
619 tmp[i][j][l][m] =
620 jacobian_pushed_forward_2nd_derivatives[point]
621 [i][j][0]
622 [m] *
623 data.covariant[point][l][0];
624 for (unsigned int lr = 1; lr < dim; ++lr)
625 tmp[i][j][l][m] +=
626 jacobian_pushed_forward_2nd_derivatives
627 [point][i][j][lr][m] *
628 data.covariant[point][l][lr];
629 }
630
631 // push forward the m-coordinate
632 for (unsigned int i = 0; i < spacedim; ++i)
633 for (unsigned int j = 0; j < spacedim; ++j)
634 for (unsigned int l = 0; l < spacedim; ++l)
635 for (unsigned int m = 0; m < spacedim; ++m)
636 {
637 jacobian_pushed_forward_2nd_derivatives
638 [point][i][j][l][m] =
639 tmp[i][j][l][0] * data.covariant[point][m][0];
640 for (unsigned int mr = 1; mr < dim; ++mr)
641 jacobian_pushed_forward_2nd_derivatives[point]
642 [i][j][l]
643 [m] +=
644 tmp[i][j][l][mr] *
645 data.covariant[point][m][mr];
646 }
647 }
648 }
649 }
650 }
651
658 template <int dim, int spacedim>
659 void
660 maybe_update_jacobian_3rd_derivatives(
661 const CellSimilarity::Similarity cell_similarity,
662 const typename QProjector<dim>::DataSetDescriptor data_set,
663 const typename ::MappingFE<dim, spacedim>::InternalData &data,
664 std::vector<DerivativeForm<4, dim, spacedim>> &jacobian_3rd_derivatives,
665 const unsigned int n_q_points)
666 {
667 const UpdateFlags update_flags = data.update_each;
668 if (update_flags & update_jacobian_3rd_derivatives)
669 {
670 AssertIndexRange(n_q_points, jacobian_3rd_derivatives.size() + 1);
671
672 if (cell_similarity != CellSimilarity::translation)
673 {
674 for (unsigned int point = 0; point < n_q_points; ++point)
675 {
676 const Tensor<4, dim> *fourth =
677 &data.fourth_derivative(point + data_set, 0);
678 double result[spacedim][dim][dim][dim][dim];
679 for (unsigned int i = 0; i < spacedim; ++i)
680 for (unsigned int j = 0; j < dim; ++j)
681 for (unsigned int l = 0; l < dim; ++l)
682 for (unsigned int m = 0; m < dim; ++m)
683 for (unsigned int n = 0; n < dim; ++n)
684 result[i][j][l][m][n] =
685 (fourth[0][j][l][m][n] *
686 data.mapping_support_points[0][i]);
687 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
688 for (unsigned int i = 0; i < spacedim; ++i)
689 for (unsigned int j = 0; j < dim; ++j)
690 for (unsigned int l = 0; l < dim; ++l)
691 for (unsigned int m = 0; m < dim; ++m)
692 for (unsigned int n = 0; n < dim; ++n)
693 result[i][j][l][m][n] +=
694 (fourth[k][j][l][m][n] *
695 data.mapping_support_points[k][i]);
696
697 for (unsigned int i = 0; i < spacedim; ++i)
698 for (unsigned int j = 0; j < dim; ++j)
699 for (unsigned int l = 0; l < dim; ++l)
700 for (unsigned int m = 0; m < dim; ++m)
701 for (unsigned int n = 0; n < dim; ++n)
702 jacobian_3rd_derivatives[point][i][j][l][m][n] =
703 result[i][j][l][m][n];
704 }
705 }
706 }
707 }
708
716 template <int dim, int spacedim>
717 void
718 maybe_update_jacobian_pushed_forward_3rd_derivatives(
719 const CellSimilarity::Similarity cell_similarity,
720 const typename QProjector<dim>::DataSetDescriptor data_set,
721 const typename ::MappingFE<dim, spacedim>::InternalData &data,
722 std::vector<Tensor<5, spacedim>>
723 &jacobian_pushed_forward_3rd_derivatives,
724 const unsigned int n_q_points)
725 {
726 const UpdateFlags update_flags = data.update_each;
728 {
730 jacobian_pushed_forward_3rd_derivatives.size() +
731 1);
732
733 if (cell_similarity != CellSimilarity::translation)
734 {
735 double tmp[spacedim][spacedim][spacedim][spacedim][spacedim];
736 for (unsigned int point = 0; point < n_q_points; ++point)
737 {
738 const Tensor<4, dim> *fourth =
739 &data.fourth_derivative(point + data_set, 0);
740 double result[spacedim][dim][dim][dim][dim];
741 for (unsigned int i = 0; i < spacedim; ++i)
742 for (unsigned int j = 0; j < dim; ++j)
743 for (unsigned int l = 0; l < dim; ++l)
744 for (unsigned int m = 0; m < dim; ++m)
745 for (unsigned int n = 0; n < dim; ++n)
746 result[i][j][l][m][n] =
747 (fourth[0][j][l][m][n] *
748 data.mapping_support_points[0][i]);
749 for (unsigned int k = 1; k < data.n_shape_functions; ++k)
750 for (unsigned int i = 0; i < spacedim; ++i)
751 for (unsigned int j = 0; j < dim; ++j)
752 for (unsigned int l = 0; l < dim; ++l)
753 for (unsigned int m = 0; m < dim; ++m)
754 for (unsigned int n = 0; n < dim; ++n)
755 result[i][j][l][m][n] +=
756 (fourth[k][j][l][m][n] *
757 data.mapping_support_points[k][i]);
758
759 // push-forward the j-coordinate
760 for (unsigned int i = 0; i < spacedim; ++i)
761 for (unsigned int j = 0; j < spacedim; ++j)
762 for (unsigned int l = 0; l < dim; ++l)
763 for (unsigned int m = 0; m < dim; ++m)
764 for (unsigned int n = 0; n < dim; ++n)
765 {
766 tmp[i][j][l][m][n] =
767 result[i][0][l][m][n] *
768 data.covariant[point][j][0];
769 for (unsigned int jr = 1; jr < dim; ++jr)
770 tmp[i][j][l][m][n] +=
771 result[i][jr][l][m][n] *
772 data.covariant[point][j][jr];
773 }
774
775 // push-forward the l-coordinate
776 for (unsigned int i = 0; i < spacedim; ++i)
777 for (unsigned int j = 0; j < spacedim; ++j)
778 for (unsigned int l = 0; l < spacedim; ++l)
779 for (unsigned int m = 0; m < dim; ++m)
780 for (unsigned int n = 0; n < dim; ++n)
781 {
782 jacobian_pushed_forward_3rd_derivatives
783 [point][i][j][l][m][n] =
784 tmp[i][j][0][m][n] *
785 data.covariant[point][l][0];
786 for (unsigned int lr = 1; lr < dim; ++lr)
787 jacobian_pushed_forward_3rd_derivatives
788 [point][i][j][l][m][n] +=
789 tmp[i][j][lr][m][n] *
790 data.covariant[point][l][lr];
791 }
792
793 // push-forward the m-coordinate
794 for (unsigned int i = 0; i < spacedim; ++i)
795 for (unsigned int j = 0; j < spacedim; ++j)
796 for (unsigned int l = 0; l < spacedim; ++l)
797 for (unsigned int m = 0; m < spacedim; ++m)
798 for (unsigned int n = 0; n < dim; ++n)
799 {
800 tmp[i][j][l][m][n] =
801 jacobian_pushed_forward_3rd_derivatives
802 [point][i][j][l][0][n] *
803 data.covariant[point][m][0];
804 for (unsigned int mr = 1; mr < dim; ++mr)
805 tmp[i][j][l][m][n] +=
806 jacobian_pushed_forward_3rd_derivatives
807 [point][i][j][l][mr][n] *
808 data.covariant[point][m][mr];
809 }
810
811 // push-forward the n-coordinate
812 for (unsigned int i = 0; i < spacedim; ++i)
813 for (unsigned int j = 0; j < spacedim; ++j)
814 for (unsigned int l = 0; l < spacedim; ++l)
815 for (unsigned int m = 0; m < spacedim; ++m)
816 for (unsigned int n = 0; n < spacedim; ++n)
817 {
818 jacobian_pushed_forward_3rd_derivatives
819 [point][i][j][l][m][n] =
820 tmp[i][j][l][m][0] *
821 data.covariant[point][n][0];
822 for (unsigned int nr = 1; nr < dim; ++nr)
823 jacobian_pushed_forward_3rd_derivatives
824 [point][i][j][l][m][n] +=
825 tmp[i][j][l][m][nr] *
826 data.covariant[point][n][nr];
827 }
828 }
829 }
830 }
831 }
832 } // namespace
833 } // namespace MappingFEImplementation
834} // namespace internal
835
836
837
838template <int dim, int spacedim>
840 : fe(fe.clone())
841 , polynomial_degree(fe.tensor_degree())
842{
844 ExcMessage("It only makes sense to create polynomial mappings "
845 "with a polynomial degree greater or equal to one."));
846 Assert(fe.n_components() == 1, ExcNotImplemented());
847
848 Assert(fe.has_support_points(), ExcNotImplemented());
849
850 const auto &mapping_support_points = fe.get_unit_support_points();
851
852 const auto reference_cell = fe.reference_cell();
853
854 const unsigned int n_points = mapping_support_points.size();
855 const unsigned int n_shape_functions = reference_cell.n_vertices();
856
858 Table<2, double>(n_points, n_shape_functions);
859
860 for (unsigned int point = 0; point < n_points; ++point)
861 for (unsigned int i = 0; i < n_shape_functions; ++i)
863 reference_cell.d_linear_shape_function(mapping_support_points[point],
864 i);
865}
866
867
868
869template <int dim, int spacedim>
875
876
877
878template <int dim, int spacedim>
879std::unique_ptr<Mapping<dim, spacedim>>
881{
882 return std::make_unique<MappingFE<dim, spacedim>>(*this);
883}
884
885
886
887template <int dim, int spacedim>
888unsigned int
893
894
895
896template <int dim, int spacedim>
900 const Point<dim> &p) const
901{
902 const auto support_points = this->compute_mapping_support_points(cell);
903
904 Point<spacedim> mapped_point;
905
906 for (unsigned int i = 0; i < this->fe->n_dofs_per_cell(); ++i)
907 mapped_point += support_points[i] * this->fe->shape_value(i, p);
908
909 return mapped_point;
910}
911
912
913
914template <int dim, int spacedim>
918 const Point<spacedim> &p) const
919{
920 const auto support_points = this->compute_mapping_support_points(cell);
921
922 const double eps = 1.e-12 * cell->diameter();
923 const unsigned int loop_limit = 10;
924
925 Point<dim> p_unit;
926
927 unsigned int loop = 0;
928
929 // This loop solves the following problem:
930 // grad_F^T residual + (grad_F^T grad_F + grad_F^T hess_F^T dp) dp = 0
931 // where the term
932 // (grad_F^T hess_F dp) is approximated by (-hess_F * residual)
933 // This is basically a second order approximation of Newton method, where the
934 // Jacobian is corrected with a higher order term coming from the hessian.
935 do
936 {
937 Point<spacedim> mapped_point;
938
939 // Transpose of the gradient map
942
943 for (unsigned int i = 0; i < this->fe->n_dofs_per_cell(); ++i)
944 {
945 mapped_point += support_points[i] * this->fe->shape_value(i, p_unit);
946 const auto grad_F_i = this->fe->shape_grad(i, p_unit);
947 const auto hessian_F_i = this->fe->shape_grad_grad(i, p_unit);
948 for (unsigned int j = 0; j < dim; ++j)
949 {
950 grad_FT[j] += grad_F_i[j] * support_points[i];
951 for (unsigned int l = 0; l < dim; ++l)
952 hess_FT[j][l] += hessian_F_i[j][l] * support_points[i];
953 }
954 }
955
956 // Residual
957 const auto residual = p - mapped_point;
958 // Project the residual on the reference coordinate system
959 // to compute the error, and to filter components orthogonal to the
960 // manifold, and compute a 2nd order correction of the metric tensor
961 const auto grad_FT_residual = apply_transformation(grad_FT, residual);
962
963 // Do not invert nor compute the metric if not necessary.
964 if (grad_FT_residual.norm() <= eps)
965 break;
966
967 // Now compute the (corrected) metric tensor
968 Tensor<2, dim> corrected_metric_tensor;
969 for (unsigned int j = 0; j < dim; ++j)
970 for (unsigned int l = 0; l < dim; ++l)
971 corrected_metric_tensor[j][l] =
972 -grad_FT[j] * grad_FT[l] + hess_FT[j][l] * residual;
973
974 // And compute the update
975 const auto g_inverse = invert(corrected_metric_tensor);
976 p_unit -= Point<dim>(g_inverse * grad_FT_residual);
977
978 ++loop;
979 }
980 while (loop < loop_limit);
981
982 // Here we check that in the last execution of while the first
983 // condition was already wrong, meaning the residual was below
984 // eps. Only if the first condition failed, loop will have been
985 // increased and tested, and thus have reached the limit.
986 AssertThrow(loop < loop_limit,
988
989 return p_unit;
990}
991
992
993
994template <int dim, int spacedim>
997{
998 // add flags if the respective quantities are necessary to compute
999 // what we need. note that some flags appear in both the conditions
1000 // and in subsequent set operations. this leads to some circular
1001 // logic. the only way to treat this is to iterate. since there are
1002 // 5 if-clauses in the loop, it will take at most 5 iterations to
1003 // converge. do them:
1004 UpdateFlags out = in;
1005 for (unsigned int i = 0; i < 5; ++i)
1006 {
1007 // The following is a little incorrect:
1008 // If not applied on a face,
1009 // update_boundary_forms does not
1010 // make sense. On the other hand,
1011 // it is necessary on a
1012 // face. Currently,
1013 // update_boundary_forms is simply
1014 // ignored for the interior of a
1015 // cell.
1017 out |= update_boundary_forms;
1018
1023
1024 if (out &
1029
1030 // The contravariant transformation is used in the Piola
1031 // transformation, which requires the determinant of the Jacobi
1032 // matrix of the transformation. Because we have no way of
1033 // knowing here whether the finite element wants to use the
1034 // contravariant or the Piola transforms, we add the JxW values
1035 // to the list of flags to be updated for each cell.
1038
1039 // the same is true when computing normal vectors: they require
1040 // the determinant of the Jacobian
1041 if (out & update_normal_vectors)
1043 }
1044
1045 return out;
1046}
1047
1048
1049
1050template <int dim, int spacedim>
1051std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1052MappingFE<dim, spacedim>::get_data(const UpdateFlags update_flags,
1053 const Quadrature<dim> &q) const
1054{
1055 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1056 std::make_unique<InternalData>(*this->fe);
1057 data_ptr->reinit(this->requires_update_flags(update_flags), q);
1058 return data_ptr;
1059}
1060
1061
1062
1063template <int dim, int spacedim>
1064std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1066 const UpdateFlags update_flags,
1067 const hp::QCollection<dim - 1> &quadrature) const
1068{
1069 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1070 std::make_unique<InternalData>(*this->fe);
1071 auto &data = dynamic_cast<InternalData &>(*data_ptr);
1072 data.initialize_face(this->requires_update_flags(update_flags),
1074 this->fe->reference_cell(), quadrature),
1075 quadrature.max_n_quadrature_points());
1076
1077 return data_ptr;
1078}
1079
1080
1081
1082template <int dim, int spacedim>
1083std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
1085 const UpdateFlags update_flags,
1086 const Quadrature<dim - 1> &quadrature) const
1087{
1088 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
1089 std::make_unique<InternalData>(*this->fe);
1090 auto &data = dynamic_cast<InternalData &>(*data_ptr);
1091 data.initialize_face(this->requires_update_flags(update_flags),
1093 this->fe->reference_cell(), quadrature),
1094 quadrature.size());
1095
1096 return data_ptr;
1097}
1098
1099
1100
1101template <int dim, int spacedim>
1105 const CellSimilarity::Similarity cell_similarity,
1106 const Quadrature<dim> &quadrature,
1107 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1109 &output_data) const
1110{
1111 // ensure that the following static_cast is really correct:
1112 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
1114 const InternalData &data = static_cast<const InternalData &>(internal_data);
1115
1116 const unsigned int n_q_points = quadrature.size();
1117
1118 // recompute the support points of the transformation of this
1119 // cell. we tried to be clever here in an earlier version of the
1120 // library by checking whether the cell is the same as the one we
1121 // had visited last, but it turns out to be difficult to determine
1122 // that because a cell for the purposes of a mapping is
1123 // characterized not just by its (triangulation, level, index)
1124 // triple, but also by the locations of its vertices, the manifold
1125 // object attached to the cell and all of its bounding faces/edges,
1126 // etc. to reliably test that the "cell" we are on is, therefore,
1127 // not easily done
1128 const auto support_points = this->compute_mapping_support_points(cell);
1129 data.mapping_support_points.assign(support_points.begin(),
1130 support_points.end());
1131
1132 // if the order of the mapping is greater than 1, then do not reuse any cell
1133 // similarity information. This is necessary because the cell similarity
1134 // value is computed with just cell vertices and does not take into account
1135 // cell curvature.
1136 const CellSimilarity::Similarity computed_cell_similarity =
1137 (polynomial_degree == 1 ? cell_similarity : CellSimilarity::none);
1138
1139 internal::MappingFEImplementation::maybe_compute_q_points<dim, spacedim>(
1141 data,
1142 output_data.quadrature_points,
1143 n_q_points);
1144
1145 internal::MappingFEImplementation::maybe_update_Jacobians<dim, spacedim>(
1146 computed_cell_similarity,
1148 data,
1149 n_q_points);
1150
1151 internal::MappingFEImplementation::maybe_update_jacobian_grads<dim, spacedim>(
1152 computed_cell_similarity,
1154 data,
1155 output_data.jacobian_grads,
1156 n_q_points);
1157
1158 internal::MappingFEImplementation::maybe_update_jacobian_pushed_forward_grads<
1159 dim,
1160 spacedim>(computed_cell_similarity,
1162 data,
1164 n_q_points);
1165
1166 internal::MappingFEImplementation::maybe_update_jacobian_2nd_derivatives<
1167 dim,
1168 spacedim>(computed_cell_similarity,
1170 data,
1171 output_data.jacobian_2nd_derivatives,
1172 n_q_points);
1173
1174 internal::MappingFEImplementation::
1175 maybe_update_jacobian_pushed_forward_2nd_derivatives<dim, spacedim>(
1176 computed_cell_similarity,
1178 data,
1180 n_q_points);
1181
1182 internal::MappingFEImplementation::maybe_update_jacobian_3rd_derivatives<
1183 dim,
1184 spacedim>(computed_cell_similarity,
1186 data,
1187 output_data.jacobian_3rd_derivatives,
1188 n_q_points);
1189
1190 internal::MappingFEImplementation::
1191 maybe_update_jacobian_pushed_forward_3rd_derivatives<dim, spacedim>(
1192 computed_cell_similarity,
1194 data,
1196 n_q_points);
1197
1198 const UpdateFlags update_flags = data.update_each;
1199 const std::vector<double> &weights = quadrature.get_weights();
1200
1201 // Multiply quadrature weights by absolute value of Jacobian determinants or
1202 // the area element g=sqrt(DX^t DX) in case of codim > 0
1203
1204 if (update_flags & (update_normal_vectors | update_JxW_values))
1205 {
1206 AssertDimension(output_data.JxW_values.size(), n_q_points);
1207
1208 Assert(!(update_flags & update_normal_vectors) ||
1209 (output_data.normal_vectors.size() == n_q_points),
1210 ExcDimensionMismatch(output_data.normal_vectors.size(),
1211 n_q_points));
1212
1213
1214 if (computed_cell_similarity != CellSimilarity::translation)
1215 for (unsigned int point = 0; point < n_q_points; ++point)
1216 {
1217 if (dim == spacedim)
1218 {
1219 const double det = data.contravariant[point].determinant();
1220
1221 // check for distorted cells.
1222
1223 // TODO: this allows for anisotropies of up to 1e6 in 3d and
1224 // 1e12 in 2d. might want to find a finer
1225 // (dimension-independent) criterion
1226 Assert(det >
1228 cell->diameter() / std::sqrt(double(dim))),
1230 cell->center(), det, point)));
1231
1232 output_data.JxW_values[point] = weights[point] * det;
1233 }
1234 // if dim==spacedim, then there is no cell normal to
1235 // compute. since this is for FEValues (and not FEFaceValues),
1236 // there are also no face normals to compute
1237 else // codim>0 case
1238 {
1239 Tensor<1, spacedim> DX_t[dim];
1240 for (unsigned int i = 0; i < spacedim; ++i)
1241 for (unsigned int j = 0; j < dim; ++j)
1242 DX_t[j][i] = data.contravariant[point][i][j];
1243
1244 Tensor<2, dim> G; // First fundamental form
1245 for (unsigned int i = 0; i < dim; ++i)
1246 for (unsigned int j = 0; j < dim; ++j)
1247 G[i][j] = DX_t[i] * DX_t[j];
1248
1249 output_data.JxW_values[point] =
1250 std::sqrt(determinant(G)) * weights[point];
1251
1252 if (computed_cell_similarity ==
1254 {
1255 // we only need to flip the normal
1256 if (update_flags & update_normal_vectors)
1257 output_data.normal_vectors[point] *= -1.;
1258 }
1259 else
1260 {
1261 if (update_flags & update_normal_vectors)
1262 {
1263 Assert(spacedim == dim + 1,
1264 ExcMessage(
1265 "There is no (unique) cell normal for " +
1267 "-dimensional cells in " +
1268 Utilities::int_to_string(spacedim) +
1269 "-dimensional space. This only works if the "
1270 "space dimension is one greater than the "
1271 "dimensionality of the mesh cells."));
1272
1273 if (dim == 1)
1274 output_data.normal_vectors[point] =
1275 cross_product_2d(-DX_t[0]);
1276 else // dim == 2
1277 output_data.normal_vectors[point] =
1278 cross_product_3d(DX_t[0], DX_t[1]);
1279
1280 output_data.normal_vectors[point] /=
1281 output_data.normal_vectors[point].norm();
1282
1283 if (cell->direction_flag() == false)
1284 output_data.normal_vectors[point] *= -1.;
1285 }
1286 }
1287 } // codim>0 case
1288 }
1289 }
1290
1291
1292
1293 // copy values from InternalData to vector given by reference
1294 if (update_flags & update_jacobians)
1295 {
1296 AssertDimension(output_data.jacobians.size(), n_q_points);
1297 if (computed_cell_similarity != CellSimilarity::translation)
1298 for (unsigned int point = 0; point < n_q_points; ++point)
1299 output_data.jacobians[point] = data.contravariant[point];
1300 }
1301
1302 // copy values from InternalData to vector given by reference
1303 if (update_flags & update_inverse_jacobians)
1304 {
1305 AssertDimension(output_data.inverse_jacobians.size(), n_q_points);
1306 if (computed_cell_similarity != CellSimilarity::translation)
1307 for (unsigned int point = 0; point < n_q_points; ++point)
1308 output_data.inverse_jacobians[point] =
1309 data.covariant[point].transpose();
1310 }
1311
1312 return computed_cell_similarity;
1313}
1314
1315
1316
1317namespace internal
1318{
1319 namespace MappingFEImplementation
1320 {
1321 namespace
1322 {
1333 template <int dim, int spacedim>
1334 void
1335 maybe_compute_face_data(
1336 const ::MappingFE<dim, spacedim> &mapping,
1337 const typename ::Triangulation<dim, spacedim>::cell_iterator
1338 &cell,
1339 const unsigned int face_no,
1340 const unsigned int subface_no,
1341 const unsigned int n_q_points,
1342 const typename QProjector<dim>::DataSetDescriptor data_set,
1343 const typename ::MappingFE<dim, spacedim>::InternalData &data,
1345 &output_data)
1346 {
1347 const UpdateFlags update_flags = data.update_each;
1348
1349 if (update_flags &
1352 {
1353 if (update_flags & update_boundary_forms)
1355 output_data.boundary_forms.size() + 1);
1356 if (update_flags & update_normal_vectors)
1358 output_data.normal_vectors.size() + 1);
1359 if (update_flags & update_JxW_values)
1360 AssertIndexRange(n_q_points, output_data.JxW_values.size() + 1);
1361
1362 Assert(data.aux.size() + 1 >= dim, ExcInternalError());
1363
1364 // first compute some common data that is used for evaluating
1365 // all of the flags below
1366
1367 // map the unit tangentials to the real cell. checking for
1368 // d!=dim-1 eliminates compiler warnings regarding unsigned int
1369 // expressions < 0.
1370 for (unsigned int d = 0; d != dim - 1; ++d)
1371 {
1372 Assert(face_no + cell->n_faces() * d <
1373 data.unit_tangentials.size(),
1375 Assert(
1376 data.aux[d].size() <=
1377 data.unit_tangentials[face_no + cell->n_faces() * d].size(),
1379
1380 mapping.transform(
1382 data.unit_tangentials[face_no + cell->n_faces() * d]),
1384 data,
1385 make_array_view(data.aux[d]));
1386 }
1387
1388 if (update_flags & update_boundary_forms)
1389 {
1390 // if dim==spacedim, we can use the unit tangentials to
1391 // compute the boundary form by simply taking the cross
1392 // product
1393 if (dim == spacedim)
1394 {
1395 for (unsigned int i = 0; i < n_q_points; ++i)
1396 switch (dim)
1397 {
1398 case 1:
1399 // in 1d, we don't have access to any of the
1400 // data.aux fields (because it has only dim-1
1401 // components), but we can still compute the
1402 // boundary form by simply looking at the number
1403 // of the face
1404 output_data.boundary_forms[i][0] =
1405 (face_no == 0 ? -1 : +1);
1406 break;
1407 case 2:
1408 output_data.boundary_forms[i] =
1409 cross_product_2d(data.aux[0][i]);
1410 break;
1411 case 3:
1412 output_data.boundary_forms[i] =
1413 cross_product_3d(data.aux[0][i], data.aux[1][i]);
1414 break;
1415 default:
1417 }
1418 }
1419 else //(dim < spacedim)
1420 {
1421 // in the codim-one case, the boundary form results from
1422 // the cross product of all the face tangential vectors
1423 // and the cell normal vector
1424 //
1425 // to compute the cell normal, use the same method used in
1426 // fill_fe_values for cells above
1427 AssertIndexRange(n_q_points, data.contravariant.size() + 1);
1428
1429 for (unsigned int point = 0; point < n_q_points; ++point)
1430 {
1431 if (dim == 1)
1432 {
1433 // J is a tangent vector
1434 output_data.boundary_forms[point] =
1435 data.contravariant[point].transpose()[0];
1436 output_data.boundary_forms[point] /=
1437 (face_no == 0 ? -1. : +1.) *
1438 output_data.boundary_forms[point].norm();
1439 }
1440
1441 if (dim == 2)
1442 {
1443 const DerivativeForm<1, spacedim, dim> DX_t =
1444 data.contravariant[point].transpose();
1445
1446 Tensor<1, spacedim> cell_normal =
1447 cross_product_3d(DX_t[0], DX_t[1]);
1448 cell_normal /= cell_normal.norm();
1449
1450 // then compute the face normal from the face
1451 // tangent and the cell normal:
1452 output_data.boundary_forms[point] =
1453 cross_product_3d(data.aux[0][point], cell_normal);
1454 }
1455 }
1456 }
1457 }
1458
1459 if (update_flags & update_JxW_values)
1460 for (unsigned int i = 0; i < n_q_points; ++i)
1461 {
1462 output_data.JxW_values[i] =
1463 output_data.boundary_forms[i].norm() *
1464 data.quadrature_weights[i + data_set];
1465
1466 if (subface_no != numbers::invalid_unsigned_int)
1467 {
1468 if (dim == 2)
1469 {
1470 const double area_ratio =
1471 1. / cell->reference_cell()
1472 .face_reference_cell(face_no)
1473 .n_isotropic_children();
1474 output_data.JxW_values[i] *= area_ratio;
1475 }
1476 else
1478 }
1479 }
1480
1481 if (update_flags & update_normal_vectors)
1482 for (unsigned int i = 0; i < n_q_points; ++i)
1483 output_data.normal_vectors[i] =
1484 Point<spacedim>(output_data.boundary_forms[i] /
1485 output_data.boundary_forms[i].norm());
1486
1487 if (update_flags & update_jacobians)
1488 for (unsigned int point = 0; point < n_q_points; ++point)
1489 output_data.jacobians[point] = data.contravariant[point];
1490
1491 if (update_flags & update_inverse_jacobians)
1492 for (unsigned int point = 0; point < n_q_points; ++point)
1493 output_data.inverse_jacobians[point] =
1494 data.covariant[point].transpose();
1495 }
1496 }
1497
1498
1505 template <int dim, int spacedim>
1506 void
1508 const ::MappingFE<dim, spacedim> &mapping,
1509 const typename ::Triangulation<dim, spacedim>::cell_iterator
1510 &cell,
1511 const unsigned int face_no,
1512 const unsigned int subface_no,
1513 const typename QProjector<dim>::DataSetDescriptor data_set,
1514 const Quadrature<dim - 1> &quadrature,
1515 const typename ::MappingFE<dim, spacedim>::InternalData &data,
1516 internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
1517 &output_data)
1518 {
1519 const unsigned int n_q_points = quadrature.size();
1520
1521 maybe_compute_q_points<dim, spacedim>(data_set,
1522 data,
1523 output_data.quadrature_points,
1524 n_q_points);
1525 maybe_update_Jacobians<dim, spacedim>(CellSimilarity::none,
1526 data_set,
1527 data,
1528 n_q_points);
1529 maybe_update_jacobian_grads<dim, spacedim>(CellSimilarity::none,
1530 data_set,
1531 data,
1532 output_data.jacobian_grads,
1533 n_q_points);
1534 maybe_update_jacobian_pushed_forward_grads<dim, spacedim>(
1536 data_set,
1537 data,
1539 n_q_points);
1540 maybe_update_jacobian_2nd_derivatives<dim, spacedim>(
1542 data_set,
1543 data,
1544 output_data.jacobian_2nd_derivatives,
1545 n_q_points);
1546 maybe_update_jacobian_pushed_forward_2nd_derivatives<dim, spacedim>(
1548 data_set,
1549 data,
1551 n_q_points);
1552 maybe_update_jacobian_3rd_derivatives<dim, spacedim>(
1554 data_set,
1555 data,
1556 output_data.jacobian_3rd_derivatives,
1557 n_q_points);
1558 maybe_update_jacobian_pushed_forward_3rd_derivatives<dim, spacedim>(
1560 data_set,
1561 data,
1563 n_q_points);
1564
1566 cell,
1567 face_no,
1568 subface_no,
1569 n_q_points,
1570 data_set,
1571 data,
1572 output_data);
1573 }
1574 } // namespace
1575 } // namespace MappingFEImplementation
1576} // namespace internal
1577
1578
1579
1580template <int dim, int spacedim>
1581void
1584 const unsigned int face_no,
1585 const hp::QCollection<dim - 1> &quadrature,
1586 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1588 &output_data) const
1589{
1590 // ensure that the following cast is really correct:
1591 Assert((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1593 const InternalData &data = static_cast<const InternalData &>(internal_data);
1594
1595 const auto support_points = this->compute_mapping_support_points(cell);
1596 data.mapping_support_points.assign(support_points.begin(),
1597 support_points.end());
1598
1599 internal::MappingFEImplementation::do_fill_fe_face_values(
1600 *this,
1601 cell,
1602 face_no,
1604 QProjector<dim>::DataSetDescriptor::face(this->fe->reference_cell(),
1605 face_no,
1607 face_no),
1608 quadrature),
1609 quadrature[quadrature.size() == 1 ? 0 : face_no],
1610 data,
1611 output_data);
1612}
1613
1614
1615
1616template <int dim, int spacedim>
1617void
1620 const unsigned int face_no,
1621 const unsigned int subface_no,
1622 const Quadrature<dim - 1> &quadrature,
1623 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
1625 &output_data) const
1626{
1627 // ensure that the following cast is really correct:
1628 Assert((dynamic_cast<const InternalData *>(&internal_data) != nullptr),
1630 const InternalData &data = static_cast<const InternalData &>(internal_data);
1631
1632 const auto support_points = this->compute_mapping_support_points(cell);
1633 data.mapping_support_points.assign(support_points.begin(),
1634 support_points.end());
1635
1636 internal::MappingFEImplementation::do_fill_fe_face_values(
1637 *this,
1638 cell,
1639 face_no,
1640 subface_no,
1641 QProjector<dim>::DataSetDescriptor::subface(this->fe->reference_cell(),
1642 face_no,
1643 subface_no,
1645 face_no),
1646 quadrature.size(),
1647 cell->subface_case(face_no)),
1648 quadrature,
1649 data,
1650 output_data);
1651}
1652
1653
1654
1655namespace internal
1656{
1657 namespace MappingFEImplementation
1658 {
1659 namespace
1660 {
1661 template <int dim, int spacedim, int rank>
1662 void
1663 transform_fields(
1664 const ArrayView<const Tensor<rank, dim>> &input,
1665 const MappingKind mapping_kind,
1666 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1667 const ArrayView<Tensor<rank, spacedim>> &output)
1668 {
1669 // In the case of wedges and pyramids, faces might have different
1670 // numbers of quadrature points on each face with the result
1671 // that input and output have different sizes, since input has
1672 // the correct size but the size of output is the maximum of
1673 // all possible sizes.
1674 AssertIndexRange(input.size(), output.size() + 1);
1675
1676 Assert(
1677 (dynamic_cast<
1678 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1679 &mapping_data) != nullptr),
1681 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1682 static_cast<
1683 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1684 mapping_data);
1685
1686 switch (mapping_kind)
1687 {
1689 {
1690 Assert(
1691 data.update_each & update_contravariant_transformation,
1693 "update_contravariant_transformation"));
1694
1695 for (unsigned int i = 0; i < input.size(); ++i)
1696 output[i] =
1697 apply_transformation(data.contravariant[i], input[i]);
1698
1699 return;
1700 }
1701
1702 case mapping_piola:
1703 {
1704 Assert(
1705 data.update_each & update_contravariant_transformation,
1707 "update_contravariant_transformation"));
1708 Assert(
1709 data.update_each & update_volume_elements,
1711 "update_volume_elements"));
1712 Assert(rank == 1, ExcMessage("Only for rank 1"));
1713 if (rank != 1)
1714 return;
1715
1716 for (unsigned int i = 0; i < input.size(); ++i)
1717 {
1718 output[i] =
1719 apply_transformation(data.contravariant[i], input[i]);
1720 output[i] /= data.volume_elements[i];
1721 }
1722 return;
1723 }
1724 // We still allow this operation as in the
1725 // reference cell Derivatives are Tensor
1726 // rather than DerivativeForm
1727 case mapping_covariant:
1728 {
1729 Assert(
1730 data.update_each & update_contravariant_transformation,
1732 "update_covariant_transformation"));
1733
1734 for (unsigned int i = 0; i < input.size(); ++i)
1735 output[i] = apply_transformation(data.covariant[i], input[i]);
1736
1737 return;
1738 }
1739
1740 default:
1742 }
1743 }
1744
1745
1746 template <int dim, int spacedim, int rank>
1747 void
1749 const ArrayView<const Tensor<rank, dim>> &input,
1750 const MappingKind mapping_kind,
1751 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1752 const ArrayView<Tensor<rank, spacedim>> &output)
1753 {
1754 AssertDimension(input.size(), output.size());
1755 Assert(
1756 (dynamic_cast<
1757 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1758 &mapping_data) != nullptr),
1760 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1761 static_cast<
1762 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1763 mapping_data);
1764
1765 switch (mapping_kind)
1766 {
1768 {
1769 Assert(
1770 data.update_each & update_covariant_transformation,
1772 "update_covariant_transformation"));
1773 Assert(
1774 data.update_each & update_contravariant_transformation,
1776 "update_contravariant_transformation"));
1777 Assert(rank == 2, ExcMessage("Only for rank 2"));
1778
1779 for (unsigned int i = 0; i < output.size(); ++i)
1780 {
1781 const DerivativeForm<1, spacedim, dim> A =
1782 apply_transformation(data.contravariant[i],
1783 transpose(input[i]));
1784 output[i] =
1785 apply_transformation(data.covariant[i], A.transpose());
1786 }
1787
1788 return;
1789 }
1790
1792 {
1793 Assert(
1794 data.update_each & update_covariant_transformation,
1796 "update_covariant_transformation"));
1797 Assert(rank == 2, ExcMessage("Only for rank 2"));
1798
1799 for (unsigned int i = 0; i < output.size(); ++i)
1800 {
1801 const DerivativeForm<1, spacedim, dim> A =
1802 apply_transformation(data.covariant[i],
1803 transpose(input[i]));
1804 output[i] =
1805 apply_transformation(data.covariant[i], A.transpose());
1806 }
1807
1808 return;
1809 }
1810
1812 {
1813 Assert(
1814 data.update_each & update_covariant_transformation,
1816 "update_covariant_transformation"));
1817 Assert(
1818 data.update_each & update_contravariant_transformation,
1820 "update_contravariant_transformation"));
1821 Assert(
1822 data.update_each & update_volume_elements,
1824 "update_volume_elements"));
1825 Assert(rank == 2, ExcMessage("Only for rank 2"));
1826
1827 for (unsigned int i = 0; i < output.size(); ++i)
1828 output[i] =
1829 internal::apply_piola_gradient(data.covariant[i],
1830 data.contravariant[i],
1831 data.volume_elements[i],
1832 input[i]);
1833
1834 return;
1835 }
1836
1837 default:
1839 }
1840 }
1841
1842
1843
1844 template <int dim, int spacedim>
1845 void
1847 const ArrayView<const Tensor<3, dim>> &input,
1848 const MappingKind mapping_kind,
1849 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1850 const ArrayView<Tensor<3, spacedim>> &output)
1851 {
1852 AssertDimension(input.size(), output.size());
1853 Assert(
1854 (dynamic_cast<
1855 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1856 &mapping_data) != nullptr),
1858 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1859 static_cast<
1860 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1861 mapping_data);
1862
1863 switch (mapping_kind)
1864 {
1866 {
1867 Assert(
1868 data.update_each & update_covariant_transformation,
1870 "update_covariant_transformation"));
1871 Assert(
1872 data.update_each & update_contravariant_transformation,
1874 "update_contravariant_transformation"));
1875
1876 for (unsigned int q = 0; q < output.size(); ++q)
1877 output[q] =
1878 internal::apply_contravariant_hessian(data.covariant[q],
1879 data.contravariant[q],
1880 input[q]);
1881
1882 return;
1883 }
1884
1886 {
1887 Assert(
1888 data.update_each & update_covariant_transformation,
1890 "update_covariant_transformation"));
1891
1892 for (unsigned int q = 0; q < output.size(); ++q)
1893 output[q] =
1894 internal::apply_covariant_hessian(data.covariant[q],
1895 input[q]);
1896
1897 return;
1898 }
1899
1901 {
1902 Assert(
1903 data.update_each & update_covariant_transformation,
1905 "update_covariant_transformation"));
1906 Assert(
1907 data.update_each & update_contravariant_transformation,
1909 "update_contravariant_transformation"));
1910 Assert(
1911 data.update_each & update_volume_elements,
1913 "update_volume_elements"));
1914
1915 for (unsigned int q = 0; q < output.size(); ++q)
1916 output[q] =
1917 internal::apply_piola_hessian(data.covariant[q],
1918 data.contravariant[q],
1919 data.volume_elements[q],
1920 input[q]);
1921
1922 return;
1923 }
1924
1925 default:
1927 }
1928 }
1929
1930
1931
1932 template <int dim, int spacedim, int rank>
1933 void
1935 const ArrayView<const DerivativeForm<rank, dim, spacedim>> &input,
1936 const MappingKind mapping_kind,
1937 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1938 const ArrayView<Tensor<rank + 1, spacedim>> &output)
1939 {
1940 AssertDimension(input.size(), output.size());
1941 Assert(
1942 (dynamic_cast<
1943 const typename ::MappingFE<dim, spacedim>::InternalData *>(
1944 &mapping_data) != nullptr),
1946 const typename ::MappingFE<dim, spacedim>::InternalData &data =
1947 static_cast<
1948 const typename ::MappingFE<dim, spacedim>::InternalData &>(
1949 mapping_data);
1950
1951 switch (mapping_kind)
1952 {
1953 case mapping_covariant:
1954 {
1955 Assert(
1956 data.update_each & update_contravariant_transformation,
1958 "update_covariant_transformation"));
1959
1960 for (unsigned int i = 0; i < output.size(); ++i)
1961 output[i] = apply_transformation(data.covariant[i], input[i]);
1962
1963 return;
1964 }
1965 default:
1967 }
1968 }
1969 } // namespace
1970 } // namespace MappingFEImplementation
1971} // namespace internal
1972
1973
1974
1975template <int dim, int spacedim>
1976void
1978 const ArrayView<const Tensor<1, dim>> &input,
1979 const MappingKind mapping_kind,
1980 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1981 const ArrayView<Tensor<1, spacedim>> &output) const
1982{
1983 internal::MappingFEImplementation::transform_fields(input,
1984 mapping_kind,
1985 mapping_data,
1986 output);
1987}
1988
1989
1990
1991template <int dim, int spacedim>
1992void
1994 const ArrayView<const DerivativeForm<1, dim, spacedim>> &input,
1995 const MappingKind mapping_kind,
1996 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1997 const ArrayView<Tensor<2, spacedim>> &output) const
1998{
1999 internal::MappingFEImplementation::transform_differential_forms(input,
2000 mapping_kind,
2001 mapping_data,
2002 output);
2003}
2004
2005
2006
2007template <int dim, int spacedim>
2008void
2010 const ArrayView<const Tensor<2, dim>> &input,
2011 const MappingKind mapping_kind,
2012 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2013 const ArrayView<Tensor<2, spacedim>> &output) const
2014{
2015 switch (mapping_kind)
2016 {
2018 internal::MappingFEImplementation::transform_fields(input,
2019 mapping_kind,
2020 mapping_data,
2021 output);
2022 return;
2023
2027 internal::MappingFEImplementation::transform_gradients(input,
2028 mapping_kind,
2029 mapping_data,
2030 output);
2031 return;
2032 default:
2034 }
2035}
2036
2037
2038
2039template <int dim, int spacedim>
2040void
2042 const ArrayView<const DerivativeForm<2, dim, spacedim>> &input,
2043 const MappingKind mapping_kind,
2044 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2045 const ArrayView<Tensor<3, spacedim>> &output) const
2046{
2047 AssertDimension(input.size(), output.size());
2048 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
2050 const InternalData &data = static_cast<const InternalData &>(mapping_data);
2051
2052 switch (mapping_kind)
2053 {
2055 {
2058 "update_covariant_transformation"));
2059
2060 for (unsigned int q = 0; q < output.size(); ++q)
2061 output[q] =
2063
2064 return;
2065 }
2066
2067 default:
2069 }
2070}
2071
2072
2073
2074template <int dim, int spacedim>
2075void
2077 const ArrayView<const Tensor<3, dim>> &input,
2078 const MappingKind mapping_kind,
2079 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
2080 const ArrayView<Tensor<3, spacedim>> &output) const
2081{
2082 switch (mapping_kind)
2083 {
2087 internal::MappingFEImplementation::transform_hessians(input,
2088 mapping_kind,
2089 mapping_data,
2090 output);
2091 return;
2092 default:
2094 }
2095}
2096
2097
2098
2099namespace
2100{
2101 template <int spacedim>
2102 bool
2103 check_all_manifold_ids_identical(
2105 {
2106 return true;
2107 }
2108
2109
2110
2111 template <int spacedim>
2112 bool
2113 check_all_manifold_ids_identical(
2115 {
2116 const auto m_id = cell->manifold_id();
2117
2118 for (const auto f : cell->face_indices())
2119 if (m_id != cell->face(f)->manifold_id())
2120 return false;
2121
2122 return true;
2123 }
2124
2125
2126
2127 template <int spacedim>
2128 bool
2129 check_all_manifold_ids_identical(
2131 {
2132 const auto m_id = cell->manifold_id();
2133
2134 for (const auto f : cell->face_indices())
2135 if (m_id != cell->face(f)->manifold_id())
2136 return false;
2137
2138 for (const auto l : cell->line_indices())
2139 if (m_id != cell->line(l)->manifold_id())
2140 return false;
2141
2142 return true;
2143 }
2144} // namespace
2145
2146
2147
2148template <int dim, int spacedim>
2149boost::container::small_vector<Point<spacedim>, 200>
2151 const typename Triangulation<dim, spacedim>::cell_iterator &cell) const
2152{
2153 boost::container::small_vector<Point<spacedim>, 200> points;
2156 vertices(cell->n_vertices());
2157 for (const unsigned int i : cell->vertex_indices())
2158 vertices[i] = cell->vertex(i);
2159
2160 points.resize(mapping_support_point_weights.size(0));
2161 if (check_all_manifold_ids_identical(cell))
2162 {
2163 // version 1) all geometric entities have the same manifold:
2165 vertices),
2167 ArrayView<Point<spacedim>>(points));
2168 }
2169 else
2170 {
2171 // version 1) geometric entities have different manifold
2172
2173 // helper function to compute mapped points on subentities
2174 // note[PM]: this function currently only uses the vertices
2175 // of cells to create new points on subentities; however,
2176 // one should use all bounding points to create new points
2177 // as in the case of MappingQ.
2178 const auto process = [&](const auto &manifold,
2179 const auto &indices,
2180 const unsigned n_points) {
2181 if ((indices.size() == 0) || (n_points == 0))
2182 return;
2183
2184 const unsigned int n_shape_functions =
2185 this->fe->reference_cell().n_vertices();
2186
2187 Table<2, double> mapping_support_point_weights_local(n_points,
2188 n_shape_functions);
2189 std::vector<Point<spacedim>> mapping_support_points_local(n_points);
2190
2191 for (unsigned int p = 0; p < n_points; ++p)
2192 for (unsigned int i = 0; i < n_shape_functions; ++i)
2193 mapping_support_point_weights_local(p, i) =
2195 indices[p + (indices.size() - n_points)], i);
2196
2197 manifold.get_new_points(ArrayView<const Point<spacedim>>(vertices),
2198 mapping_support_point_weights_local,
2200 mapping_support_points_local));
2201
2202 for (unsigned int p = 0; p < n_points; ++p)
2203 points[indices[p + (indices.size() - n_points)]] =
2204 mapping_support_points_local[p];
2205 };
2206
2207 // create dummy DoFHandler to extract indices on subobjects
2208 const auto &fe = *this->fe;
2210 GridGenerator::reference_cell(tria, fe.reference_cell());
2211 DoFHandler<dim, spacedim> dof_handler(tria);
2212 dof_handler.distribute_dofs(fe);
2213 const auto &cell_ref = dof_handler.begin_active();
2214
2215 std::vector<types::global_dof_index> indices;
2216
2217 // add vertices
2218 for (const unsigned int i : cell->vertex_indices())
2219 points[i] = vertices[i];
2220
2221 // process and add line support points
2222 for (unsigned int l = 0; l < cell_ref->n_lines(); ++l)
2223 {
2224 const auto accessor = cell_ref->line(l);
2225 indices.resize(fe.n_dofs_per_line() + 2 * fe.n_dofs_per_vertex());
2226 accessor->get_dof_indices(indices);
2227 process(cell->line(l)->get_manifold(), indices, fe.n_dofs_per_line());
2228 }
2229
2230 // process and add face support points
2231 if constexpr (dim >= 3)
2232 {
2233 for (unsigned int f = 0; f < cell_ref->n_faces(); ++f)
2234 {
2235 const auto accessor = cell_ref->face(f);
2236 indices.resize(fe.n_dofs_per_face());
2237 accessor->get_dof_indices(indices);
2238 process(cell->face(f)->get_manifold(),
2239 indices,
2240 fe.n_dofs_per_quad());
2241 }
2242 }
2243
2244 // process and add volume support points
2245 if constexpr (dim >= 2)
2246 {
2247 indices.resize(fe.n_dofs_per_cell());
2248 cell_ref->get_dof_indices(indices);
2249 process(cell->get_manifold(),
2250 indices,
2251 (dim == 2) ? fe.n_dofs_per_quad() : fe.n_dofs_per_hex());
2252 }
2253 }
2254
2255 return points;
2256}
2257
2258
2259
2260template <int dim, int spacedim>
2267
2268
2269
2270template <int dim, int spacedim>
2271bool
2273 const ReferenceCell<dim> &reference_cell) const
2274{
2275 Assert(dim == reference_cell.get_dimension(),
2276 ExcMessage("The dimension of your mapping (" +
2278 ") and the reference cell cell_type (" +
2279 Utilities::to_string(reference_cell.get_dimension()) +
2280 " ) do not agree."));
2281
2282 return fe->reference_cell() == reference_cell;
2283}
2284
2285
2286
2287//--------------------------- Explicit instantiations -----------------------
2288#include "fe/mapping_fe.inst"
2289
2290
*  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)
internal::SubfaceCase< dim > subface_case(const unsigned int face_no) const
double diameter(const Mapping< dim, spacedim > &mapping) const
TriaIterator< TriaAccessor< dim - 1, dim, spacedim > > face(const unsigned int i) const
bool direction_flag() const
void distribute_dofs(const FiniteElement< dim, spacedim > &fe)
active_cell_iterator begin_active(const unsigned int level=0) const
virtual void get_new_points(const ArrayView< const Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim > > new_points) const
const Tensor< 3, dim > & third_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
void initialize_face(const UpdateFlags update_flags, const Quadrature< dim > &quadrature, const unsigned int n_original_q_points)
std::vector< Point< spacedim > > mapping_support_points
Definition mapping_fe.h:372
const Tensor< 4, dim > & fourth_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
std::vector< std::vector< Tensor< 1, spacedim > > > aux
Definition mapping_fe.h:367
std::vector< Tensor< 3, dim > > shape_third_derivatives
Definition mapping_fe.h:309
std::vector< Tensor< 2, dim > > shape_second_derivatives
Definition mapping_fe.h:301
std::vector< Tensor< 4, dim > > shape_fourth_derivatives
Definition mapping_fe.h:317
void compute_shape_function_values(const std::vector< Point< dim > > &unit_points)
std::array< std::vector< Tensor< 1, dim > >, ReferenceCells::max_n_faces< dim >() *2 > unit_tangentials
Definition mapping_fe.h:327
std::vector< double > quadrature_weights
Definition mapping_fe.h:383
const FiniteElement< dim, spacedim > & fe
Definition mapping_fe.h:332
std::vector< DerivativeForm< 1, dim, spacedim > > contravariant
Definition mapping_fe.h:362
std::vector< DerivativeForm< 1, dim, spacedim > > covariant
Definition mapping_fe.h:353
const Tensor< 1, dim > & derivative(const unsigned int qpoint, const unsigned int shape_nr) const
std::vector< double > shape_values
Definition mapping_fe.h:286
std::vector< Tensor< 1, dim > > shape_derivatives
Definition mapping_fe.h:293
virtual std::size_t memory_consumption() const override
Definition mapping_fe.cc:60
const Tensor< 2, dim > & second_derivative(const unsigned int qpoint, const unsigned int shape_nr) const
InternalData(const FiniteElement< dim, spacedim > &fe)
Definition mapping_fe.cc:49
const unsigned int n_shape_functions
Definition mapping_fe.h:342
std::vector< double > volume_elements
Definition mapping_fe.h:378
const double & shape(const unsigned int qpoint, const unsigned int shape_nr) const
virtual void reinit(const UpdateFlags update_flags, const Quadrature< dim > &quadrature) override
Definition mapping_fe.cc:79
const unsigned int polynomial_degree
Definition mapping_fe.h:337
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:451
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:461
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:445
UpdateFlags update_each
Definition mapping.h:702
virtual std::size_t memory_consumption() const
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:333
static DataSetDescriptor cell()
Definition qprojector.h:515
static DataSetDescriptor subface(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const unsigned int subface_no, const bool face_orientation, const bool face_flip, const bool face_rotation, const unsigned int n_quadrature_points, const internal::SubfaceCase< dim > ref_case=internal::SubfaceCase< dim >::case_isotropic)
static DataSetDescriptor face(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const bool face_orientation, const bool face_flip, const bool face_rotation, const unsigned int n_quadrature_points)
static Quadrature< dim > project_to_all_faces(const ReferenceCell< dim > &reference_cell, const hp::QCollection< dim - 1 > &quadrature)
static Quadrature< dim > project_to_all_subfaces(const ReferenceCell< dim > &reference_cell, const SubQuadrature &quadrature)
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
std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices() const
const Manifold< dim, spacedim > & get_manifold() const
unsigned int n_vertices() const
Point< spacedim > center(const bool respect_manifold=false, const bool interpolate_from_surrounding=false) const
Point< spacedim > & vertex(const unsigned int i) const
typename::internal::TriangulationImplementation::Iterators< dim, spacedim >::line_iterator line(const unsigned int i) 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()
static ::ExceptionBase & ExcAccessToUninitializedField(std::string arg1)
static ::ExceptionBase & ExcDistortedMappedCell(Point< spacedim > arg1, double arg2, int arg3)
static ::ExceptionBase & ExcTransformationFailed()
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)
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1624
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
types::geometric_orientation combined_face_orientation(const unsigned int face) const
MappingQ< dim, spacedim > StaticMappingQ1< dim, spacedim >::mapping
Definition mapping_q1.h:101
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
constexpr unsigned int max_n_vertices()
constexpr T fixed_power(const T t)
Definition utilities.h:942
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:236
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
*  const unsigned int n_q_points
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
constexpr Tensor< 1, dim, Number > cross_product_2d(const Tensor< 1, dim, Number > &src)
Definition tensor.h:2639
constexpr Tensor< 1, dim, typename ProductType< Number1, Number2 >::type > cross_product_3d(const Tensor< 1, dim, Number1 > &src1, const Tensor< 1, dim, Number2 > &src2)
Definition tensor.h:2664