17 #include <deal.II/base/array_view.h>
18 #include <deal.II/base/derivative_form.h>
19 #include <deal.II/base/memory_consumption.h>
20 #include <deal.II/base/qprojector.h>
21 #include <deal.II/base/quadrature.h>
22 #include <deal.II/base/quadrature_lib.h>
23 #include <deal.II/base/std_cxx14/memory.h>
24 #include <deal.II/base/tensor_product_polynomials.h>
26 #include <deal.II/dofs/dof_accessor.h>
28 #include <deal.II/fe/fe.h>
29 #include <deal.II/fe/fe_tools.h>
30 #include <deal.II/fe/fe_values.h>
31 #include <deal.II/fe/mapping_manifold.h>
32 #include <deal.II/fe/mapping_q1.h>
34 #include <deal.II/grid/manifold.h>
35 #include <deal.II/grid/tria.h>
36 #include <deal.II/grid/tria_iterator.h>
38 #include <deal.II/lac/full_matrix.h>
47 DEAL_II_NAMESPACE_OPEN
49 template <
int dim,
int spacedim>
69 template <
int dim,
int spacedim>
72 const UpdateFlags update_flags,
74 const unsigned int n_original_q_points)
78 this->update_each = update_flags;
88 if (this->update_each &
89 (update_quadrature_points | update_contravariant_transformation))
90 compute_manifold_quadrature_weights(q);
92 if (this->update_each & update_covariant_transformation)
93 covariant.resize(n_original_q_points);
95 if (this->update_each & update_contravariant_transformation)
96 contravariant.resize(n_original_q_points);
98 if (this->update_each & update_volume_elements)
99 volume_elements.resize(n_original_q_points);
103 template <
int dim,
int spacedim>
106 const UpdateFlags update_flags,
108 const unsigned int n_original_q_points)
110 initialize(update_flags, q, n_original_q_points);
114 if (this->update_each & update_boundary_forms)
120 for (
unsigned int i = 0; i < unit_tangentials.size(); ++i)
121 unit_tangentials[i].resize(n_original_q_points);
128 static const int tangential_orientation[4] = {-1, 1, 1, -1};
129 for (
unsigned int i = 0;
130 i < GeometryInfo<dim>::faces_per_cell;
134 tang[1 - i / 2] = tangential_orientation[i];
135 std::fill(unit_tangentials[i].begin(),
136 unit_tangentials[i].end(),
143 for (
unsigned int i = 0;
144 i < GeometryInfo<dim>::faces_per_cell;
149 const unsigned int nd =
157 tang1[(nd + 1) % dim] =
162 tang2[(nd + 2) % dim] = 1.;
167 std::fill(unit_tangentials[i].begin(),
168 unit_tangentials[i].end(),
188 template <
int dim,
int spacedim>
195 template <
int dim,
int spacedim>
196 std::unique_ptr<Mapping<dim, spacedim>>
199 return std_cxx14::make_unique<MappingManifold<dim, spacedim>>(*this);
204 template <
int dim,
int spacedim>
216 template <
int dim,
int spacedim>
223 std::array<double, GeometryInfo<dim>::vertices_per_cell> weights;
225 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
227 vertices[v] = cell->vertex(v);
230 return cell->get_manifold().get_new_point(
231 make_array_view(vertices.begin(), vertices.end()),
232 make_array_view(weights.begin(), weights.end()));
250 template <
int dim,
int spacedim>
253 const UpdateFlags in)
const
261 UpdateFlags out = in;
262 for (
unsigned int i = 0; i < 5; ++i)
273 if (out & (update_JxW_values | update_normal_vectors))
274 out |= update_boundary_forms;
276 if (out & (update_covariant_transformation | update_JxW_values |
277 update_jacobians | update_jacobian_grads |
278 update_boundary_forms | update_normal_vectors))
279 out |= update_contravariant_transformation;
282 (update_inverse_jacobians | update_jacobian_pushed_forward_grads |
283 update_jacobian_pushed_forward_2nd_derivatives |
284 update_jacobian_pushed_forward_3rd_derivatives))
285 out |= update_covariant_transformation;
293 if (out & update_contravariant_transformation)
294 out |= update_JxW_values;
296 if (out & update_normal_vectors)
297 out |= update_JxW_values;
302 Assert(!(out & (update_jacobian_grads | update_jacobian_pushed_forward_grads |
303 update_jacobian_pushed_forward_2nd_derivatives |
304 update_jacobian_pushed_forward_3rd_derivatives)),
312 template <
int dim,
int spacedim>
313 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
317 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
318 std_cxx14::make_unique<InternalData>();
319 auto &data = dynamic_cast<InternalData &>(*data_ptr);
327 template <
int dim,
int spacedim>
328 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
330 const UpdateFlags update_flags,
333 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
334 std_cxx14::make_unique<InternalData>();
335 auto &data = dynamic_cast<InternalData &>(*data_ptr);
345 template <
int dim,
int spacedim>
346 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase>
348 const UpdateFlags update_flags,
351 std::unique_ptr<typename Mapping<dim, spacedim>::InternalDataBase> data_ptr =
352 std_cxx14::make_unique<InternalData>();
353 auto &data = dynamic_cast<InternalData &>(*data_ptr);
365 namespace MappingManifoldImplementation
375 template <
int dim,
int spacedim>
377 maybe_compute_q_points(
379 const typename ::MappingManifold<dim, spacedim>::InternalData
383 const UpdateFlags update_flags = data.update_each;
388 if (update_flags & update_quadrature_points)
390 for (
unsigned int point = 0; point < quadrature_points.size();
393 quadrature_points[point] = data.manifold->get_new_point(
394 make_array_view(data.vertices),
396 data.cell_manifold_quadrature_weights[point + data_set]));
409 template <
int dim,
int spacedim>
411 maybe_update_Jacobians(
412 const typename ::QProjector<dim>::DataSetDescriptor data_set,
413 const typename ::MappingManifold<dim, spacedim>::InternalData
416 const UpdateFlags update_flags = data.update_each;
418 if (update_flags & update_contravariant_transformation)
420 const unsigned int n_q_points = data.contravariant.size();
422 std::fill(data.contravariant.begin(),
423 data.contravariant.end(),
427 data.vertices.size());
428 for (
unsigned int point = 0;
point < n_q_points; ++
point)
432 const Point<dim> &p = data.quad.point(point + data_set);
436 make_array_view(data.vertices),
438 data.cell_manifold_quadrature_weights[point + data_set]));
447 for (
unsigned int i = 0; i < dim; ++i)
450 const double pi = p[i];
451 Assert(pi >= 0 && pi <= 1.0,
453 "Was expecting a quadrature point "
454 "inside the unit reference element."));
458 const double L = pi > .5 ? -pi : 1 - pi;
463 for (
unsigned int j = 0;
464 j < GeometryInfo<dim>::vertices_per_cell;
466 data.vertex_weights[j] =
470 make_array_view(data.vertices),
471 make_array_view(data.vertex_weights));
474 data.manifold->get_tangent_vector(P, NP);
476 for (
unsigned int d = 0;
d < spacedim; ++
d)
477 data.contravariant[point][d][i] = T[d] / L;
481 if (update_flags & update_covariant_transformation)
483 const unsigned int n_q_points = data.contravariant.size();
484 for (
unsigned int point = 0;
point < n_q_points; ++
point)
486 data.covariant[
point] =
487 (data.contravariant[
point]).covariant_form();
491 if (update_flags & update_volume_elements)
493 const unsigned int n_q_points = data.contravariant.size();
494 for (
unsigned int point = 0;
point < n_q_points; ++
point)
495 data.volume_elements[point] =
506 template <
int dim,
int spacedim>
517 Assert(dynamic_cast<const InternalData *>(&internal_data) !=
nullptr,
519 const InternalData &data = static_cast<const InternalData &>(internal_data);
521 const unsigned int n_q_points = quadrature.
size();
524 data.
manifold = &(cell->get_manifold());
526 internal::MappingManifoldImplementation::maybe_compute_q_points<dim,
532 internal::MappingManifoldImplementation::maybe_update_Jacobians<dim,
536 const UpdateFlags update_flags = data.update_each;
537 const std::vector<double> &weights = quadrature.
get_weights();
542 if (update_flags & (update_normal_vectors | update_JxW_values))
546 Assert(!(update_flags & update_normal_vectors) ||
552 for (
unsigned int point = 0; point < n_q_points; ++point)
556 const double det = data.contravariant[point].determinant();
563 Assert(det > 1e-12 * Utilities::fixed_power<dim>(
564 cell->diameter() / std::sqrt(
double(dim))),
566 cell->center(), det, point)));
568 output_data.
JxW_values[point] = weights[point] * det;
576 for (
unsigned int i = 0; i < spacedim; ++i)
577 for (
unsigned int j = 0; j < dim; ++j)
578 DX_t[j][i] = data.contravariant[point][i][j];
581 for (
unsigned int i = 0; i < dim; ++i)
582 for (
unsigned int j = 0; j < dim; ++j)
583 G[i][j] = DX_t[i] * DX_t[j];
591 if (update_flags & update_normal_vectors)
596 if (update_flags & update_normal_vectors)
598 Assert(spacedim == dim + 1,
600 "There is no (unique) cell normal for " +
602 "-dimensional cells in " +
604 "-dimensional space. This only works if the "
605 "space dimension is one greater than the "
606 "dimensionality of the mesh cells."));
610 cross_product_2d(-DX_t[0]);
613 cross_product_3d(DX_t[0], DX_t[1]);
618 if (cell->direction_flag() ==
false)
629 if (update_flags & update_jacobians)
633 for (
unsigned int point = 0; point < n_q_points; ++point)
634 output_data.
jacobians[point] = data.contravariant[point];
638 if (update_flags & update_inverse_jacobians)
642 for (
unsigned int point = 0; point < n_q_points; ++point)
644 data.covariant[point].transpose();
647 return cell_similarity;
654 namespace MappingManifoldImplementation
667 template <
int dim,
int spacedim>
669 maybe_compute_face_data(
670 const ::MappingManifold<dim, spacedim> &mapping,
671 const typename ::Triangulation<dim, spacedim>::cell_iterator
673 const unsigned int face_no,
674 const unsigned int subface_no,
675 const unsigned int n_q_points,
676 const std::vector<double> &weights,
677 const typename ::MappingManifold<dim, spacedim>::InternalData
682 const UpdateFlags update_flags = data.update_each;
684 if (update_flags & update_boundary_forms)
687 if (update_flags & update_normal_vectors)
689 if (update_flags & update_JxW_values)
695 for (
unsigned int d = 0; d != dim - 1; ++d)
698 data.unit_tangentials.size(),
701 data.aux[d].size() <=
703 .unit_tangentials[face_no +
711 .unit_tangentials[face_no +
715 make_array_view(data.aux[d]));
722 for (
unsigned int i = 0; i < n_q_points; ++i)
731 (face_no == 0 ? -1 : +1);
735 cross_product_2d(data.aux[0][i]);
739 cross_product_3d(data.aux[0][i], data.aux[1][i]);
755 for (
unsigned int point = 0;
point < n_q_points; ++
point)
763 data.contravariant[
point].transpose()[0];
765 (face_no == 0 ? -1. : +1.) *
777 cross_product_3d(DX_t[0], DX_t[1]);
778 cell_normal /= cell_normal.
norm();
783 cross_product_3d(data.aux[0][point], cell_normal);
794 if (update_flags & (update_normal_vectors | update_JxW_values))
798 if (update_flags & update_JxW_values)
805 const double area_ratio =
807 cell->subface_case(face_no), subface_no);
812 if (update_flags & update_normal_vectors)
818 if (update_flags & update_jacobians)
819 for (
unsigned int point = 0;
point < n_q_points; ++
point)
820 output_data.
jacobians[point] = data.contravariant[point];
822 if (update_flags & update_inverse_jacobians)
823 for (
unsigned int point = 0;
point < n_q_points; ++
point)
825 data.covariant[point].transpose();
836 template <
int dim,
int spacedim>
838 do_fill_fe_face_values(
839 const ::MappingManifold<dim, spacedim> &mapping,
840 const typename ::Triangulation<dim, spacedim>::cell_iterator
842 const unsigned int face_no,
843 const unsigned int subface_no,
846 const typename ::MappingManifold<dim, spacedim>::InternalData
851 data.store_vertices(cell);
853 data.manifold = &cell->face(face_no)->get_manifold();
855 maybe_compute_q_points<dim, spacedim>(data_set,
858 maybe_update_Jacobians<dim, spacedim>(data_set, data);
860 maybe_compute_face_data(mapping,
870 template <
int dim,
int spacedim,
int rank>
879 Assert((
dynamic_cast<const typename ::
880 MappingManifold<dim, spacedim>::InternalData *
>(
881 &mapping_data) !=
nullptr),
883 const typename ::MappingManifold<dim, spacedim>::InternalData
885 static_cast<const typename ::MappingManifold<dim, spacedim>::
886 InternalData &
>(mapping_data);
888 switch (mapping_type)
893 data.update_each & update_contravariant_transformation,
895 "update_contravariant_transformation"));
897 for (
unsigned int i = 0; i < output.size(); ++i)
899 apply_transformation(data.contravariant[i], input[i]);
907 data.update_each & update_contravariant_transformation,
909 "update_contravariant_transformation"));
911 data.update_each & update_volume_elements,
913 "update_volume_elements"));
918 for (
unsigned int i = 0; i < output.size(); ++i)
921 apply_transformation(data.contravariant[i], input[i]);
922 output[i] /= data.volume_elements[i];
932 data.update_each & update_contravariant_transformation,
934 "update_covariant_transformation"));
936 for (
unsigned int i = 0; i < output.size(); ++i)
937 output[i] = apply_transformation(data.covariant[i], input[i]);
948 template <
int dim,
int spacedim,
int rank>
957 Assert((
dynamic_cast<const typename ::
958 MappingManifold<dim, spacedim>::InternalData *
>(
959 &mapping_data) !=
nullptr),
961 const typename ::MappingManifold<dim, spacedim>::InternalData
963 static_cast<const typename ::MappingManifold<dim, spacedim>::
964 InternalData &
>(mapping_data);
966 switch (mapping_type)
971 data.update_each & update_covariant_transformation,
973 "update_covariant_transformation"));
975 data.update_each & update_contravariant_transformation,
977 "update_contravariant_transformation"));
980 for (
unsigned int i = 0; i < output.size(); ++i)
983 apply_transformation(data.contravariant[i],
986 apply_transformation(data.covariant[i], A.
transpose());
995 data.update_each & update_covariant_transformation,
997 "update_covariant_transformation"));
1000 for (
unsigned int i = 0; i < output.size(); ++i)
1003 apply_transformation(data.covariant[i],
1006 apply_transformation(data.covariant[i], A.
transpose());
1015 data.update_each & update_covariant_transformation,
1017 "update_covariant_transformation"));
1019 data.update_each & update_contravariant_transformation,
1021 "update_contravariant_transformation"));
1023 data.update_each & update_volume_elements,
1025 "update_volume_elements"));
1028 for (
unsigned int i = 0; i < output.size(); ++i)
1031 apply_transformation(data.covariant[i], input[i]);
1033 apply_transformation(data.contravariant[i],
1037 output[i] /= data.volume_elements[i];
1050 template <
int dim,
int spacedim>
1059 Assert((
dynamic_cast<const typename ::
1060 MappingManifold<dim, spacedim>::InternalData *
>(
1061 &mapping_data) !=
nullptr),
1063 const typename ::MappingManifold<dim, spacedim>::InternalData
1065 static_cast<const typename ::MappingManifold<dim, spacedim>::
1066 InternalData &
>(mapping_data);
1068 switch (mapping_type)
1073 data.update_each & update_covariant_transformation,
1075 "update_covariant_transformation"));
1077 data.update_each & update_contravariant_transformation,
1079 "update_contravariant_transformation"));
1081 for (
unsigned int q = 0; q < output.size(); ++q)
1082 for (
unsigned int i = 0; i < spacedim; ++i)
1084 double tmp1[dim][dim];
1085 for (
unsigned int J = 0; J < dim; ++J)
1086 for (
unsigned int K = 0; K < dim; ++K)
1089 data.contravariant[q][i][0] * input[q][0][J][K];
1090 for (
unsigned int I = 1; I < dim; ++I)
1092 data.contravariant[q][i][I] * input[q][I][J][K];
1094 for (
unsigned int j = 0; j < spacedim; ++j)
1097 for (
unsigned int K = 0; K < dim; ++K)
1099 tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
1100 for (
unsigned int J = 1; J < dim; ++J)
1101 tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
1103 for (
unsigned int k = 0; k < spacedim; ++k)
1105 output[q][i][j][k] =
1106 data.covariant[q][k][0] * tmp2[0];
1107 for (
unsigned int K = 1; K < dim; ++K)
1108 output[q][i][j][k] +=
1109 data.covariant[q][k][K] * tmp2[K];
1119 data.update_each & update_covariant_transformation,
1121 "update_covariant_transformation"));
1123 for (
unsigned int q = 0; q < output.size(); ++q)
1124 for (
unsigned int i = 0; i < spacedim; ++i)
1126 double tmp1[dim][dim];
1127 for (
unsigned int J = 0; J < dim; ++J)
1128 for (
unsigned int K = 0; K < dim; ++K)
1131 data.covariant[q][i][0] * input[q][0][J][K];
1132 for (
unsigned int I = 1; I < dim; ++I)
1134 data.covariant[q][i][I] * input[q][I][J][K];
1136 for (
unsigned int j = 0; j < spacedim; ++j)
1139 for (
unsigned int K = 0; K < dim; ++K)
1141 tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
1142 for (
unsigned int J = 1; J < dim; ++J)
1143 tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
1145 for (
unsigned int k = 0; k < spacedim; ++k)
1147 output[q][i][j][k] =
1148 data.covariant[q][k][0] * tmp2[0];
1149 for (
unsigned int K = 1; K < dim; ++K)
1150 output[q][i][j][k] +=
1151 data.covariant[q][k][K] * tmp2[K];
1162 data.update_each & update_covariant_transformation,
1164 "update_covariant_transformation"));
1166 data.update_each & update_contravariant_transformation,
1168 "update_contravariant_transformation"));
1170 data.update_each & update_volume_elements,
1172 "update_volume_elements"));
1174 for (
unsigned int q = 0; q < output.size(); ++q)
1175 for (
unsigned int i = 0; i < spacedim; ++i)
1178 for (
unsigned int I = 0; I < dim; ++I)
1180 data.contravariant[q][i][I] / data.volume_elements[q];
1181 double tmp1[dim][dim];
1182 for (
unsigned int J = 0; J < dim; ++J)
1183 for (
unsigned int K = 0; K < dim; ++K)
1185 tmp1[J][K] = factor[0] * input[q][0][J][K];
1186 for (
unsigned int I = 1; I < dim; ++I)
1187 tmp1[J][K] += factor[I] * input[q][I][J][K];
1189 for (
unsigned int j = 0; j < spacedim; ++j)
1192 for (
unsigned int K = 0; K < dim; ++K)
1194 tmp2[K] = data.covariant[q][j][0] * tmp1[0][K];
1195 for (
unsigned int J = 1; J < dim; ++J)
1196 tmp2[K] += data.covariant[q][j][J] * tmp1[J][K];
1198 for (
unsigned int k = 0; k < spacedim; ++k)
1200 output[q][i][j][k] =
1201 data.covariant[q][k][0] * tmp2[0];
1202 for (
unsigned int K = 1; K < dim; ++K)
1203 output[q][i][j][k] +=
1204 data.covariant[q][k][K] * tmp2[K];
1219 template <
int dim,
int spacedim,
int rank>
1221 transform_differential_forms(
1228 Assert((
dynamic_cast<const typename ::
1229 MappingManifold<dim, spacedim>::InternalData *
>(
1230 &mapping_data) !=
nullptr),
1232 const typename ::MappingManifold<dim, spacedim>::InternalData
1234 static_cast<const typename ::MappingManifold<dim, spacedim>::
1235 InternalData &
>(mapping_data);
1237 switch (mapping_type)
1242 data.update_each & update_contravariant_transformation,
1244 "update_covariant_transformation"));
1246 for (
unsigned int i = 0; i < output.size(); ++i)
1247 output[i] = apply_transformation(data.covariant[i], input[i]);
1261 template <
int dim,
int spacedim>
1265 const unsigned int face_no,
1272 Assert((dynamic_cast<const InternalData *>(&internal_data) !=
nullptr),
1274 const InternalData &data = static_cast<const InternalData &>(internal_data);
1276 internal::MappingManifoldImplementation::do_fill_fe_face_values(
1282 cell->face_orientation(face_no),
1283 cell->face_flip(face_no),
1284 cell->face_rotation(face_no),
1293 template <
int dim,
int spacedim>
1297 const unsigned int face_no,
1298 const unsigned int subface_no,
1305 Assert((dynamic_cast<const InternalData *>(&internal_data) !=
nullptr),
1307 const InternalData &data = static_cast<const InternalData &>(internal_data);
1309 internal::MappingManifoldImplementation::do_fill_fe_face_values(
1316 cell->face_orientation(face_no),
1317 cell->face_flip(face_no),
1318 cell->face_rotation(face_no),
1320 cell->subface_case(face_no)),
1328 template <
int dim,
int spacedim>
1336 internal::MappingManifoldImplementation::transform_fields(input,
1344 template <
int dim,
int spacedim>
1352 internal::MappingManifoldImplementation::transform_differential_forms(
1353 input, mapping_type, mapping_data, output);
1358 template <
int dim,
int spacedim>
1366 switch (mapping_type)
1369 internal::MappingManifoldImplementation::transform_fields(input,
1378 internal::MappingManifoldImplementation::transform_gradients(
1379 input, mapping_type, mapping_data, output);
1388 template <
int dim,
int spacedim>
1397 Assert(dynamic_cast<const InternalData *>(&mapping_data) !=
nullptr,
1399 const InternalData &data = static_cast<const InternalData &>(mapping_data);
1401 switch (mapping_type)
1407 "update_covariant_transformation"));
1409 for (
unsigned int q = 0; q < output.size(); ++q)
1410 for (
unsigned int i = 0; i < spacedim; ++i)
1411 for (
unsigned int j = 0; j < spacedim; ++j)
1414 for (
unsigned int K = 0; K < dim; ++K)
1416 tmp[K] = data.
covariant[q][j][0] * input[q][i][0][K];
1417 for (
unsigned int J = 1; J < dim; ++J)
1418 tmp[K] += data.
covariant[q][j][J] * input[q][i][J][K];
1420 for (
unsigned int k = 0; k < spacedim; ++k)
1422 output[q][i][j][k] = data.
covariant[q][k][0] * tmp[0];
1423 for (
unsigned int K = 1; K < dim; ++K)
1424 output[q][i][j][k] += data.
covariant[q][k][K] * tmp[K];
1437 template <
int dim,
int spacedim>
1445 switch (mapping_type)
1450 internal::MappingManifoldImplementation::transform_hessians(
1451 input, mapping_type, mapping_data, output);
1459 #include "mapping_manifold.inst"
1462 DEAL_II_NAMESPACE_CLOSE