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