deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
mapping_cartesian.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) 2001 - 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
18#include <deal.II/base/tensor.h>
19
21
24
25#include <deal.II/grid/tria.h>
27
29
30#include <algorithm>
31#include <cmath>
32#include <memory>
33
34
36
39 "You are using MappingCartesian, but the incoming cell is not Cartesian.");
40
41
42
48template <typename CellType>
49bool
50is_cartesian(const CellType &cell)
51{
52 if (!cell->reference_cell().is_hyper_cube())
53 return false;
54
55 // The tolerances here are somewhat larger than the square of the machine
56 // epsilon, because we are going to compare the square of distances (to
57 // avoid computing square roots).
58 const double abs_tol = 1e-30;
59 const double rel_tol = 1e-28;
60 const auto bounding_box = cell->bounding_box();
61 const auto &bounding_vertices = bounding_box.get_boundary_points();
62 const auto bb_diagonal_length_squared =
63 bounding_vertices.first.distance_square(bounding_vertices.second);
64
65 for (const unsigned int v : cell->vertex_indices())
66 {
67 // Choose a tolerance that takes into account both that vertices far
68 // away from the origin have only a finite number of digits
69 // that are considered correct (an "absolute tolerance"), as well as that
70 // vertices are supposed to be close to the corresponding vertices of the
71 // bounding box (a tolerance that is "relative" to the size of the cell).
72 //
73 // We need to do it this way because when a vertex is far away from
74 // the origin, computing the difference between two vertices is subject
75 // to cancellation.
76 const double tolerance = std::max(abs_tol * cell->vertex(v).norm_square(),
77 rel_tol * bb_diagonal_length_squared);
78
79 if (cell->vertex(v).distance_square(bounding_box.vertex(v)) > tolerance)
80 return false;
81 }
82
83 return true;
84}
85
86
87
88template <int dim, int spacedim>
90 const Quadrature<dim> &q)
91 : cell_extents(numbers::signaling_nan<Tensor<1, dim>>())
92 , inverse_cell_extents(numbers::signaling_nan<Tensor<1, dim>>())
93 , volume_element(numbers::signaling_nan<double>())
94 , quadrature_points(q.get_points())
95{}
96
97
98
99template <int dim, int spacedim>
100void
102 const UpdateFlags update_flags,
103 const Quadrature<dim> &)
104{
105 // store the flags in the internal data object so we can access them
106 // in fill_fe_*_values(). use the transitive hull of the required
107 // flags
108 this->update_each = update_flags;
109}
110
111
112
113template <int dim, int spacedim>
114std::size_t
122
123
124
125template <int dim, int spacedim>
126bool
131
132
133
134template <int dim, int spacedim>
135bool
137 const ReferenceCell<dim> &reference_cell) const
138{
139 Assert(dim == reference_cell.get_dimension(),
140 ExcMessage("The dimension of your mapping (" +
142 ") and the reference cell cell_type (" +
143 Utilities::to_string(reference_cell.get_dimension()) +
144 " ) do not agree."));
145
146 return reference_cell.is_hyper_cube();
147}
148
149
150
151template <int dim, int spacedim>
154 const UpdateFlags in) const
155{
156 // this mapping is pretty simple in that it can basically compute
157 // every piece of information wanted by FEValues without requiring
158 // computing any other quantities. boundary forms are one exception
159 // since they can be computed from the normal vectors without much
160 // further ado
161 UpdateFlags out = in;
162 if (out & update_boundary_forms)
164
165 return out;
166}
167
168
169
170template <int dim, int spacedim>
171std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
173 const Quadrature<dim> &q) const
174{
175 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
176 std::make_unique<InternalData>();
177 data_ptr->reinit(requires_update_flags(update_flags), q);
178
179 return data_ptr;
180}
181
182
183
184template <int dim, int spacedim>
185std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
187 const UpdateFlags update_flags,
188 const hp::QCollection<dim - 1> &quadrature) const
189{
190 AssertDimension(quadrature.size(), 1);
191
192 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
193 std::make_unique<InternalData>(QProjector<dim>::project_to_all_faces(
194 ReferenceCells::get_hypercube<dim>(), quadrature[0]));
195 auto &data = dynamic_cast<InternalData &>(*data_ptr);
196
197 // verify that we have computed the transitive hull of the required
198 // flags and that FEValues has faithfully passed them on to us
199 Assert(update_flags == requires_update_flags(update_flags),
201
202 // store the flags in the internal data object so we can access them
203 // in fill_fe_*_values()
204 data.update_each = update_flags;
205
206 return data_ptr;
207}
208
209
210
211template <int dim, int spacedim>
212std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
214 const UpdateFlags update_flags,
215 const Quadrature<dim - 1> &quadrature) const
216{
217 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
218 std::make_unique<InternalData>(QProjector<dim>::project_to_all_subfaces(
219 ReferenceCells::get_hypercube<dim>(), quadrature));
220 auto &data = dynamic_cast<InternalData &>(*data_ptr);
221
222 // verify that we have computed the transitive hull of the required
223 // flags and that FEValues has faithfully passed them on to us
224 Assert(update_flags == requires_update_flags(update_flags),
226
227 // store the flags in the internal data object so we can access them
228 // in fill_fe_*_values()
229 data.update_each = update_flags;
230
231 return data_ptr;
232}
233
234
235
236template <int dim, int spacedim>
237void
240 const CellSimilarity::Similarity cell_similarity,
241 const InternalData &data) const
242{
243 // Compute start point and sizes along axes. The vertices to be looked at
244 // are 1, 2, 4 compared to the base vertex 0.
245 if (cell_similarity != CellSimilarity::translation)
246 {
247 const Point<dim> start = cell->vertex(0);
248 for (unsigned int d = 0; d < dim; ++d)
249 {
250 const double cell_extent_d = cell->vertex(1 << d)[d] - start[d];
251 data.cell_extents[d] = cell_extent_d;
252 Assert(cell_extent_d != 0.,
253 ExcMessage("Cell does not appear to be Cartesian!"));
254 data.inverse_cell_extents[d] = 1. / cell_extent_d;
255 }
256 }
257}
258
259
260
261namespace
262{
263 template <int dim>
264 void
265 transform_quadrature_points(
266 const Tensor<1, dim> first_vertex,
267 const Tensor<1, dim> cell_extents,
268 const ArrayView<const Point<dim>> &unit_quadrature_points,
269 const typename QProjector<dim>::DataSetDescriptor &offset,
270 std::vector<Point<dim>> &quadrature_points)
271 {
272 for (unsigned int i = 0; i < quadrature_points.size(); ++i)
273 {
274 quadrature_points[i] = first_vertex;
275 for (unsigned int d = 0; d < dim; ++d)
276 quadrature_points[i][d] +=
277 cell_extents[d] * unit_quadrature_points[i + offset][d];
278 }
279 }
280} // namespace
281
282
283
284template <int dim, int spacedim>
285void
288 const InternalData &data,
289 const ArrayView<const Point<dim>> &unit_quadrature_points,
290 std::vector<Point<dim>> &quadrature_points) const
291{
292 if (data.update_each & update_quadrature_points)
293 {
294 const auto offset = QProjector<dim>::DataSetDescriptor::cell();
295
296 transform_quadrature_points(cell->vertex(0),
297 data.cell_extents,
298 unit_quadrature_points,
299 offset,
300 quadrature_points);
301 }
302}
303
304
305
306template <int dim, int spacedim>
307void
310 const unsigned int face_no,
311 const InternalData &data,
312 std::vector<Point<dim>> &quadrature_points) const
313{
315
316 if (data.update_each & update_quadrature_points)
317 {
319 ReferenceCells::get_hypercube<dim>(),
320 face_no,
321 cell->combined_face_orientation(face_no),
322 quadrature_points.size());
323
324
325 transform_quadrature_points(cell->vertex(0),
326 data.cell_extents,
327 make_array_view(data.quadrature_points),
328 offset,
329 quadrature_points);
330 }
331}
332
333
334
335template <int dim, int spacedim>
336void
339 const unsigned int face_no,
340 const unsigned int sub_no,
341 const InternalData &data,
342 std::vector<Point<dim>> &quadrature_points) const
343{
346 if (cell->face(face_no)->has_children())
347 {
348 AssertIndexRange(sub_no, cell->face(face_no)->n_children());
349 }
350
351 if (data.update_each & update_quadrature_points)
352 {
354 ReferenceCells::get_hypercube<dim>(),
355 face_no,
356 sub_no,
357 cell->combined_face_orientation(face_no),
358 quadrature_points.size(),
359 cell->subface_case(face_no));
360
361 transform_quadrature_points(cell->vertex(0),
362 data.cell_extents,
363 make_array_view(data.quadrature_points),
364 offset,
365 quadrature_points);
366 }
367}
368
369
370
371template <int dim, int spacedim>
372void
374 const unsigned int face_no,
375 const InternalData &data,
376 std::vector<Tensor<1, dim>> &normal_vectors) const
377{
378 // compute normal vectors. All normals on a face have the same value.
379 if (data.update_each & update_normal_vectors)
380 {
382 std::fill(normal_vectors.begin(),
383 normal_vectors.end(),
384 ReferenceCells::get_hypercube<dim>().face_normal_vector(
385 face_no));
386 }
387}
388
389
390
391template <int dim, int spacedim>
392void
394 const InternalData &data,
395 const CellSimilarity::Similarity cell_similarity,
397 &output_data) const
398{
399 if (cell_similarity != CellSimilarity::translation)
400 {
401 if (data.update_each & update_jacobian_grads)
402 for (unsigned int i = 0; i < output_data.jacobian_grads.size(); ++i)
404
406 for (unsigned int i = 0;
407 i < output_data.jacobian_pushed_forward_grads.size();
408 ++i)
410
411 if (data.update_each & update_jacobian_2nd_derivatives)
412 for (unsigned int i = 0;
413 i < output_data.jacobian_2nd_derivatives.size();
414 ++i)
415 output_data.jacobian_2nd_derivatives[i] =
417
419 for (unsigned int i = 0;
420 i < output_data.jacobian_pushed_forward_2nd_derivatives.size();
421 ++i)
424
425 if (data.update_each & update_jacobian_3rd_derivatives)
426 for (unsigned int i = 0;
427 i < output_data.jacobian_3rd_derivatives.size();
428 ++i)
429 output_data.jacobian_3rd_derivatives[i] =
431
433 for (unsigned int i = 0;
434 i < output_data.jacobian_pushed_forward_3rd_derivatives.size();
435 ++i)
438 }
439}
440
441
442
443template <int dim, int spacedim>
444void
446 const InternalData &data) const
447{
448 if (data.update_each & update_volume_elements)
449 {
450 double volume = data.cell_extents[0];
451 for (unsigned int d = 1; d < dim; ++d)
452 volume *= data.cell_extents[d];
453 data.volume_element = volume;
454 }
455}
456
457
458
459template <int dim, int spacedim>
460void
462 const InternalData &data,
463 const CellSimilarity::Similarity cell_similarity,
465 &output_data) const
466{
467 // "compute" Jacobian at the quadrature points, which are all the
468 // same
469 if (data.update_each & update_jacobians)
470 if (cell_similarity != CellSimilarity::translation)
471 for (unsigned int i = 0; i < output_data.jacobians.size(); ++i)
472 {
474 for (unsigned int j = 0; j < dim; ++j)
475 output_data.jacobians[i][j][j] = data.cell_extents[j];
476 }
477}
478
479
480
481template <int dim, int spacedim>
482void
484 const InternalData &data,
485 const CellSimilarity::Similarity cell_similarity,
487 &output_data) const
488{
489 // "compute" inverse Jacobian at the quadrature points, which are
490 // all the same
491 if (data.update_each & update_inverse_jacobians)
492 if (cell_similarity != CellSimilarity::translation)
493 for (unsigned int i = 0; i < output_data.inverse_jacobians.size(); ++i)
494 {
495 output_data.inverse_jacobians[i] = Tensor<2, dim>();
496 for (unsigned int j = 0; j < dim; ++j)
497 output_data.inverse_jacobians[i][j][j] =
498 data.inverse_cell_extents[j];
499 }
500}
501
502
503
504template <int dim, int spacedim>
508 const CellSimilarity::Similarity cell_similarity,
509 const Quadrature<dim> &quadrature,
510 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
512 &output_data) const
513{
515
516 // convert data object to internal data for this class. fails with
517 // an exception if that is not possible
518 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
520 const InternalData &data = static_cast<const InternalData &>(internal_data);
521
522
523 update_cell_extents(cell, cell_similarity, data);
524
526 data,
527 quadrature.get_points(),
528 output_data.quadrature_points);
529
530 // compute Jacobian determinant. all values are equal and are the
531 // product of the local lengths in each coordinate direction
532 if (data.update_each & (update_JxW_values | update_volume_elements))
533 if (cell_similarity != CellSimilarity::translation)
534 {
535 double J = data.cell_extents[0];
536 for (unsigned int d = 1; d < dim; ++d)
537 J *= data.cell_extents[d];
538 data.volume_element = J;
539 if (data.update_each & update_JxW_values)
540 for (unsigned int i = 0; i < output_data.JxW_values.size(); ++i)
541 output_data.JxW_values[i] = J * quadrature.weight(i);
542 }
543
544
545 maybe_update_jacobians(data, cell_similarity, output_data);
546 maybe_update_jacobian_derivatives(data, cell_similarity, output_data);
547 maybe_update_inverse_jacobians(data, cell_similarity, output_data);
548
549 return cell_similarity;
550}
551
552
553
554template <int dim, int spacedim>
555void
558 const ArrayView<const Point<dim>> &unit_points,
559 const UpdateFlags update_flags,
561 &output_data) const
562{
563 if (update_flags == update_default)
564 return;
565
567
568 Assert(update_flags & update_inverse_jacobians ||
569 update_flags & update_jacobians ||
570 update_flags & update_quadrature_points,
572
573 output_data.initialize(unit_points.size(), update_flags);
574
576 data.update_each = update_flags;
577
579
581 data,
582 unit_points,
583 output_data.quadrature_points);
584
587}
588
589
590
591template <int dim, int spacedim>
592void
595 const unsigned int face_no,
596 const hp::QCollection<dim - 1> &quadrature,
597 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
599 &output_data) const
600{
602 AssertDimension(quadrature.size(), 1);
603
604 // convert data object to internal
605 // data for this class. fails with
606 // an exception if that is not
607 // possible
608 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
610 const InternalData &data = static_cast<const InternalData &>(internal_data);
611
613
615 face_no,
616 data,
617 output_data.quadrature_points);
618
619 maybe_update_normal_vectors(face_no, data, output_data.normal_vectors);
620
621 // first compute Jacobian determinant, which is simply the product
622 // of the local lengths since the jacobian is diagonal
623 double J = 1.;
624 for (unsigned int d = 0; d < dim; ++d)
626 J *= data.cell_extents[d];
627
628 if (data.update_each & update_JxW_values)
629 for (unsigned int i = 0; i < output_data.JxW_values.size(); ++i)
630 output_data.JxW_values[i] = J * quadrature[0].weight(i);
631
632 if (data.update_each & update_boundary_forms)
633 for (unsigned int i = 0; i < output_data.boundary_forms.size(); ++i)
634 output_data.boundary_forms[i] = J * output_data.normal_vectors[i];
635
640}
641
642
643
644template <int dim, int spacedim>
645void
648 const unsigned int face_no,
649 const unsigned int subface_no,
650 const Quadrature<dim - 1> &quadrature,
651 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
653 &output_data) const
654{
656
657 // convert data object to internal data for this class. fails with
658 // an exception if that is not possible
659 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
661 const InternalData &data = static_cast<const InternalData &>(internal_data);
662
664
666 cell, face_no, subface_no, data, output_data.quadrature_points);
667
668 maybe_update_normal_vectors(face_no, data, output_data.normal_vectors);
669
670 // first compute Jacobian determinant, which is simply the product
671 // of the local lengths since the jacobian is diagonal
672 double J = 1.;
673 for (unsigned int d = 0; d < dim; ++d)
675 J *= data.cell_extents[d];
676
677 if (data.update_each & update_JxW_values)
678 {
679 // Here, cell->face(face_no)->n_children() would be the right
680 // choice, but unfortunately the current function is also called
681 // for faces without children (see tests/fe/mapping.cc). Add
682 // following switch to avoid diffs in tests/fe/mapping.OK
683 const unsigned int n_subfaces =
684 cell->face(face_no)->has_children() ?
685 cell->face(face_no)->n_children() :
687 for (unsigned int i = 0; i < output_data.JxW_values.size(); ++i)
688 output_data.JxW_values[i] = J * quadrature.weight(i) / n_subfaces;
689 }
690
691 if (data.update_each & update_boundary_forms)
692 for (unsigned int i = 0; i < output_data.boundary_forms.size(); ++i)
693 output_data.boundary_forms[i] = J * output_data.normal_vectors[i];
694
699}
700
701
702
703template <int dim, int spacedim>
704void
708 const typename Mapping<dim, spacedim>::InternalDataBase &internal_data,
710 &output_data) const
711{
712 AssertDimension(dim, spacedim);
714
715 // Convert data object to internal data for this class. Fails with an
716 // exception if that is not possible.
717 Assert(dynamic_cast<const InternalData *>(&internal_data) != nullptr,
719 const InternalData &data = static_cast<const InternalData &>(internal_data);
720
721
723
725 data,
726 quadrature.get_points(),
727 output_data.quadrature_points);
728
729 if (data.update_each & update_normal_vectors)
730 for (unsigned int i = 0; i < output_data.normal_vectors.size(); ++i)
731 {
732 // The normals are n = J^{-T} * \hat{n} before normalizing.
733 Tensor<1, dim> normal;
734 const Tensor<1, dim> &ref_space_normal = quadrature.normal_vector(i);
735 for (unsigned int d = 0; d < dim; ++d)
736 {
737 normal[d] = ref_space_normal[d] * data.inverse_cell_extents[d];
738 }
739 normal /= normal.norm();
740 output_data.normal_vectors[i] = normal;
741 }
742
743 if (data.update_each & update_JxW_values)
744 for (unsigned int i = 0; i < output_data.JxW_values.size(); ++i)
745 {
746 const Tensor<1, dim> &ref_space_normal = quadrature.normal_vector(i);
747
748 // J^{-T} \times \hat{n}
749 Tensor<1, dim> invJTxNormal;
750 double det_jacobian = 1.;
751 for (unsigned int d = 0; d < dim; ++d)
752 {
753 det_jacobian *= data.cell_extents[d];
754 invJTxNormal[d] =
755 ref_space_normal[d] * data.inverse_cell_extents[d];
756 }
757 output_data.JxW_values[i] =
758 det_jacobian * invJTxNormal.norm() * quadrature.weight(i);
759 }
760
765}
766
767
768
769template <int dim, int spacedim>
770void
772 const ArrayView<const Tensor<1, dim>> &input,
773 const MappingKind mapping_kind,
774 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
775 const ArrayView<Tensor<1, spacedim>> &output) const
776{
777 AssertDimension(input.size(), output.size());
778 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
780 const InternalData &data = static_cast<const InternalData &>(mapping_data);
781
782 switch (mapping_kind)
783 {
785 {
788 "update_covariant_transformation"));
789
790 for (unsigned int i = 0; i < output.size(); ++i)
791 for (unsigned int d = 0; d < dim; ++d)
792 output[i][d] = input[i][d] * data.inverse_cell_extents[d];
793 return;
794 }
795
797 {
800 "update_contravariant_transformation"));
801
802 for (unsigned int i = 0; i < output.size(); ++i)
803 for (unsigned int d = 0; d < dim; ++d)
804 output[i][d] = input[i][d] * data.cell_extents[d];
805 return;
806 }
807 case mapping_piola:
808 {
811 "update_contravariant_transformation"));
812 Assert(data.update_each & update_volume_elements,
814 "update_volume_elements"));
815
816 for (unsigned int i = 0; i < output.size(); ++i)
817 for (unsigned int d = 0; d < dim; ++d)
818 output[i][d] =
819 input[i][d] * data.cell_extents[d] / data.volume_element;
820 return;
821 }
822 default:
824 }
825}
826
827
828
829template <int dim, int spacedim>
830void
833 const MappingKind mapping_kind,
834 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
835 const ArrayView<Tensor<2, spacedim>> &output) const
836{
837 AssertDimension(input.size(), output.size());
838 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
840 const InternalData &data = static_cast<const InternalData &>(mapping_data);
841
842 switch (mapping_kind)
843 {
845 {
848 "update_covariant_transformation"));
849
850 for (unsigned int i = 0; i < output.size(); ++i)
851 for (unsigned int d1 = 0; d1 < dim; ++d1)
852 for (unsigned int d2 = 0; d2 < dim; ++d2)
853 output[i][d1][d2] =
854 input[i][d1][d2] * data.inverse_cell_extents[d2];
855 return;
856 }
857
859 {
862 "update_contravariant_transformation"));
863
864 for (unsigned int i = 0; i < output.size(); ++i)
865 for (unsigned int d1 = 0; d1 < dim; ++d1)
866 for (unsigned int d2 = 0; d2 < dim; ++d2)
867 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2];
868 return;
869 }
870
872 {
875 "update_covariant_transformation"));
876
877 for (unsigned int i = 0; i < output.size(); ++i)
878 for (unsigned int d1 = 0; d1 < dim; ++d1)
879 for (unsigned int d2 = 0; d2 < dim; ++d2)
880 output[i][d1][d2] = input[i][d1][d2] *
881 data.inverse_cell_extents[d2] *
882 data.inverse_cell_extents[d1];
883 return;
884 }
885
887 {
890 "update_contravariant_transformation"));
891
892 for (unsigned int i = 0; i < output.size(); ++i)
893 for (unsigned int d1 = 0; d1 < dim; ++d1)
894 for (unsigned int d2 = 0; d2 < dim; ++d2)
895 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] *
896 data.inverse_cell_extents[d1];
897 return;
898 }
899
900 case mapping_piola:
901 {
904 "update_contravariant_transformation"));
905 Assert(data.update_each & update_volume_elements,
907 "update_volume_elements"));
908
909 for (unsigned int i = 0; i < output.size(); ++i)
910 for (unsigned int d1 = 0; d1 < dim; ++d1)
911 for (unsigned int d2 = 0; d2 < dim; ++d2)
912 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] /
913 data.volume_element;
914 return;
915 }
916
918 {
921 "update_contravariant_transformation"));
922 Assert(data.update_each & update_volume_elements,
924 "update_volume_elements"));
925
926 for (unsigned int i = 0; i < output.size(); ++i)
927 for (unsigned int d1 = 0; d1 < dim; ++d1)
928 for (unsigned int d2 = 0; d2 < dim; ++d2)
929 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] *
930 data.inverse_cell_extents[d1] /
931 data.volume_element;
932 return;
933 }
934
935 default:
937 }
938}
939
940
941
942template <int dim, int spacedim>
943void
945 const ArrayView<const Tensor<2, dim>> &input,
946 const MappingKind mapping_kind,
947 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
948 const ArrayView<Tensor<2, spacedim>> &output) const
949{
950 AssertDimension(input.size(), output.size());
951 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
953 const InternalData &data = static_cast<const InternalData &>(mapping_data);
954
955 switch (mapping_kind)
956 {
958 {
961 "update_covariant_transformation"));
962
963 for (unsigned int i = 0; i < output.size(); ++i)
964 for (unsigned int d1 = 0; d1 < dim; ++d1)
965 for (unsigned int d2 = 0; d2 < dim; ++d2)
966 output[i][d1][d2] =
967 input[i][d1][d2] * data.inverse_cell_extents[d2];
968 return;
969 }
970
972 {
975 "update_contravariant_transformation"));
976
977 for (unsigned int i = 0; i < output.size(); ++i)
978 for (unsigned int d1 = 0; d1 < dim; ++d1)
979 for (unsigned int d2 = 0; d2 < dim; ++d2)
980 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2];
981 return;
982 }
983
985 {
988 "update_covariant_transformation"));
989
990 for (unsigned int i = 0; i < output.size(); ++i)
991 for (unsigned int d1 = 0; d1 < dim; ++d1)
992 for (unsigned int d2 = 0; d2 < dim; ++d2)
993 output[i][d1][d2] = input[i][d1][d2] *
994 data.inverse_cell_extents[d2] *
995 data.inverse_cell_extents[d1];
996 return;
997 }
998
1000 {
1003 "update_contravariant_transformation"));
1004
1005 for (unsigned int i = 0; i < output.size(); ++i)
1006 for (unsigned int d1 = 0; d1 < dim; ++d1)
1007 for (unsigned int d2 = 0; d2 < dim; ++d2)
1008 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] *
1009 data.inverse_cell_extents[d1];
1010 return;
1011 }
1012
1013 case mapping_piola:
1014 {
1017 "update_contravariant_transformation"));
1018 Assert(data.update_each & update_volume_elements,
1020 "update_volume_elements"));
1021
1022 for (unsigned int i = 0; i < output.size(); ++i)
1023 for (unsigned int d1 = 0; d1 < dim; ++d1)
1024 for (unsigned int d2 = 0; d2 < dim; ++d2)
1025 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] /
1026 data.volume_element;
1027 return;
1028 }
1029
1031 {
1034 "update_contravariant_transformation"));
1035 Assert(data.update_each & update_volume_elements,
1037 "update_volume_elements"));
1038
1039 for (unsigned int i = 0; i < output.size(); ++i)
1040 for (unsigned int d1 = 0; d1 < dim; ++d1)
1041 for (unsigned int d2 = 0; d2 < dim; ++d2)
1042 output[i][d1][d2] = input[i][d1][d2] * data.cell_extents[d2] *
1043 data.inverse_cell_extents[d1] /
1044 data.volume_element;
1045 return;
1046 }
1047
1048 default:
1050 }
1051}
1052
1053
1054
1055template <int dim, int spacedim>
1056void
1058 const ArrayView<const DerivativeForm<2, dim, spacedim>> &input,
1059 const MappingKind mapping_kind,
1060 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1061 const ArrayView<Tensor<3, spacedim>> &output) const
1062{
1063 AssertDimension(input.size(), output.size());
1064 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
1066 const InternalData &data = static_cast<const InternalData &>(mapping_data);
1067
1068 switch (mapping_kind)
1069 {
1071 {
1074 "update_covariant_transformation"));
1075
1076 for (unsigned int q = 0; q < output.size(); ++q)
1077 for (unsigned int i = 0; i < spacedim; ++i)
1078 for (unsigned int j = 0; j < spacedim; ++j)
1079 for (unsigned int k = 0; k < spacedim; ++k)
1080 {
1081 output[q][i][j][k] = input[q][i][j][k] *
1082 data.inverse_cell_extents[j] *
1083 data.inverse_cell_extents[k];
1084 }
1085 return;
1086 }
1087 default:
1089 }
1090}
1091
1092
1093
1094template <int dim, int spacedim>
1095void
1097 const ArrayView<const Tensor<3, dim>> &input,
1098 const MappingKind mapping_kind,
1099 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_data,
1100 const ArrayView<Tensor<3, spacedim>> &output) const
1101{
1102 AssertDimension(input.size(), output.size());
1103 Assert(dynamic_cast<const InternalData *>(&mapping_data) != nullptr,
1105 const InternalData &data = static_cast<const InternalData &>(mapping_data);
1106
1107 switch (mapping_kind)
1108 {
1110 {
1113 "update_covariant_transformation"));
1116 "update_contravariant_transformation"));
1117
1118 for (unsigned int q = 0; q < output.size(); ++q)
1119 for (unsigned int i = 0; i < spacedim; ++i)
1120 for (unsigned int j = 0; j < spacedim; ++j)
1121 for (unsigned int k = 0; k < spacedim; ++k)
1122 {
1123 output[q][i][j][k] = input[q][i][j][k] *
1124 data.cell_extents[i] *
1125 data.inverse_cell_extents[j] *
1126 data.inverse_cell_extents[k];
1127 }
1128 return;
1129 }
1130
1132 {
1135 "update_covariant_transformation"));
1136
1137 for (unsigned int q = 0; q < output.size(); ++q)
1138 for (unsigned int i = 0; i < spacedim; ++i)
1139 for (unsigned int j = 0; j < spacedim; ++j)
1140 for (unsigned int k = 0; k < spacedim; ++k)
1141 {
1142 output[q][i][j][k] = input[q][i][j][k] *
1143 (data.inverse_cell_extents[i] *
1144 data.inverse_cell_extents[j]) *
1145 data.inverse_cell_extents[k];
1146 }
1147
1148 return;
1149 }
1150
1152 {
1155 "update_covariant_transformation"));
1158 "update_contravariant_transformation"));
1159 Assert(data.update_each & update_volume_elements,
1161 "update_volume_elements"));
1162
1163 for (unsigned int q = 0; q < output.size(); ++q)
1164 for (unsigned int i = 0; i < spacedim; ++i)
1165 for (unsigned int j = 0; j < spacedim; ++j)
1166 for (unsigned int k = 0; k < spacedim; ++k)
1167 {
1168 output[q][i][j][k] =
1169 input[q][i][j][k] *
1170 (data.cell_extents[i] / data.volume_element *
1171 data.inverse_cell_extents[j]) *
1172 data.inverse_cell_extents[k];
1173 }
1174
1175 return;
1176 }
1177
1178 default:
1180 }
1181}
1182
1183
1184
1185template <int dim, int spacedim>
1189 const Point<dim> &p) const
1190{
1192 Assert(dim == spacedim, ExcNotImplemented());
1193
1194 Point<dim> unit = cell->vertex(0);
1195
1196 // Go through vertices with numbers 1, 2, 4
1197 for (unsigned int d = 0; d < dim; ++d)
1198 unit[d] += (cell->vertex(1 << d)[d] - unit[d]) * p[d];
1199
1200 return unit;
1201}
1202
1203
1204
1205template <int dim, int spacedim>
1209 const Point<spacedim> &p) const
1210{
1212 Assert(dim == spacedim, ExcNotImplemented());
1213
1214 const Point<dim> start = cell->vertex(0);
1215 Point<dim> real = p;
1216
1217 // Go through vertices with numbers 1, 2, 4
1218 for (unsigned int d = 0; d < dim; ++d)
1219 real[d] = (real[d] - start[d]) / (cell->vertex(1 << d)[d] - start[d]);
1220
1221 return real;
1222}
1223
1224
1225
1226template <int dim, int spacedim>
1227void
1230 const ArrayView<const Point<spacedim>> &real_points,
1231 const ArrayView<Point<dim>> &unit_points) const
1232{
1234 AssertDimension(real_points.size(), unit_points.size());
1235
1236 if (dim != spacedim)
1238
1239 const Point<dim> start = cell->vertex(0);
1240
1241 // Go through vertices with numbers 1, 2, 4
1242 std::array<double, dim> inverse_lengths;
1243 for (unsigned int d = 0; d < dim; ++d)
1244 inverse_lengths[d] = 1. / (cell->vertex(1 << d)[d] - start[d]);
1245
1246 for (unsigned int i = 0; i < real_points.size(); ++i)
1247 for (unsigned int d = 0; d < dim; ++d)
1248 unit_points[i][d] = (real_points[i][d] - start[d]) * inverse_lengths[d];
1249}
1250
1251
1252
1253template <int dim, int spacedim>
1254std::unique_ptr<Mapping<dim, spacedim>>
1256{
1257 return std::make_unique<MappingCartesian<dim, spacedim>>(*this);
1258}
1259
1260
1261//---------------------------------------------------------------------------
1262// explicit instantiations
1263#include "fe/mapping_cartesian.inst"
1264
1265
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
virtual void reinit(const UpdateFlags update_flags, const Quadrature< dim > &quadrature) override
virtual std::size_t memory_consumption() 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
void maybe_update_cell_quadrature_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const InternalData &data, const ArrayView< const Point< dim > > &unit_quadrature_points, std::vector< Point< dim > > &quadrature_points) const
void maybe_update_volume_elements(const InternalData &data) const
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_face_data(const UpdateFlags flags, const hp::QCollection< dim - 1 > &quadrature) const override
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) 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
void update_cell_extents(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellSimilarity::Similarity cell_similarity, const InternalData &data) const
virtual void fill_fe_immersed_surface_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const NonMatching::ImmersedSurfaceQuadrature< dim > &quadrature, const typename Mapping< dim, spacedim >::InternalDataBase &internal_data, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const override
void maybe_update_jacobians(const InternalData &data, const CellSimilarity::Similarity cell_similarity, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const
void maybe_update_subface_quadrature_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int sub_no, const InternalData &data, std::vector< Point< dim > > &quadrature_points) const
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
void maybe_update_face_quadrature_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const InternalData &data, std::vector< Point< dim > > &quadrature_points) const
virtual bool preserves_vertex_locations() const override
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const override
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() 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 void transform_points_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const ArrayView< const Point< spacedim > > &real_points, const ArrayView< Point< dim > > &unit_points) const override
void fill_mapping_data_for_generic_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const ArrayView< const Point< dim > > &unit_points, const UpdateFlags update_flags, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) const
void maybe_update_jacobian_derivatives(const InternalData &data, const CellSimilarity::Similarity cell_similarity, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) 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
void maybe_update_normal_vectors(const unsigned int face_no, const InternalData &data, std::vector< Tensor< 1, dim > > &normal_vectors) const
virtual std::unique_ptr< typename Mapping< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags, const Quadrature< dim > &quadrature) const override
void maybe_update_inverse_jacobians(const InternalData &data, const CellSimilarity::Similarity cell_similarity, internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &output_data) 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
Abstract base class for mapping classes.
Definition mapping.h:318
const Tensor< 1, spacedim > & normal_vector(const unsigned int i) 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:204
static DataSetDescriptor face(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points)
static DataSetDescriptor cell()
Definition qprojector.h:314
static DataSetDescriptor subface(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const unsigned int subface_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points, const internal::SubfaceCase< dim > ref_case=internal::SubfaceCase< dim >::case_isotropic)
Class which transforms dim - 1-dimensional quadrature rules to dim-dimensional face quadratures.
Definition qprojector.h:68
double weight(const unsigned int i) const
const std::vector< Point< dim > > & get_points() const
numbers::NumberTraits< Number >::real_type norm() const
unsigned int size() const
Definition collection.h:314
std::vector< DerivativeForm< 1, spacedim, dim > > inverse_jacobians
void initialize(const unsigned int n_quadrature_points, const UpdateFlags flags)
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
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcCellNotCartesian()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
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_default
No update.
@ 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
bool is_cartesian(const CellType &cell)
std::vector< index_type > data
Definition mpi.cc:734
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:473
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)